from __future__ import annotations import copy import json import sys from pathlib import Path import pytest REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO_ROOT / "scripts")) import run_leo_local_ingestion_proposal_canary as canary # noqa: E402 def _loaded() -> tuple[dict, dict, dict]: fixture, input_receipt = canary.load_fixture(canary.DEFAULT_FIXTURE) row_ids = canary.build_row_ids(input_receipt["artifact_sha256"]) return fixture, input_receipt, row_ids def test_fixture_is_realistic_hash_bound_and_exactly_evidenced() -> None: fixture, input_receipt, row_ids = _loaded() assert fixture["extraction"]["evidence"]["body"] in fixture["source"]["body"] assert len(input_receipt["artifact_sha256"]) == 64 assert len(input_receipt["source_content_sha256"]) == 64 assert input_receipt["artifact_sha256"] != input_receipt["source_content_sha256"] assert len(set(row_ids.values())) == 4 def test_fixture_validation_fails_closed_when_evidence_is_not_in_source(tmp_path: Path) -> None: fixture = json.loads(canary.DEFAULT_FIXTURE.read_text(encoding="utf-8")) fixture["extraction"]["evidence"]["body"] = "invented evidence" path = tmp_path / "bad-fixture.json" path.write_text(json.dumps(fixture), encoding="utf-8") with pytest.raises(canary.CanaryError, match="exact substring"): canary.load_fixture(path) def test_fixture_validation_fails_closed_when_claim_body_is_not_in_source( tmp_path: Path, ) -> None: fixture = json.loads(canary.DEFAULT_FIXTURE.read_text(encoding="utf-8")) fixture["extraction"]["claim"]["body"] = "invented claim body" path = tmp_path / "bad-claim-fixture.json" path.write_text(json.dumps(fixture), encoding="utf-8") with pytest.raises(canary.CanaryError, match="claim body must be an exact substring"): canary.load_fixture(path) def test_capture_sql_escapes_quotes_and_backslashes_from_fixture( tmp_path: Path, ) -> None: fixture = json.loads(canary.DEFAULT_FIXTURE.read_text(encoding="utf-8")) fixture["source"]["title"] = "O'Brien\\review" fixture["source"]["metadata"]["note"] = "quoted ' value \\ path" path = tmp_path / "quoted-fixture.json" path.write_text(json.dumps(fixture), encoding="utf-8") loaded, input_receipt = canary.load_fixture(path) row_ids = canary.build_row_ids(input_receipt["artifact_sha256"]) sql = canary.build_capture_sql(loaded, input_receipt, row_ids) assert canary.ap.sql_literal(fixture["source"]["title"]) in sql assert canary.ap.sql_literal( json.dumps(fixture["source"]["metadata"], sort_keys=True) ) in sql def test_parent_normalizes_to_hash_bound_pending_proposal_with_embedded_row_links() -> None: fixture, input_receipt, row_ids = _loaded() parent = canary.build_parent_packet(fixture, input_receipt, row_ids) child = canary.normalized_stage.prepare_normalized_child(parent) payload = child["payload"]["apply_payload"] assert child["status"] == "pending_review" assert child["proposal_type"] == "approve_claim" assert len(payload["claims"]) == 1 assert len(payload["sources"]) == 2 assert len(payload["evidence"]) == 2 assert input_receipt["source_content_sha256"] in {row["hash"] for row in payload["sources"]} excerpts = "\n".join(row["excerpt"] for row in payload["sources"]) assert input_receipt["artifact_sha256"] in excerpts assert row_ids["source_capture_id"] in excerpts assert row_ids["claim_extraction_id"] in excerpts assert row_ids["evidence_extraction_id"] in excerpts def test_capture_and_stage_sql_never_mutate_canonical_public_tables() -> None: fixture, input_receipt, row_ids = _loaded() child = canary.normalized_stage.prepare_normalized_child( canary.build_parent_packet(fixture, input_receipt, row_ids) ) sql = "\n".join( ( canary.build_schema_sql(), canary.build_capture_sql(fixture, input_receipt, row_ids), canary.normalized_stage.build_stage_sql(child), ) ).lower() assert "insert into public." not in sql assert "update public." not in sql assert "delete from public." not in sql assert "insert into kb_canary.source_captures" in sql assert "insert into kb_canary.claim_extractions" in sql assert "insert into kb_canary.evidence_extractions" in sql assert "insert into kb_stage.kb_proposals" in sql def test_check_evaluation_requires_every_row_link_and_staging_boundary() -> None: fixture, input_receipt, row_ids = _loaded() child = canary.normalized_stage.prepare_normalized_child( canary.build_parent_packet(fixture, input_receipt, row_ids) ) apply_payload = child["payload"]["apply_payload"] readback = { "source_capture": { "id": row_ids["source_capture_id"], "artifact_sha256": input_receipt["artifact_sha256"], "content_sha256": input_receipt["source_content_sha256"], "source_identity": input_receipt["source_identity"], }, "claim_extraction": { "id": row_ids["claim_extraction_id"], "source_capture_id": row_ids["source_capture_id"], "body": fixture["extraction"]["claim"]["body"], "metadata": {"text": fixture["extraction"]["claim"]["text"]}, }, "evidence_extraction": { "id": row_ids["evidence_extraction_id"], "claim_extraction_id": row_ids["claim_extraction_id"], "source_capture_id": row_ids["source_capture_id"], "body": fixture["extraction"]["evidence"]["body"], "metadata": fixture["extraction"]["evidence"]["metadata"], }, "staged_proposal": { "id": child["id"], "status": "pending_review", "source_ref": child["source_ref"], "payload": {"apply_payload": apply_payload}, "reviewed_by_handle": None, "reviewed_at": None, "applied_by_handle": None, "applied_at": None, }, "counts": { "source_captures": 1, "claim_extractions": 1, "evidence_extractions": 1, "staged_proposals": 1, }, } checks = canary.evaluate_checks(fixture, input_receipt, row_ids, readback) assert all(checks.values()) broken = copy.deepcopy(readback) broken["evidence_extraction"]["claim_extraction_id"] = canary.stable_uuid("0" * 64, "wrong") assert ( canary.evaluate_checks(fixture, input_receipt, row_ids, broken)["evidence_links_to_claim_and_source"] is False )