1545 lines
61 KiB
Python
1545 lines
61 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
import re
|
|
import stat
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from ops import run_local_genesis_ledger_rebuild as genesis_rebuild
|
|
from ops import verify_teleo_v3_epistemic_contract as contract
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
|
|
|
import apply_proposal as apply # noqa: E402
|
|
import export_kb_transition_replay_material as material_exporter # noqa: E402
|
|
import kb_apply_replay_receipt as replay # noqa: E402
|
|
|
|
PREREQUISITES = REPO_ROOT / "scripts" / "kb_apply_prereqs.sql"
|
|
MIGRATION = REPO_ROOT / "ops" / "teleo_v3_epistemic_contract.sql"
|
|
WORKER = REPO_ROOT / "scripts" / "apply_worker.py"
|
|
APPLY_SCRIPT = REPO_ROOT / "scripts" / "apply_proposal.py"
|
|
MATERIAL_EXPORTER = REPO_ROOT / "scripts" / "export_kb_transition_replay_material.py"
|
|
|
|
PROPOSAL_ID = "90000000-0000-4000-8000-000000000001"
|
|
CLAIM_ID = "90000000-0000-4000-8000-000000000002"
|
|
SOURCE_ID = "90000000-0000-4000-8000-000000000003"
|
|
EVIDENCE_ID = "90000000-0000-4000-8000-000000000004"
|
|
ASSESSMENT_ID = "90000000-0000-4000-8000-000000000005"
|
|
REVIEWER_AGENT_ID = "90000000-0000-4000-8000-000000000006"
|
|
CANONICAL_REVIEWER_HANDLE = "m3taversal"
|
|
LEGACY_REVIEWER_HANDLE = "m3ta"
|
|
SUPPORT_CLAIM_ID = "90000000-0000-4000-8000-000000000007"
|
|
EDGE_ID = "90000000-0000-4000-8000-000000000008"
|
|
V2_PROPOSAL_ID = "90000000-0000-4000-8000-000000000009"
|
|
V2_REVISE_PROPOSAL_ID = "90000000-0000-4000-8000-000000000014"
|
|
MALFORMED_V3_PROPOSAL_ID = "90000000-0000-4000-8000-000000000010"
|
|
HYBRID_V3_PROPOSAL_ID = "90000000-0000-4000-8000-000000000011"
|
|
SUPPORT_ASSESSMENT_ID = "90000000-0000-4000-8000-000000000012"
|
|
SUPPORT_EVIDENCE_ID = "90000000-0000-4000-8000-000000000013"
|
|
|
|
PRESEED_IDS = {
|
|
"proposal": "91000000-0000-4000-8000-000000000001",
|
|
"claim": "91000000-0000-4000-8000-000000000002",
|
|
"source": "91000000-0000-4000-8000-000000000003",
|
|
"evidence": "91000000-0000-4000-8000-000000000004",
|
|
"assessment": "91000000-0000-4000-8000-000000000005",
|
|
"support_claim": "91000000-0000-4000-8000-000000000007",
|
|
"edge": "91000000-0000-4000-8000-000000000008",
|
|
"support_assessment": "91000000-0000-4000-8000-000000000012",
|
|
"support_evidence": "91000000-0000-4000-8000-000000000013",
|
|
}
|
|
MISMATCH_IDS = {
|
|
"proposal": "92000000-0000-4000-8000-000000000001",
|
|
"claim": "92000000-0000-4000-8000-000000000002",
|
|
"source": "92000000-0000-4000-8000-000000000003",
|
|
"evidence": "92000000-0000-4000-8000-000000000004",
|
|
"assessment": "92000000-0000-4000-8000-000000000005",
|
|
"support_claim": "92000000-0000-4000-8000-000000000007",
|
|
"edge": "92000000-0000-4000-8000-000000000008",
|
|
"support_assessment": "92000000-0000-4000-8000-000000000012",
|
|
"support_evidence": "92000000-0000-4000-8000-000000000013",
|
|
}
|
|
RACE_IDS = {
|
|
"proposal": "93000000-0000-4000-8000-000000000001",
|
|
"claim": "93000000-0000-4000-8000-000000000002",
|
|
"source": "93000000-0000-4000-8000-000000000003",
|
|
"evidence": "93000000-0000-4000-8000-000000000004",
|
|
"assessment": "93000000-0000-4000-8000-000000000005",
|
|
"support_claim": "93000000-0000-4000-8000-000000000007",
|
|
"edge": "93000000-0000-4000-8000-000000000008",
|
|
"support_assessment": "93000000-0000-4000-8000-000000000012",
|
|
"support_evidence": "93000000-0000-4000-8000-000000000013",
|
|
}
|
|
SUPERSEDED_MISMATCH_IDS = {
|
|
"proposal": "94000000-0000-4000-8000-000000000001",
|
|
"claim": "94000000-0000-4000-8000-000000000002",
|
|
"source": "94000000-0000-4000-8000-000000000003",
|
|
"evidence": "94000000-0000-4000-8000-000000000004",
|
|
"assessment": "94000000-0000-4000-8000-000000000005",
|
|
"support_claim": "94000000-0000-4000-8000-000000000007",
|
|
"edge": "94000000-0000-4000-8000-000000000008",
|
|
"support_assessment": "94000000-0000-4000-8000-000000000012",
|
|
"support_evidence": "94000000-0000-4000-8000-000000000013",
|
|
}
|
|
DEFAULT_IDS = {
|
|
"proposal": PROPOSAL_ID,
|
|
"claim": CLAIM_ID,
|
|
"source": SOURCE_ID,
|
|
"evidence": EVIDENCE_ID,
|
|
"assessment": ASSESSMENT_ID,
|
|
"support_claim": SUPPORT_CLAIM_ID,
|
|
"edge": EDGE_ID,
|
|
"support_assessment": SUPPORT_ASSESSMENT_ID,
|
|
"support_evidence": SUPPORT_EVIDENCE_ID,
|
|
}
|
|
APPLY_PASSWORD = "disposable-v3-apply-password"
|
|
REVIEW_PASSWORD = "disposable-v3-review-password"
|
|
|
|
|
|
def _role_psql(
|
|
postgres: contract.DisposablePostgres,
|
|
role: str,
|
|
password: str,
|
|
sql: str,
|
|
*,
|
|
check: bool = True,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
result = subprocess.run(
|
|
[
|
|
"docker",
|
|
"exec",
|
|
"-e",
|
|
f"PGPASSWORD={password}",
|
|
"-e",
|
|
"PGOPTIONS=-c timezone=UTC",
|
|
"-i",
|
|
postgres.name,
|
|
"psql",
|
|
"--no-psqlrc",
|
|
"--set=ON_ERROR_STOP=1",
|
|
"--set=VERBOSITY=verbose",
|
|
"--tuples-only",
|
|
"--no-align",
|
|
"--host=127.0.0.1",
|
|
f"--username={role}",
|
|
f"--dbname={contract.DATABASE}",
|
|
],
|
|
input=sql,
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
if check and result.returncode != 0:
|
|
raise AssertionError(f"psql as {role} failed:\n{result.stderr}")
|
|
return result
|
|
|
|
|
|
def _payload(ids: dict[str, str] = DEFAULT_IDS) -> dict:
|
|
content_hash = hashlib.sha256(ids["proposal"].encode("ascii")).hexdigest()
|
|
evidence = {
|
|
"id": ids["evidence"],
|
|
"claim_id": ids["claim"],
|
|
"source_id": ids["source"],
|
|
"polarity": "supports",
|
|
"excerpt": "The exact source bytes support the bounded proposition.",
|
|
"locator_json": {"section": "worker-canary", "paragraph": 1},
|
|
"source_content_hash": content_hash,
|
|
"rationale": "The exact locator directly supports the claim body.",
|
|
"created_by": contract.AGENT_ID,
|
|
}
|
|
support_evidence = {
|
|
"id": ids["support_evidence"],
|
|
"claim_id": ids["support_claim"],
|
|
"source_id": ids["source"],
|
|
"polarity": "illustrates",
|
|
"excerpt": "The exact source bytes illustrate typed receipt recovery.",
|
|
"locator_json": {"section": "worker-canary", "paragraph": 2},
|
|
"source_content_hash": content_hash,
|
|
"rationale": "The second exact locator illustrates the conceptual claim.",
|
|
"created_by": contract.AGENT_ID,
|
|
}
|
|
evidence_rows = [evidence, support_evidence]
|
|
return {
|
|
"contract_version": 3,
|
|
"agent_id": contract.AGENT_ID,
|
|
"claims": [
|
|
{
|
|
"id": ids["claim"],
|
|
"owner_agent_id": None,
|
|
"type": "empirical",
|
|
"proposition": "The V3 worker preserves an exact reviewed provenance chain.",
|
|
"body_markdown": "One content-addressed source and exact locator support this bounded claim.",
|
|
"scope": "Network-isolated disposable PostgreSQL worker canary.",
|
|
"access_scope": "collective_internal",
|
|
"status": "active",
|
|
"revision_criteria": "Revise if the source bytes, locator, or review receipt cannot be reproduced.",
|
|
"revision_kind": "original",
|
|
"supersedes_id": None,
|
|
"tags": ["v3", "worker-canary"],
|
|
"created_by": contract.AGENT_ID,
|
|
},
|
|
{
|
|
"id": ids["support_claim"],
|
|
"owner_agent_id": None,
|
|
"type": "conceptual",
|
|
"proposition": "Receipt recovery depends on canonical typed values.",
|
|
"body_markdown": "Canonical UUID and timestamp values bind replay to PostgreSQL rows.",
|
|
"scope": "Network-isolated disposable PostgreSQL worker canary.",
|
|
"access_scope": "collective_internal",
|
|
"status": "active",
|
|
"revision_criteria": "Revise if typed canonicalization is no longer deterministic.",
|
|
"revision_kind": "original",
|
|
"supersedes_id": None,
|
|
"tags": ["v3", "worker-canary"],
|
|
"created_by": contract.AGENT_ID,
|
|
},
|
|
],
|
|
"sources": [
|
|
{
|
|
"id": ids["source"],
|
|
"source_type": "paper",
|
|
"canonical_url": "https://example.test/v3-worker-canary",
|
|
"storage_uri": None,
|
|
"excerpt": "Exact disposable source bytes.",
|
|
"content_hash": content_hash,
|
|
"access_scope": "collective_internal",
|
|
"ingestion_origin": "operator_upload",
|
|
"provenance_status": "verified",
|
|
"source_class": "primary_record",
|
|
"auto_promotion_policy": "human_required",
|
|
"captured_at": "2026-07-18T14:00:00.123400+02:00",
|
|
"created_by": contract.AGENT_ID,
|
|
}
|
|
],
|
|
"evidence": evidence_rows,
|
|
"edges": [
|
|
{
|
|
"id": ids["edge"],
|
|
"from_claim": ids["support_claim"],
|
|
"to_claim": ids["claim"],
|
|
"relation_type": "supports",
|
|
"rationale": "Typed canonicalization supports deterministic receipt recovery.",
|
|
"scope_or_conditions": "The reviewed V3 apply and receipt contracts.",
|
|
"created_by": contract.AGENT_ID,
|
|
}
|
|
],
|
|
"assessments": [
|
|
{
|
|
"id": ids["assessment"],
|
|
"claim_id": ids["claim"],
|
|
"support_tier": "strong",
|
|
"challenge_tier": "none",
|
|
"overall_state": "support_dominant",
|
|
"rationale": "The exact source and locator directly support the bounded claim.",
|
|
"evidence_set_hash": apply._v3_evidence_set_hash(ids["claim"], evidence_rows),
|
|
"supersedes_assessment_id": None,
|
|
},
|
|
{
|
|
"id": ids["support_assessment"],
|
|
"claim_id": ids["support_claim"],
|
|
"support_tier": None,
|
|
"challenge_tier": None,
|
|
"overall_state": "insufficient",
|
|
"rationale": "One exact locator illustrates the conceptual support claim.",
|
|
"evidence_set_hash": apply._v3_evidence_set_hash(ids["support_claim"], evidence_rows),
|
|
"supersedes_assessment_id": None,
|
|
},
|
|
],
|
|
"reasoning_tools": [],
|
|
}
|
|
|
|
|
|
def _supplemental_bootstrap() -> str:
|
|
return f"""
|
|
alter role kb_review login password '{REVIEW_PASSWORD}';
|
|
alter role kb_apply login password '{APPLY_PASSWORD}';
|
|
|
|
create table public.strategies (
|
|
id uuid primary key,
|
|
agent_id uuid not null,
|
|
active boolean not null default true
|
|
);
|
|
create table public.strategy_nodes (id uuid primary key);
|
|
create table public.reasoning_tools (id uuid primary key);
|
|
|
|
insert into public.agents (id, handle, kind)
|
|
values ('{REVIEWER_AGENT_ID}', '{CANONICAL_REVIEWER_HANDLE}', 'human');
|
|
"""
|
|
|
|
|
|
def _packet(payload: dict, title: str) -> dict:
|
|
return {"title": title, "apply_payload": payload}
|
|
|
|
|
|
def _insert_pending_proposal(
|
|
postgres: contract.DisposablePostgres,
|
|
payload: dict,
|
|
ids: dict[str, str] = DEFAULT_IDS,
|
|
) -> dict:
|
|
title = f"V3 worker disposable canary {ids['proposal']}"
|
|
packet = _packet(payload, title)
|
|
postgres.psql(
|
|
f"""
|
|
insert into kb_stage.kb_proposals (
|
|
id, proposal_type, status, proposed_by_handle, proposed_by_agent_id,
|
|
channel, rationale, payload, created_at, updated_at
|
|
) values (
|
|
'{ids["proposal"]}'::uuid, 'approve_claim', 'pending_review', 'leo',
|
|
'{contract.AGENT_ID}'::uuid, 'disposable_worker_canary',
|
|
'Prove the exact restricted V3 worker lifecycle.',
|
|
{apply.sql_literal(json.dumps(packet, separators=(",", ":"), sort_keys=True))}::jsonb,
|
|
'2026-07-18T12:01:00+00:00', '2026-07-18T12:01:00+00:00'
|
|
);
|
|
"""
|
|
)
|
|
return packet
|
|
|
|
|
|
def _approve_proposal(
|
|
postgres: contract.DisposablePostgres,
|
|
proposal_id: str,
|
|
packet: dict,
|
|
) -> None:
|
|
approved = _role_psql(
|
|
postgres,
|
|
"kb_review",
|
|
REVIEW_PASSWORD,
|
|
f"""
|
|
select kb_stage.approve_strict_proposal(
|
|
'{proposal_id}'::uuid,
|
|
'approve_claim',
|
|
{apply.sql_literal(json.dumps(packet, separators=(",", ":"), sort_keys=True))}::jsonb,
|
|
'{CANONICAL_REVIEWER_HANDLE}',
|
|
'Approved exact V3 disposable worker packet.'
|
|
)::text;
|
|
""",
|
|
)
|
|
assert '"status": "approved"' in approved.stdout
|
|
|
|
|
|
def _insert_historical_v2_queue(postgres: contract.DisposablePostgres) -> None:
|
|
payload = {
|
|
"apply_payload": {
|
|
"from_claim": contract.LEGACY_CLAIM_ID,
|
|
"to_claim": contract.LEGACY_RELATED_CLAIM_ID,
|
|
"edge_type": "supports",
|
|
"weight": None,
|
|
}
|
|
}
|
|
revise_payload = {
|
|
"apply_payload": {
|
|
"agent_id": contract.AGENT_ID,
|
|
"strategy": {
|
|
"diagnosis": "A disabled V3 guard must never reopen V2 strategy execution.",
|
|
"guiding_policy": "Refuse catalog drift before selecting queued work.",
|
|
"proximate_objectives": ["zero V2 writes under drift"],
|
|
},
|
|
"strategy_nodes": [
|
|
{
|
|
"node_type": "policy",
|
|
"title": "Fail closed",
|
|
"body": "Keep the retained V2 packet review-visible without executing it.",
|
|
"rank": 1,
|
|
}
|
|
],
|
|
}
|
|
}
|
|
postgres.psql(
|
|
f"""
|
|
insert into kb_stage.kb_proposals (
|
|
id, proposal_type, status, proposed_by_handle, proposed_by_agent_id,
|
|
channel, rationale, payload, reviewed_by_handle, reviewed_by_agent_id,
|
|
reviewed_at, review_note, created_at, updated_at
|
|
) values (
|
|
'{V2_PROPOSAL_ID}'::uuid, 'add_edge', 'approved', 'leo',
|
|
'{contract.AGENT_ID}'::uuid, 'retained_genesis_queue',
|
|
'Historical approved V2 packet remains visible across V3 cutover.',
|
|
{apply.sql_literal(json.dumps(payload, separators=(",", ":"), sort_keys=True))}::jsonb,
|
|
'{LEGACY_REVIEWER_HANDLE}', '{REVIEWER_AGENT_ID}'::uuid, '2026-07-18T11:55:00Z',
|
|
'Retain for explicit migration or rejection.',
|
|
'2026-07-18T11:54:00Z', '2026-07-18T11:55:00Z'
|
|
);
|
|
|
|
insert into kb_stage.kb_proposals (
|
|
id, proposal_type, status, proposed_by_handle, proposed_by_agent_id,
|
|
channel, rationale, payload, reviewed_by_handle, reviewed_by_agent_id,
|
|
reviewed_at, review_note, created_at, updated_at
|
|
) values (
|
|
'{V2_REVISE_PROPOSAL_ID}'::uuid, 'revise_strategy', 'approved', 'leo',
|
|
'{contract.AGENT_ID}'::uuid, 'retained_genesis_queue',
|
|
'Historical approved V2 strategy packet remains visible across V3 cutover.',
|
|
{apply.sql_literal(json.dumps(revise_payload, separators=(",", ":"), sort_keys=True))}::jsonb,
|
|
'{LEGACY_REVIEWER_HANDLE}', '{REVIEWER_AGENT_ID}'::uuid, '2026-07-18T11:55:30Z',
|
|
'Retain for explicit migration or rejection.',
|
|
'2026-07-18T11:54:30Z', '2026-07-18T11:55:30Z'
|
|
);
|
|
"""
|
|
)
|
|
|
|
|
|
def _preseed_v3_rows(
|
|
postgres: contract.DisposablePostgres,
|
|
payload: dict,
|
|
ids: dict[str, str],
|
|
*,
|
|
mismatch_source_excerpt: bool = False,
|
|
) -> None:
|
|
bundle = apply._normalize_v3_approve_claim(payload)
|
|
source = bundle["sources"][0]
|
|
source_excerpt = "Conflicting preseeded source text." if mismatch_source_excerpt else source["excerpt"]
|
|
claim_values = ",\n".join(
|
|
f"""(
|
|
{apply.sql_literal(row["id"])}::uuid, {apply.sql_literal(row["owner_agent_id"])}::uuid,
|
|
{apply.sql_literal(row["type"])}, {apply.sql_literal(row["proposition"])},
|
|
{apply.sql_literal(row["proposition"])}, {apply.sql_literal(row["body_markdown"])},
|
|
{apply.sql_literal(row["scope"])}, {apply.sql_literal(row["access_scope"])},
|
|
{apply.sql_literal(row["status"])}, 'admitted', {apply.sql_literal(row["revision_criteria"])},
|
|
'original', null, null, {apply._text_array(row["tags"])},
|
|
{apply.sql_literal(row["created_by"])}::uuid, null, {apply.sql_literal(ids["proposal"])}::uuid,
|
|
'2026-07-18T12:03:00.654321Z', '2026-07-18T12:03:00.654321Z'
|
|
)"""
|
|
for row in bundle["claims"]
|
|
)
|
|
evidence_values = ",\n".join(
|
|
f"""(
|
|
{apply.sql_literal(row["id"])}::uuid, {apply.sql_literal(row["claim_id"])}::uuid,
|
|
{apply.sql_literal(row["source_id"])}::uuid, {apply.sql_literal(row["role"])}::evidence_role, null,
|
|
{apply.sql_literal(row["created_by"])}::uuid, {apply.sql_literal(row["excerpt"])},
|
|
{apply.sql_literal(json.dumps(row["locator_json"], separators=(",", ":"), sort_keys=True))}::jsonb,
|
|
{apply.sql_literal(row["source_content_hash"])}, {apply.sql_literal(row["rationale"])},
|
|
{apply.sql_literal(row["polarity"])}, {apply.sql_literal(ids["proposal"])}::uuid,
|
|
'2026-07-18T12:04:00.654321Z'
|
|
)"""
|
|
for row in bundle["evidence"]
|
|
)
|
|
edge = bundle["edges"][0]
|
|
assessment_values = ",\n".join(
|
|
f"""(
|
|
{apply.sql_literal(row["id"])}::uuid, {apply.sql_literal(row["claim_id"])}::uuid,
|
|
{apply.sql_literal(row["support_tier"])}, {apply.sql_literal(row["challenge_tier"])},
|
|
{apply.sql_literal(row["overall_state"])}, {apply.sql_literal(row["rationale"])},
|
|
{apply.sql_literal(row["evidence_set_hash"])}, {apply.sql_literal(ids["proposal"])}::uuid,
|
|
{apply.sql_literal(row["supersedes_assessment_id"])}::uuid, '2026-07-18T12:06:00.654321Z'
|
|
)"""
|
|
for row in bundle["assessments"]
|
|
)
|
|
postgres.psql(
|
|
f"""
|
|
insert into public.sources (
|
|
id, source_type, url, storage_path, excerpt, hash, created_by, captured_at,
|
|
canonical_url, storage_uri, content_hash, access_scope, ingestion_origin,
|
|
provenance_status, source_class, auto_promotion_policy, accepted_by_proposal_id, created_at
|
|
) values (
|
|
{apply.sql_literal(source["id"])}::uuid, {apply.sql_literal(source["source_type"])},
|
|
{apply.sql_literal(source["canonical_url"])}, {apply.sql_literal(source["storage_uri"])},
|
|
{apply.sql_literal(source_excerpt)}, {apply.sql_literal(source["content_hash"])},
|
|
{apply.sql_literal(source["created_by"])}::uuid, {apply.sql_literal(source["captured_at"])}::timestamptz,
|
|
{apply.sql_literal(source["canonical_url"])}, {apply.sql_literal(source["storage_uri"])},
|
|
{apply.sql_literal(source["content_hash"])}, {apply.sql_literal(source["access_scope"])},
|
|
{apply.sql_literal(source["ingestion_origin"])}, {apply.sql_literal(source["provenance_status"])},
|
|
{apply.sql_literal(source["source_class"])}, {apply.sql_literal(source["auto_promotion_policy"])},
|
|
{apply.sql_literal(ids["proposal"])}::uuid, '2026-07-18T12:02:00.654321Z'
|
|
);
|
|
|
|
insert into public.claims (
|
|
id, owner_agent_id, type, text, proposition, body_markdown, scope, access_scope,
|
|
status, admission_state, revision_criteria, revision_kind, supersedes_id,
|
|
confidence, tags, created_by, superseded_by, accepted_by_proposal_id, created_at, updated_at
|
|
) values
|
|
{claim_values};
|
|
|
|
insert into public.claim_evidence (
|
|
id, claim_id, source_id, role, weight, created_by, excerpt, locator_json,
|
|
source_content_hash, rationale, polarity, accepted_from_proposal_id, created_at
|
|
) values
|
|
{evidence_values};
|
|
|
|
insert into public.claim_edges (
|
|
id, from_claim, to_claim, edge_type, weight, created_by, relation_type,
|
|
rationale, scope_or_conditions, accepted_by_proposal_id, created_at
|
|
) values (
|
|
{apply.sql_literal(edge["id"])}::uuid, {apply.sql_literal(edge["from_claim"])}::uuid,
|
|
{apply.sql_literal(edge["to_claim"])}::uuid, 'supports', null,
|
|
{apply.sql_literal(edge["created_by"])}::uuid, {apply.sql_literal(edge["relation_type"])},
|
|
{apply.sql_literal(edge["rationale"])}, {apply.sql_literal(edge["scope_or_conditions"])},
|
|
{apply.sql_literal(ids["proposal"])}::uuid, '2026-07-18T12:05:00.654321Z'
|
|
);
|
|
|
|
insert into public.claim_evidence_assessments (
|
|
id, claim_id, support_tier, challenge_tier, overall_state, rationale,
|
|
evidence_set_hash, accepted_by_proposal_id, supersedes_assessment_id, created_at
|
|
) values
|
|
{assessment_values};
|
|
"""
|
|
)
|
|
|
|
|
|
def _install_v3_contract(postgres: contract.DisposablePostgres) -> None:
|
|
postgres.psql("alter role kb_apply nologin;")
|
|
postgres.apply_file(MIGRATION)
|
|
postgres.apply_file(PREREQUISITES)
|
|
|
|
|
|
def _install_spoofed_cutover_catalog(postgres: contract.DisposablePostgres) -> None:
|
|
postgres.psql(
|
|
"""
|
|
create function kb_stage.teleo_v3_enforce_apply_contract_cutover()
|
|
returns trigger language plpgsql as $function$
|
|
begin
|
|
return new;
|
|
end
|
|
$function$;
|
|
|
|
create function kb_stage.teleo_v3_spoof_cutover_target()
|
|
returns trigger language plpgsql as $function$
|
|
begin
|
|
return new;
|
|
end
|
|
$function$;
|
|
|
|
create trigger teleo_v3_00_enforce_apply_contract_cutover
|
|
before insert or update of proposal_type, payload, status on kb_stage.kb_proposals
|
|
for each row execute function kb_stage.teleo_v3_spoof_cutover_target();
|
|
"""
|
|
)
|
|
|
|
|
|
def _reduce_spoofed_cutover_to_partial_function(postgres: contract.DisposablePostgres) -> None:
|
|
postgres.psql(
|
|
"""
|
|
drop trigger teleo_v3_00_enforce_apply_contract_cutover on kb_stage.kb_proposals;
|
|
drop function kb_stage.teleo_v3_spoof_cutover_target();
|
|
"""
|
|
)
|
|
|
|
|
|
def _drop_partial_cutover_function(postgres: contract.DisposablePostgres) -> None:
|
|
postgres.psql(
|
|
"""
|
|
drop function kb_stage.teleo_v3_enforce_apply_contract_cutover();
|
|
"""
|
|
)
|
|
|
|
|
|
def _start_active_apply_session(
|
|
postgres: contract.DisposablePostgres,
|
|
) -> subprocess.Popen[str]:
|
|
assert postgres.docker is not None
|
|
holder = subprocess.Popen(
|
|
[
|
|
postgres.docker,
|
|
"exec",
|
|
"-e",
|
|
f"PGPASSWORD={APPLY_PASSWORD}",
|
|
"-e",
|
|
"PGOPTIONS=-c timezone=UTC",
|
|
"-i",
|
|
postgres.name,
|
|
"psql",
|
|
"--no-psqlrc",
|
|
"--set=ON_ERROR_STOP=1",
|
|
"--host=127.0.0.1",
|
|
"--username=kb_apply",
|
|
f"--dbname={contract.DATABASE}",
|
|
],
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
assert holder.stdin is not None
|
|
holder.stdin.write("set application_name = 'teleo_v2_active_holder'; select pg_sleep(30);\n")
|
|
holder.stdin.close()
|
|
holder.stdin = None
|
|
deadline = time.monotonic() + 8
|
|
while time.monotonic() < deadline:
|
|
active = postgres.psql_json(
|
|
"""
|
|
select jsonb_build_object(
|
|
'active', exists (
|
|
select 1 from pg_stat_activity
|
|
where application_name = 'teleo_v2_active_holder'
|
|
and usename = 'kb_apply'
|
|
and wait_event = 'PgSleep'
|
|
)
|
|
)::text;
|
|
"""
|
|
)["active"]
|
|
if active:
|
|
return holder
|
|
time.sleep(0.1)
|
|
holder.terminate()
|
|
holder.wait(timeout=3)
|
|
raise AssertionError("kb_apply session did not reach the active cutover gate")
|
|
|
|
|
|
def _terminate_active_apply_session(
|
|
postgres: contract.DisposablePostgres,
|
|
holder: subprocess.Popen[str],
|
|
) -> None:
|
|
postgres.psql(
|
|
"select pg_terminate_backend(pid) from pg_stat_activity where application_name = 'teleo_v2_active_holder';"
|
|
)
|
|
try:
|
|
holder.communicate(timeout=5)
|
|
except subprocess.TimeoutExpired:
|
|
holder.terminate()
|
|
holder.wait(timeout=3)
|
|
|
|
|
|
def _worker_command(
|
|
postgres: contract.DisposablePostgres,
|
|
secrets_file: Path,
|
|
receipt_dir: Path,
|
|
state_file: Path,
|
|
contract_version: int,
|
|
*,
|
|
apply_script: Path = APPLY_SCRIPT,
|
|
) -> list[str]:
|
|
return [
|
|
sys.executable,
|
|
str(WORKER),
|
|
"--enable",
|
|
"--contract-version",
|
|
str(contract_version),
|
|
"--max-per-tick",
|
|
"1",
|
|
"--secrets-file",
|
|
str(secrets_file),
|
|
"--failure-state-file",
|
|
str(state_file),
|
|
"--receipt-dir",
|
|
str(receipt_dir),
|
|
"--apply-script",
|
|
str(apply_script),
|
|
"--container",
|
|
postgres.name,
|
|
"--db",
|
|
contract.DATABASE,
|
|
"--host",
|
|
"127.0.0.1",
|
|
"--role",
|
|
"kb_apply",
|
|
]
|
|
|
|
|
|
def _contract_state(postgres: contract.DisposablePostgres) -> str:
|
|
return postgres.psql(apply.build_v3_contract_state_query() + ";").stdout.strip()
|
|
|
|
|
|
def _assert_invalid_contract_workers(
|
|
postgres: contract.DisposablePostgres,
|
|
secrets_file: Path,
|
|
receipt_dir: Path,
|
|
state_file: Path,
|
|
) -> None:
|
|
assert _contract_state(postgres) == "INVALID"
|
|
for contract_version in (2, 3):
|
|
worker = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, contract_version),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert worker.returncode == 1
|
|
assert "contract integrity is INVALID" in worker.stderr
|
|
assert "no candidate selection or writes attempted" in worker.stderr
|
|
|
|
|
|
def _write_catalog_race_apply_wrapper(tmp_path: Path) -> Path:
|
|
wrapper = tmp_path / "shape-drift-cutover-before-real-apply.py"
|
|
wrapper.write_text(
|
|
f"""import os
|
|
import subprocess
|
|
import sys
|
|
|
|
arguments = sys.argv[1:]
|
|
container = arguments[arguments.index("--container") + 1]
|
|
database = arguments[arguments.index("--db") + 1]
|
|
subprocess.run(
|
|
[
|
|
"docker", "exec", "-i", container, "psql", "--no-psqlrc",
|
|
"--set=ON_ERROR_STOP=1", "--username=postgres", f"--dbname={{database}}",
|
|
],
|
|
input=(
|
|
"create or replace trigger teleo_v3_00_enforce_apply_contract_cutover "
|
|
"before insert or update of proposal_type, payload, status on kb_stage.kb_proposals "
|
|
"for each row when (false) execute function "
|
|
"kb_stage.teleo_v3_enforce_apply_contract_cutover();"
|
|
),
|
|
text=True,
|
|
check=True,
|
|
)
|
|
os.execv(sys.executable, [sys.executable, {str(APPLY_SCRIPT)!r}, *arguments])
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
return wrapper
|
|
|
|
|
|
@pytest.mark.skipif(not contract.docker_available(), reason="Docker daemon is required")
|
|
def test_v3_restricted_worker_applies_once_and_retains_exact_receipt(tmp_path: Path) -> None:
|
|
postgres = contract.DisposablePostgres()
|
|
cleanup: dict = {}
|
|
try:
|
|
environment = postgres.start()
|
|
assert environment["network_mode"] == "none"
|
|
postgres.psql(contract.BOOTSTRAP_SQL)
|
|
postgres.psql(_supplemental_bootstrap())
|
|
postgres.apply_file(PREREQUISITES)
|
|
secrets_file = tmp_path / "kb-apply.env"
|
|
secrets_file.write_text(f"KB_APPLY_DB_PASSWORD={APPLY_PASSWORD}\n", encoding="utf-8")
|
|
secrets_file.chmod(0o600)
|
|
receipt_dir = tmp_path / "receipts"
|
|
state_file = tmp_path / "worker-state.json"
|
|
_insert_historical_v2_queue(postgres)
|
|
|
|
postgres.psql("alter role kb_gate_owner login inherit superuser createdb createrole replication bypassrls;")
|
|
role_drift_refusal = postgres.apply_file(MIGRATION, check=False)
|
|
assert role_drift_refusal.returncode != 0
|
|
assert "55000" in role_drift_refusal.stderr
|
|
assert "kb_gate_owner must be NOLOGIN NOINHERIT and unprivileged" in role_drift_refusal.stderr
|
|
assert postgres.psql("select to_regclass('public.claim_evidence_assessments') is null;").stdout.strip() == "t"
|
|
postgres.psql(
|
|
"alter role kb_gate_owner nologin noinherit nosuperuser nocreatedb nocreaterole noreplication nobypassrls;"
|
|
)
|
|
|
|
_install_spoofed_cutover_catalog(postgres)
|
|
for contract_version in (2, 3):
|
|
spoofed_worker = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, contract_version),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert spoofed_worker.returncode == 1
|
|
assert "contract integrity is INVALID" in spoofed_worker.stderr
|
|
assert "no candidate selection or writes attempted" in spoofed_worker.stderr
|
|
refused_cutover = postgres.apply_file(MIGRATION, check=False)
|
|
assert refused_cutover.returncode != 0
|
|
assert "55000" in refused_cutover.stderr
|
|
assert "stop the V2 worker" in refused_cutover.stderr
|
|
preinstall = postgres.psql_json(
|
|
"""
|
|
select jsonb_build_object(
|
|
'assessment_table', to_regclass('public.claim_evidence_assessments')::text,
|
|
'cutover_function', to_regprocedure('kb_stage.teleo_v3_enforce_apply_contract_cutover()')::text,
|
|
'trigger_target', (
|
|
select procedure.proname
|
|
from pg_trigger trigger_row
|
|
join pg_proc procedure on procedure.oid = trigger_row.tgfoid
|
|
where trigger_row.tgrelid = 'kb_stage.kb_proposals'::regclass
|
|
and trigger_row.tgname = 'teleo_v3_00_enforce_apply_contract_cutover'
|
|
),
|
|
'v2_status', (select status from kb_stage.kb_proposals where id =
|
|
'90000000-0000-4000-8000-000000000009'::uuid)
|
|
)::text;
|
|
"""
|
|
)
|
|
assert preinstall == {
|
|
"assessment_table": None,
|
|
"cutover_function": "kb_stage.teleo_v3_enforce_apply_contract_cutover()",
|
|
"trigger_target": "teleo_v3_spoof_cutover_target",
|
|
"v2_status": "approved",
|
|
}
|
|
_reduce_spoofed_cutover_to_partial_function(postgres)
|
|
for contract_version in (2, 3):
|
|
partial_worker = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, contract_version),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert partial_worker.returncode == 1
|
|
assert "contract integrity is INVALID" in partial_worker.stderr
|
|
_drop_partial_cutover_function(postgres)
|
|
|
|
active_holder = _start_active_apply_session(postgres)
|
|
try:
|
|
postgres.psql("alter role kb_apply nologin;")
|
|
active_refusal = postgres.apply_file(MIGRATION, check=False)
|
|
assert active_refusal.returncode != 0
|
|
assert "55000" in active_refusal.stderr
|
|
assert "active kb_apply sessions must exit" in active_refusal.stderr
|
|
assert (
|
|
postgres.psql("select to_regclass('public.claim_evidence_assessments') is null;").stdout.strip() == "t"
|
|
)
|
|
finally:
|
|
_terminate_active_apply_session(postgres, active_holder)
|
|
|
|
_install_v3_contract(postgres)
|
|
|
|
postgres.psql("alter table kb_stage.kb_proposals disable trigger teleo_v3_00_enforce_apply_contract_cutover;")
|
|
for contract_version in (2, 3):
|
|
disabled_worker = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, contract_version),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert disabled_worker.returncode == 1
|
|
assert "contract integrity is INVALID" in disabled_worker.stderr
|
|
assert (
|
|
postgres.psql(
|
|
f"select count(*) from public.strategies where agent_id = '{contract.AGENT_ID}'::uuid;"
|
|
).stdout.strip()
|
|
== "0"
|
|
)
|
|
assert (
|
|
postgres.psql(
|
|
f"select count(*) from public.claim_edges where from_claim = '{contract.LEGACY_CLAIM_ID}'::uuid "
|
|
f"and to_claim = '{contract.LEGACY_RELATED_CLAIM_ID}'::uuid and edge_type = 'supports';"
|
|
).stdout.strip()
|
|
== "0"
|
|
)
|
|
disabled_refusal = postgres.apply_file(MIGRATION, check=False)
|
|
assert disabled_refusal.returncode != 0
|
|
assert "55000" in disabled_refusal.stderr
|
|
assert "stop the V2 worker" in disabled_refusal.stderr
|
|
postgres.psql("alter role kb_apply nologin;")
|
|
postgres.apply_file(MIGRATION)
|
|
postgres.apply_file(PREREQUISITES)
|
|
restored_cutover = postgres.psql_json(
|
|
"""
|
|
select jsonb_build_object(
|
|
'enabled', trigger_row.tgenabled,
|
|
'exact_target', trigger_row.tgfoid =
|
|
'kb_stage.teleo_v3_enforce_apply_contract_cutover()'::regprocedure
|
|
)::text
|
|
from pg_trigger trigger_row
|
|
where trigger_row.tgrelid = 'kb_stage.kb_proposals'::regclass
|
|
and trigger_row.tgname = 'teleo_v3_00_enforce_apply_contract_cutover';
|
|
"""
|
|
)
|
|
assert restored_cutover == {"enabled": "O", "exact_target": True}
|
|
|
|
postgres.psql(
|
|
"""
|
|
create or replace trigger teleo_v3_00_enforce_apply_contract_cutover
|
|
before insert or update of proposal_type, payload, status on kb_stage.kb_proposals
|
|
for each row when (false)
|
|
execute function kb_stage.teleo_v3_enforce_apply_contract_cutover();
|
|
"""
|
|
)
|
|
_assert_invalid_contract_workers(postgres, secrets_file, receipt_dir, state_file)
|
|
conditional_cutover_refusal = postgres.apply_file(MIGRATION, check=False)
|
|
assert conditional_cutover_refusal.returncode != 0
|
|
assert "stop the V2 worker" in conditional_cutover_refusal.stderr
|
|
_install_v3_contract(postgres)
|
|
assert _contract_state(postgres) == "V3"
|
|
|
|
postgres.psql(
|
|
"""
|
|
create or replace trigger teleo_v3_00_enforce_apply_contract_cutover
|
|
before insert or update of status on kb_stage.kb_proposals
|
|
for each row execute function kb_stage.teleo_v3_enforce_apply_contract_cutover();
|
|
"""
|
|
)
|
|
_assert_invalid_contract_workers(postgres, secrets_file, receipt_dir, state_file)
|
|
_install_v3_contract(postgres)
|
|
assert _contract_state(postgres) == "V3"
|
|
|
|
postgres.psql(
|
|
"""
|
|
create or replace trigger teleo_v3_guard_linked_proposal_decision
|
|
before update of status on kb_stage.kb_proposals
|
|
for each row when (false)
|
|
execute function kb_stage.teleo_v3_guard_linked_proposal_decision();
|
|
"""
|
|
)
|
|
_assert_invalid_contract_workers(postgres, secrets_file, receipt_dir, state_file)
|
|
_install_v3_contract(postgres)
|
|
assert _contract_state(postgres) == "V3"
|
|
|
|
postgres.psql(
|
|
"""
|
|
drop trigger teleo_v3_00_claim_require_linked_insert on public.claims;
|
|
create trigger teleo_v3_00_claim_require_linked_insert
|
|
before update on public.sources
|
|
for each row execute function kb_stage.teleo_v3_validate_claim_edge();
|
|
"""
|
|
)
|
|
_assert_invalid_contract_workers(postgres, secrets_file, receipt_dir, state_file)
|
|
postgres.psql("alter role kb_apply nologin;")
|
|
wrong_table_migration = postgres.apply_file(MIGRATION, check=False)
|
|
assert wrong_table_migration.returncode != 0
|
|
assert "installed trigger catalog is INVALID" in wrong_table_migration.stderr
|
|
assert _contract_state(postgres) == "INVALID"
|
|
postgres.psql("drop trigger teleo_v3_00_claim_require_linked_insert on public.sources;")
|
|
postgres.apply_file(MIGRATION)
|
|
postgres.apply_file(PREREQUISITES)
|
|
assert _contract_state(postgres) == "V3"
|
|
assert (
|
|
postgres.psql(
|
|
f"select count(*) from public.strategies where agent_id = '{contract.AGENT_ID}'::uuid;"
|
|
).stdout.strip()
|
|
== "0"
|
|
)
|
|
assert (
|
|
postgres.psql(
|
|
f"select count(*) from public.claim_edges where from_claim = '{contract.LEGACY_CLAIM_ID}'::uuid "
|
|
f"and to_claim = '{contract.LEGACY_RELATED_CLAIM_ID}'::uuid and edge_type = 'supports';"
|
|
).stdout.strip()
|
|
== "0"
|
|
)
|
|
|
|
race_payload = _payload(RACE_IDS)
|
|
race_packet = _insert_pending_proposal(postgres, race_payload, RACE_IDS)
|
|
_approve_proposal(postgres, RACE_IDS["proposal"], race_packet)
|
|
|
|
postgres.psql("alter role kb_gate_owner login;")
|
|
unsafe_owner = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert unsafe_owner.returncode == 1
|
|
assert "contract integrity is INVALID" in unsafe_owner.stderr
|
|
postgres.psql("alter role kb_gate_owner nologin;")
|
|
|
|
postgres.psql("grant kb_gate_owner to kb_apply;")
|
|
membership_drift = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert membership_drift.returncode == 1
|
|
assert "contract integrity is INVALID" in membership_drift.stderr
|
|
postgres.psql("revoke kb_gate_owner from kb_apply;")
|
|
|
|
postgres.psql("grant execute on function kb_stage.teleo_v3_enforce_apply_contract_cutover() to kb_apply;")
|
|
acl_drift = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert acl_drift.returncode == 1
|
|
assert "contract integrity is INVALID" in acl_drift.stderr
|
|
postgres.psql("revoke execute on function kb_stage.teleo_v3_enforce_apply_contract_cutover() from kb_apply;")
|
|
|
|
postgres.psql("alter function kb_stage.teleo_v3_enforce_apply_contract_cutover() owner to postgres;")
|
|
function_owner_drift = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert function_owner_drift.returncode == 1
|
|
assert "contract integrity is INVALID" in function_owner_drift.stderr
|
|
postgres.psql(
|
|
"alter function kb_stage.teleo_v3_enforce_apply_contract_cutover() owner to kb_gate_owner; "
|
|
"revoke all on function kb_stage.teleo_v3_enforce_apply_contract_cutover() "
|
|
"from public, kb_apply, kb_review;"
|
|
)
|
|
|
|
postgres.psql("alter function kb_stage.teleo_v3_validate_claim_edge() owner to postgres;")
|
|
_assert_invalid_contract_workers(postgres, secrets_file, receipt_dir, state_file)
|
|
postgres.psql("alter function kb_stage.teleo_v3_validate_claim_edge() owner to kb_gate_owner;")
|
|
|
|
postgres.psql(
|
|
"""
|
|
create or replace function kb_stage.teleo_v3_guard_immutable_fields()
|
|
returns trigger
|
|
language plpgsql
|
|
security invoker
|
|
set search_path = pg_catalog, pg_temp
|
|
as $function$
|
|
begin
|
|
return new;
|
|
end
|
|
$function$;
|
|
"""
|
|
)
|
|
_assert_invalid_contract_workers(postgres, secrets_file, receipt_dir, state_file)
|
|
_install_v3_contract(postgres)
|
|
assert _contract_state(postgres) == "V3"
|
|
|
|
race_wrapper = _write_catalog_race_apply_wrapper(tmp_path)
|
|
raced_apply = subprocess.run(
|
|
_worker_command(
|
|
postgres,
|
|
secrets_file,
|
|
receipt_dir,
|
|
state_file,
|
|
3,
|
|
apply_script=race_wrapper,
|
|
),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert raced_apply.returncode == 1
|
|
assert "V3 catalog contract is INVALID" in raced_apply.stderr
|
|
assert not (receipt_dir / f"{RACE_IDS['proposal']}.json").exists()
|
|
assert postgres.psql_json(
|
|
f"""
|
|
select jsonb_build_object(
|
|
'status', (select status from kb_stage.kb_proposals where id = '{RACE_IDS["proposal"]}'::uuid),
|
|
'applied_at', (select applied_at from kb_stage.kb_proposals where id = '{RACE_IDS["proposal"]}'::uuid),
|
|
'claims', (
|
|
select count(*) from public.claims where accepted_by_proposal_id = '{RACE_IDS["proposal"]}'::uuid
|
|
),
|
|
'sources', (
|
|
select count(*) from public.sources where accepted_by_proposal_id = '{RACE_IDS["proposal"]}'::uuid
|
|
),
|
|
'evidence', (
|
|
select count(*) from public.claim_evidence where accepted_from_proposal_id = '{RACE_IDS["proposal"]}'::uuid
|
|
),
|
|
'edges', (
|
|
select count(*) from public.claim_edges where accepted_by_proposal_id = '{RACE_IDS["proposal"]}'::uuid
|
|
),
|
|
'assessments', (
|
|
select count(*) from public.claim_evidence_assessments
|
|
where accepted_by_proposal_id = '{RACE_IDS["proposal"]}'::uuid
|
|
)
|
|
)::text;
|
|
"""
|
|
) == {
|
|
"status": "approved",
|
|
"applied_at": None,
|
|
"claims": 0,
|
|
"sources": 0,
|
|
"evidence": 0,
|
|
"edges": 0,
|
|
"assessments": 0,
|
|
}
|
|
_install_v3_contract(postgres)
|
|
postgres.psql(
|
|
f"update kb_stage.kb_proposals set status = 'rejected' where id = '{RACE_IDS['proposal']}'::uuid;"
|
|
)
|
|
|
|
payload = _payload()
|
|
packet = _insert_pending_proposal(postgres, payload)
|
|
_approve_proposal(postgres, PROPOSAL_ID, packet)
|
|
material_path = tmp_path / "private-material" / "entry-0001.json"
|
|
assert not material_path.exists()
|
|
approved_snapshot = postgres.psql_json(
|
|
f"""
|
|
select jsonb_build_object(
|
|
'status', proposal.status,
|
|
'snapshot_present', approval.approved_proposal_snapshot is not null,
|
|
'snapshot_matches', approval.approved_proposal_snapshot = to_jsonb(proposal),
|
|
'snapshot_updated_at', approval.approved_proposal_snapshot->'updated_at',
|
|
'proposal_updated_at', to_jsonb(proposal)->'updated_at'
|
|
)::text
|
|
from kb_stage.kb_proposals proposal
|
|
join kb_stage.kb_proposal_approvals approval on approval.proposal_id = proposal.id
|
|
where proposal.id = '{PROPOSAL_ID}'::uuid;
|
|
"""
|
|
)
|
|
assert approved_snapshot == {
|
|
"status": "approved",
|
|
"snapshot_present": True,
|
|
"snapshot_matches": True,
|
|
"snapshot_updated_at": approved_snapshot["proposal_updated_at"],
|
|
"proposal_updated_at": approved_snapshot["proposal_updated_at"],
|
|
}
|
|
|
|
v2 = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 2),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert v2.returncode == 0, v2.stderr
|
|
assert "SKIP contract v2 execution" in v2.stderr
|
|
assert f"retained V2 proposal {V2_PROPOSAL_ID} (add_edge)" in v2.stderr
|
|
assert "remain review-visible" in v2.stderr
|
|
assert (
|
|
postgres.psql(f"select status from kb_stage.kb_proposals where id = '{PROPOSAL_ID}'::uuid;").stdout.strip()
|
|
== "approved"
|
|
)
|
|
retained_v2 = postgres.psql_json(
|
|
f"""
|
|
select jsonb_build_object(
|
|
'status', (select status from kb_stage.kb_proposals where id = '{V2_PROPOSAL_ID}'::uuid),
|
|
'revise_status', (select status from kb_stage.kb_proposals where id = '{V2_REVISE_PROPOSAL_ID}'::uuid),
|
|
'strategy_count', (select count(*) from public.strategies
|
|
where agent_id = '{contract.AGENT_ID}'::uuid),
|
|
'legacy_edge_count', (select count(*) from public.claim_edges
|
|
where from_claim = '{contract.LEGACY_CLAIM_ID}'::uuid
|
|
and to_claim = '{contract.LEGACY_RELATED_CLAIM_ID}'::uuid
|
|
and edge_type = 'supports')
|
|
)::text;
|
|
"""
|
|
)
|
|
assert retained_v2 == {
|
|
"status": "approved",
|
|
"revise_status": "approved",
|
|
"strategy_count": 0,
|
|
"legacy_edge_count": 0,
|
|
}
|
|
|
|
v3 = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert v3.returncode == 0, v3.stderr
|
|
assert f"applied {PROPOSAL_ID} (approve_claim)" in v3.stdout
|
|
|
|
receipt_path = receipt_dir / f"{PROPOSAL_ID}.json"
|
|
assert stat.S_IMODE(receipt_path.stat().st_mode) == 0o600
|
|
receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
|
|
replay.validate_replay_receipt(receipt, expected_proposal_id=PROPOSAL_ID)
|
|
assert receipt["expected_row_counts"] == {
|
|
"claims": 2,
|
|
"sources": 1,
|
|
"claim_evidence": 2,
|
|
"claim_edges": 1,
|
|
"claim_evidence_assessments": 2,
|
|
"reasoning_tools": 0,
|
|
}
|
|
assert receipt["canonical_rows"]["sources"][0]["captured_at"] == "2026-07-18T12:00:00.123400Z"
|
|
assert re.fullmatch(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z", receipt["proposal"]["reviewed_at"])
|
|
assert re.fullmatch(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z", receipt["proposal"]["applied_at"])
|
|
|
|
exported = subprocess.run(
|
|
[
|
|
sys.executable,
|
|
str(MATERIAL_EXPORTER),
|
|
PROPOSAL_ID,
|
|
"--replay-receipt",
|
|
str(receipt_path),
|
|
"--sequence",
|
|
"1",
|
|
"--output",
|
|
str(material_path),
|
|
"--secrets-file",
|
|
str(secrets_file),
|
|
"--container",
|
|
postgres.name,
|
|
"--db",
|
|
contract.DATABASE,
|
|
"--host",
|
|
"127.0.0.1",
|
|
"--role",
|
|
"kb_apply",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert exported.returncode == 0, exported.stderr
|
|
assert exported.stdout.strip() == f"replay material created: proposal={PROPOSAL_ID} sequence=1"
|
|
assert str(material_path) not in exported.stdout
|
|
assert "Private exact" not in exported.stdout
|
|
assert stat.S_IMODE(material_path.stat().st_mode) == 0o600
|
|
material = json.loads(material_path.read_text(encoding="utf-8"))
|
|
material = material_exporter.validate_material(
|
|
material,
|
|
expected_proposal_id=PROPOSAL_ID,
|
|
expected_sequence=1,
|
|
)
|
|
assert set(material) == material_exporter.MATERIAL_FIELDS
|
|
genesis_rebuild._validate_proposal_rows(
|
|
material["approved_proposal"],
|
|
material["applied_proposal"],
|
|
material["approval_snapshot"],
|
|
material["replay_receipt"]["proposal"],
|
|
)
|
|
validated_entry = genesis_rebuild._validate_entry_material(
|
|
material,
|
|
expected_sequence=1,
|
|
expected_replay_hash=material["replay_receipt"]["hashes"]["replay_material_sha256"],
|
|
material_path=material_path,
|
|
material_sha256=hashlib.sha256(material_path.read_bytes()).hexdigest(),
|
|
)
|
|
assert validated_entry.sequence == 1
|
|
assert validated_entry.applied_proposal["id"] == PROPOSAL_ID
|
|
assert material["approved_proposal"]["updated_at"] == replay.canonical_utc_timestamp(
|
|
approved_snapshot["proposal_updated_at"],
|
|
path="approved_snapshot.proposal_updated_at",
|
|
)
|
|
|
|
exported_again = subprocess.run(
|
|
[
|
|
sys.executable,
|
|
str(MATERIAL_EXPORTER),
|
|
PROPOSAL_ID,
|
|
"--replay-receipt",
|
|
str(receipt_path),
|
|
"--sequence",
|
|
"1",
|
|
"--output",
|
|
str(material_path),
|
|
"--secrets-file",
|
|
str(secrets_file),
|
|
"--container",
|
|
postgres.name,
|
|
"--db",
|
|
contract.DATABASE,
|
|
"--host",
|
|
"127.0.0.1",
|
|
"--role",
|
|
"kb_apply",
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert exported_again.returncode == 0, exported_again.stderr
|
|
assert exported_again.stdout.strip() == f"replay material unchanged: proposal={PROPOSAL_ID} sequence=1"
|
|
|
|
readback = postgres.psql_json(
|
|
f"""
|
|
select jsonb_build_object(
|
|
'proposal_status', (select status from kb_stage.kb_proposals where id = '{PROPOSAL_ID}'::uuid),
|
|
'applied_at_present', (select applied_at is not null from kb_stage.kb_proposals where id = '{PROPOSAL_ID}'::uuid),
|
|
'claims', (select count(*) from public.claims where accepted_by_proposal_id = '{PROPOSAL_ID}'::uuid),
|
|
'sources', (select count(*) from public.sources where accepted_by_proposal_id = '{PROPOSAL_ID}'::uuid),
|
|
'evidence', (select count(*) from public.claim_evidence where accepted_from_proposal_id = '{PROPOSAL_ID}'::uuid),
|
|
'edges', (select count(*) from public.claim_edges where accepted_by_proposal_id = '{PROPOSAL_ID}'::uuid),
|
|
'assessments', (select count(*) from public.claim_evidence_assessments where accepted_by_proposal_id = '{PROPOSAL_ID}'::uuid)
|
|
)::text;
|
|
"""
|
|
)
|
|
assert readback == {
|
|
"proposal_status": "applied",
|
|
"applied_at_present": True,
|
|
"claims": 2,
|
|
"sources": 1,
|
|
"evidence": 2,
|
|
"edges": 1,
|
|
"assessments": 2,
|
|
}
|
|
|
|
original_canonical_hash = receipt["hashes"]["canonical_rows_sha256"]
|
|
original_payload_hash = receipt["hashes"]["proposal_payload_sha256"]
|
|
receipt_path.unlink()
|
|
recovered = subprocess.run(
|
|
[
|
|
sys.executable,
|
|
str(APPLY_SCRIPT),
|
|
PROPOSAL_ID,
|
|
"--expected-contract-version",
|
|
"3",
|
|
"--receipt-only",
|
|
"--secrets-file",
|
|
str(secrets_file),
|
|
"--container",
|
|
postgres.name,
|
|
"--db",
|
|
contract.DATABASE,
|
|
"--host",
|
|
"127.0.0.1",
|
|
"--role",
|
|
"kb_apply",
|
|
"--receipt-out",
|
|
str(receipt_path),
|
|
],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert recovered.returncode == 0, recovered.stderr
|
|
recovered_receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
|
|
replay.validate_replay_receipt(recovered_receipt, expected_proposal_id=PROPOSAL_ID)
|
|
assert recovered_receipt["apply_engine"]["source"] == "reconstructed_current_engine"
|
|
assert recovered_receipt["hashes"]["canonical_rows_sha256"] == original_canonical_hash
|
|
assert recovered_receipt["hashes"]["proposal_payload_sha256"] == original_payload_hash
|
|
assert recovered_receipt["canonical_rows"]["sources"][0]["captured_at"] == ("2026-07-18T12:00:00.123400Z")
|
|
assert stat.S_IMODE(receipt_path.stat().st_mode) == 0o600
|
|
|
|
second = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert second.returncode == 0, second.stderr
|
|
assert "no approved+applyable contract v3 proposals" in second.stdout
|
|
|
|
postgres.psql(f"update kb_stage.kb_proposals set status = 'rejected' where id = '{V2_PROPOSAL_ID}'::uuid;")
|
|
assert (
|
|
postgres.psql(
|
|
f"select status from kb_stage.kb_proposals where id = '{V2_PROPOSAL_ID}'::uuid;"
|
|
).stdout.strip()
|
|
== "rejected"
|
|
)
|
|
|
|
malformed_insert = f"""
|
|
insert into kb_stage.kb_proposals (
|
|
id, proposal_type, status, rationale, payload, reviewed_by_handle,
|
|
reviewed_by_agent_id, reviewed_at, review_note
|
|
) values (
|
|
'{MALFORMED_V3_PROPOSAL_ID}'::uuid, 'approve_claim', 'approved',
|
|
'Malformed typed V3 contract.', '{{"apply_payload": {{"contract_version": "3"}}}}'::jsonb,
|
|
'{CANONICAL_REVIEWER_HANDLE}', '{REVIEWER_AGENT_ID}'::uuid, '2026-07-18T12:10:00Z', 'Must be refused.'
|
|
);
|
|
"""
|
|
hybrid_insert = f"""
|
|
insert into kb_stage.kb_proposals (
|
|
id, proposal_type, status, rationale, payload, reviewed_by_handle,
|
|
reviewed_by_agent_id, reviewed_at, review_note
|
|
) values (
|
|
'{HYBRID_V3_PROPOSAL_ID}'::uuid, 'add_edge', 'approved',
|
|
'Hybrid proposal type and V3 version.', '{{"apply_payload": {{"contract_version": 3}}}}'::jsonb,
|
|
'{CANONICAL_REVIEWER_HANDLE}', '{REVIEWER_AGENT_ID}'::uuid, '2026-07-18T12:11:00Z', 'Must be refused.'
|
|
);
|
|
"""
|
|
for invalid_sql in (malformed_insert, hybrid_insert):
|
|
refused = postgres.psql(invalid_sql, check=False)
|
|
assert refused.returncode != 0
|
|
assert "55000" in refused.stderr
|
|
assert "migrate or reject" in refused.stderr
|
|
|
|
postgres.psql(
|
|
"begin; set local session_replication_role = replica;\n" + malformed_insert + hybrid_insert + "commit;"
|
|
)
|
|
malformed_tick = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert malformed_tick.returncode == 0, malformed_tick.stderr
|
|
assert "no approved+applyable contract v3 proposals" in malformed_tick.stdout
|
|
assert postgres.psql_json(
|
|
f"""
|
|
select jsonb_build_object(
|
|
'malformed', (select status from kb_stage.kb_proposals where id = '{MALFORMED_V3_PROPOSAL_ID}'::uuid),
|
|
'hybrid', (select status from kb_stage.kb_proposals where id = '{HYBRID_V3_PROPOSAL_ID}'::uuid)
|
|
)::text;
|
|
"""
|
|
) == {"malformed": "approved", "hybrid": "approved"}
|
|
|
|
gate_security = postgres.psql_json(
|
|
"""
|
|
select jsonb_build_object(
|
|
'owner', owner_role.rolname,
|
|
'security_definer', procedure.prosecdef,
|
|
'search_path', procedure.proconfig,
|
|
'non_owner_execute', exists (
|
|
select 1 from aclexplode(coalesce(procedure.proacl, acldefault('f', procedure.proowner))) acl
|
|
where acl.privilege_type = 'EXECUTE' and acl.grantee <> procedure.proowner
|
|
)
|
|
)::text
|
|
from pg_proc procedure
|
|
join pg_namespace namespace on namespace.oid = procedure.pronamespace
|
|
join pg_roles owner_role on owner_role.oid = procedure.proowner
|
|
where namespace.nspname = 'kb_stage'
|
|
and procedure.proname = 'teleo_v3_require_accepted_proposal';
|
|
"""
|
|
)
|
|
assert gate_security == {
|
|
"owner": "kb_gate_owner",
|
|
"security_definer": True,
|
|
"search_path": ["search_path=pg_catalog, pg_temp"],
|
|
"non_owner_execute": False,
|
|
}
|
|
cutover_security = postgres.psql_json(
|
|
"""
|
|
select jsonb_build_object(
|
|
'owner', owner_role.rolname,
|
|
'security_definer', procedure.prosecdef,
|
|
'search_path', procedure.proconfig,
|
|
'non_owner_execute', exists (
|
|
select 1 from aclexplode(coalesce(procedure.proacl, acldefault('f', procedure.proowner))) acl
|
|
where acl.privilege_type = 'EXECUTE' and acl.grantee <> procedure.proowner
|
|
)
|
|
)::text
|
|
from pg_proc procedure
|
|
join pg_namespace namespace on namespace.oid = procedure.pronamespace
|
|
join pg_roles owner_role on owner_role.oid = procedure.proowner
|
|
where namespace.nspname = 'kb_stage'
|
|
and procedure.proname = 'teleo_v3_enforce_apply_contract_cutover';
|
|
"""
|
|
)
|
|
assert cutover_security == gate_security
|
|
|
|
rejected_delete = postgres.psql(
|
|
f"delete from public.claims where id = '{CLAIM_ID}'::uuid;",
|
|
check=False,
|
|
)
|
|
assert rejected_delete.returncode != 0
|
|
assert "55000" in rejected_delete.stderr
|
|
finally:
|
|
cleanup = postgres.cleanup()
|
|
|
|
assert cleanup["container_absent"] is True
|
|
assert cleanup["name_readback_clear"] is True
|
|
assert cleanup["instance_label_readback_clear"] is True
|
|
|
|
|
|
@pytest.mark.skipif(not contract.docker_available(), reason="Docker daemon is required")
|
|
def test_v3_worker_replays_exact_preseeded_rows_and_rejects_conflicts(tmp_path: Path) -> None:
|
|
postgres = contract.DisposablePostgres()
|
|
cleanup: dict = {}
|
|
try:
|
|
environment = postgres.start()
|
|
assert environment["network_mode"] == "none"
|
|
postgres.psql(contract.BOOTSTRAP_SQL)
|
|
postgres.psql(_supplemental_bootstrap())
|
|
postgres.apply_file(PREREQUISITES)
|
|
_install_v3_contract(postgres)
|
|
|
|
secrets_file = tmp_path / "kb-apply.env"
|
|
secrets_file.write_text(f"KB_APPLY_DB_PASSWORD={APPLY_PASSWORD}\n", encoding="utf-8")
|
|
secrets_file.chmod(0o600)
|
|
receipt_dir = tmp_path / "receipts"
|
|
state_file = tmp_path / "worker-state.json"
|
|
|
|
preseed_payload = _payload(PRESEED_IDS)
|
|
preseed_packet = _insert_pending_proposal(postgres, preseed_payload, PRESEED_IDS)
|
|
_approve_proposal(postgres, PRESEED_IDS["proposal"], preseed_packet)
|
|
_preseed_v3_rows(postgres, preseed_payload, PRESEED_IDS)
|
|
|
|
exact_replay = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert exact_replay.returncode == 0, exact_replay.stderr
|
|
assert f"applied {PRESEED_IDS['proposal']} (approve_claim)" in exact_replay.stdout
|
|
|
|
exact_receipt_path = receipt_dir / f"{PRESEED_IDS['proposal']}.json"
|
|
exact_receipt = json.loads(exact_receipt_path.read_text(encoding="utf-8"))
|
|
replay.validate_replay_receipt(exact_receipt, expected_proposal_id=PRESEED_IDS["proposal"])
|
|
assert exact_receipt["expected_row_counts"] == {
|
|
"claims": 2,
|
|
"sources": 1,
|
|
"claim_evidence": 2,
|
|
"claim_edges": 1,
|
|
"claim_evidence_assessments": 2,
|
|
"reasoning_tools": 0,
|
|
}
|
|
assert exact_receipt["canonical_rows"]["sources"][0]["created_at"] == ("2026-07-18T12:02:00.654321Z")
|
|
assert exact_receipt["canonical_rows"]["claims"][0]["created_at"] == ("2026-07-18T12:03:00.654321Z")
|
|
assert stat.S_IMODE(exact_receipt_path.stat().st_mode) == 0o600
|
|
assert (
|
|
postgres.psql(
|
|
f"select status from kb_stage.kb_proposals where id = '{PRESEED_IDS['proposal']}'::uuid;"
|
|
).stdout.strip()
|
|
== "applied"
|
|
)
|
|
|
|
no_replay = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert no_replay.returncode == 0, no_replay.stderr
|
|
assert "no approved+applyable contract v3 proposals" in no_replay.stdout
|
|
|
|
mismatch_payload = _payload(MISMATCH_IDS)
|
|
mismatch_packet = _insert_pending_proposal(postgres, mismatch_payload, MISMATCH_IDS)
|
|
_approve_proposal(postgres, MISMATCH_IDS["proposal"], mismatch_packet)
|
|
_preseed_v3_rows(
|
|
postgres,
|
|
mismatch_payload,
|
|
MISMATCH_IDS,
|
|
mismatch_source_excerpt=True,
|
|
)
|
|
|
|
conflicting_replay = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert conflicting_replay.returncode == 1
|
|
assert "source row does not match strict payload" in conflicting_replay.stderr
|
|
assert not (receipt_dir / f"{MISMATCH_IDS['proposal']}.json").exists()
|
|
mismatch_readback = postgres.psql_json(
|
|
f"""
|
|
select jsonb_build_object(
|
|
'status', (select status from kb_stage.kb_proposals where id = '{MISMATCH_IDS["proposal"]}'::uuid),
|
|
'applied_at', (select applied_at from kb_stage.kb_proposals where id = '{MISMATCH_IDS["proposal"]}'::uuid),
|
|
'source_excerpt', (select excerpt from public.sources where id = '{MISMATCH_IDS["source"]}'::uuid),
|
|
'claims', (select count(*) from public.claims where accepted_by_proposal_id = '{MISMATCH_IDS["proposal"]}'::uuid),
|
|
'sources', (select count(*) from public.sources where accepted_by_proposal_id = '{MISMATCH_IDS["proposal"]}'::uuid),
|
|
'evidence', (select count(*) from public.claim_evidence where accepted_from_proposal_id = '{MISMATCH_IDS["proposal"]}'::uuid),
|
|
'edges', (select count(*) from public.claim_edges where accepted_by_proposal_id = '{MISMATCH_IDS["proposal"]}'::uuid),
|
|
'assessments', (select count(*) from public.claim_evidence_assessments where accepted_by_proposal_id = '{MISMATCH_IDS["proposal"]}'::uuid)
|
|
)::text;
|
|
"""
|
|
)
|
|
assert mismatch_readback == {
|
|
"status": "approved",
|
|
"applied_at": None,
|
|
"source_excerpt": "Conflicting preseeded source text.",
|
|
"claims": 2,
|
|
"sources": 1,
|
|
"evidence": 2,
|
|
"edges": 1,
|
|
"assessments": 2,
|
|
}
|
|
state_file.write_text(
|
|
json.dumps({MISMATCH_IDS["proposal"]: 3}, sort_keys=True) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
superseded_payload = _payload(SUPERSEDED_MISMATCH_IDS)
|
|
superseded_packet = _insert_pending_proposal(
|
|
postgres,
|
|
superseded_payload,
|
|
SUPERSEDED_MISMATCH_IDS,
|
|
)
|
|
_approve_proposal(postgres, SUPERSEDED_MISMATCH_IDS["proposal"], superseded_packet)
|
|
_preseed_v3_rows(postgres, superseded_payload, SUPERSEDED_MISMATCH_IDS)
|
|
postgres.psql(
|
|
f"""
|
|
begin;
|
|
set local session_replication_role = replica;
|
|
update public.claims
|
|
set superseded_by = '{SUPERSEDED_MISMATCH_IDS["support_claim"]}'::uuid
|
|
where id = '{SUPERSEDED_MISMATCH_IDS["claim"]}'::uuid;
|
|
commit;
|
|
"""
|
|
)
|
|
|
|
superseded_conflict = subprocess.run(
|
|
_worker_command(postgres, secrets_file, receipt_dir, state_file, 3),
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
assert superseded_conflict.returncode == 1
|
|
assert "claim row does not match strict payload" in superseded_conflict.stderr
|
|
assert not (receipt_dir / f"{SUPERSEDED_MISMATCH_IDS['proposal']}.json").exists()
|
|
assert postgres.psql_json(
|
|
f"""
|
|
select jsonb_build_object(
|
|
'status', (select status from kb_stage.kb_proposals
|
|
where id = '{SUPERSEDED_MISMATCH_IDS["proposal"]}'::uuid),
|
|
'applied_at', (select applied_at from kb_stage.kb_proposals
|
|
where id = '{SUPERSEDED_MISMATCH_IDS["proposal"]}'::uuid),
|
|
'superseded_by', (select superseded_by from public.claims
|
|
where id = '{SUPERSEDED_MISMATCH_IDS["claim"]}'::uuid),
|
|
'claims', (select count(*) from public.claims
|
|
where accepted_by_proposal_id = '{SUPERSEDED_MISMATCH_IDS["proposal"]}'::uuid),
|
|
'sources', (select count(*) from public.sources
|
|
where accepted_by_proposal_id = '{SUPERSEDED_MISMATCH_IDS["proposal"]}'::uuid)
|
|
)::text;
|
|
"""
|
|
) == {
|
|
"status": "approved",
|
|
"applied_at": None,
|
|
"superseded_by": SUPERSEDED_MISMATCH_IDS["support_claim"],
|
|
"claims": 2,
|
|
"sources": 1,
|
|
}
|
|
assert json.loads(state_file.read_text(encoding="utf-8")) == {
|
|
MISMATCH_IDS["proposal"]: 3,
|
|
SUPERSEDED_MISMATCH_IDS["proposal"]: 1,
|
|
}
|
|
finally:
|
|
cleanup = postgres.cleanup()
|
|
|
|
assert cleanup["container_absent"] is True
|
|
assert cleanup["name_readback_clear"] is True
|
|
assert cleanup["instance_label_readback_clear"] is True
|