teleo-infrastructure/tests/test_audit_kb_rebuild_coverage.py
2026-07-13 10:58:53 +02:00

244 lines
9.5 KiB
Python

from __future__ import annotations
import json
import re
from collections.abc import Sequence
from typing import Any
import pytest
from ops.audit_kb_rebuild_coverage import (
CommandResult,
audit_database,
build_audit_sql,
build_report,
)
def aggregate_fixture() -> dict[str, Any]:
return {
"identity": {"database": "teleo", "transaction_read_only": "on", "server_version_num": "160004"},
"canonical_counts": {"claims": 10, "sources": 8, "claim_evidence": 12, "claim_edges": 9},
"staging_counts": {
"canonical_mappings": 17,
"import_runs": 1,
"inventory_items": 20,
"staged_claims": 11,
"staged_sources": 8,
"staged_claim_sources": 13,
"staged_claim_edges": 10,
"kb_proposals": 4,
},
"mappings": {
"claims": {
"rows": 9,
"legacy_keys": 9,
"target_ids": 9,
"missing_canonical_targets": 0,
"with_first_run_staged_row": 9,
"canonical_target_rows_covered": 9,
"canonical_target_rows_unmapped": 1,
"staged_distinct_keys": 10,
"staged_distinct_keys_unmapped": 1,
},
"sources": {
"rows": 8,
"legacy_keys": 8,
"target_ids": 8,
"missing_canonical_targets": 0,
"with_first_run_staged_row": 7,
"canonical_target_rows_covered": 8,
"canonical_target_rows_unmapped": 0,
"staged_distinct_keys": 8,
"staged_distinct_keys_unmapped": 0,
},
"unsupported_target_rows": 0,
},
"claim_parity": {
"compared_fields": ["type", "text_from_title"],
"eligible_rows": 9,
"exact_projection_rows": 9,
"field_matches": {"type": 9, "text_from_title": 9},
"projection_limits": {"staged_body_nonempty": 9},
},
"source_parity": {
"compared_fields": ["source_type", "hash"],
"eligible_rows": 7,
"exact_projection_rows": 6,
"field_matches": {"source_type": 7, "hash": 6},
"projection_limits": {"staged_title_nonempty": 7},
},
"claim_evidence_reconstruction": {
"compared_fields": ["claim_id", "source_id", "role", "weight"],
"not_replayed_fields": ["created_by", "created_at"],
"staged_rows": 13,
"rows_with_mapped_claim": 12,
"rows_with_mapped_source": 13,
"rows_with_both_mapped_endpoints": 12,
"distinct_projected_rows": 11,
"projected_rows_present_in_canonical": 11,
"canonical_rows_covered": 11,
"canonical_rows_total": 12,
},
"claim_edge_reconstruction": {
"compared_fields": ["from_claim", "to_claim", "edge_type"],
"not_replayed_fields": ["id", "weight", "created_by", "created_at", "duplicate_multiplicity"],
"staged_rows": 10,
"resolution_state_resolved_rows": 9,
"resolved_rows_with_from_mapping": 9,
"resolved_rows_with_to_mapping": 8,
"resolved_rows_with_both_mapped_endpoints": 8,
"distinct_projected_rows": 8,
"projected_rows_present_in_canonical": 8,
"canonical_rows_covered": 8,
"canonical_rows_total": 9,
},
"later_and_unmapped": {
"latest_import_completed_at": "2026-01-01T00:00:00+00:00",
"canonical_created_after_latest_import": {
"claims": 1,
"sources": 0,
"claim_evidence": 1,
"claim_edges": 1,
},
"canonical_without_mapping": {"claims": 1, "sources": 0},
"canonical_relations_not_reconstructible": {"claim_evidence": 1, "claim_edges": 1},
"staged_distinct_keys_without_mapping": {"claims": 1, "sources": 0},
},
"proposal_apply_payload": {
"total_rows": 4,
"status_counts": {"applied": 2, "pending_review": 2},
"with_apply_payload_key": 2,
"with_valid_apply_payload": 2,
"applied_rows": 2,
"applied_with_valid_apply_payload": 1,
},
"import_runs": [
{
"id": "run-id",
"label": "fixture-run",
"repo_path": "/workspace",
"inventory_path": "/inventory/fixture.jsonl",
"started_at": "2026-01-01T00:00:00+00:00",
"completed_at": "2026-01-01T00:01:00+00:00",
"inventory_items": 20,
"staged_claims": 11,
"staged_sources": 8,
"staged_claim_sources": 13,
"staged_claim_edges": 10,
}
],
}
def test_sql_is_guarded_and_read_only() -> None:
sql = build_audit_sql()
assert "BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY" in sql
assert "current_setting('transaction_read_only')" in sql
assert "expected_schema_absent" in sql
assert "\\if :schema_ok" in sql
assert sql.count("ROLLBACK;") >= 2
assert not re.search(r"\b(INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|COPY)\b", sql, re.IGNORECASE)
def test_report_separates_snapshot_recovery_from_source_recompile_and_calculates_gaps() -> None:
report = build_report(aggregate_fixture(), container="teleo-test", database="teleo")
semantic = report["source_derived_recompile_readiness"]
assert report["audit_status"] == "complete"
assert report["exact_snapshot_recovery"]["verified_by_this_database_only_auditor"] is False
assert report["exact_snapshot_recovery"]["current_state_counts"]["canonical"]["claims"] == 10
assert semantic["status"] == "partial"
assert semantic["canonical_mappings"]["claims"]["canonical_coverage"] == {
"covered": 9,
"total": 10,
"gap": 1,
"percent": 90.0,
}
assert semantic["canonical_mappings"]["sources"]["first_run_stage_origin_coverage"]["percent"] == 87.5
assert semantic["claim_evidence_from_staged_claim_sources"]["canonical_reconstruction_coverage"]["percent"] == 91.67
assert semantic["claim_evidence_from_staged_claim_sources"]["not_replayed_fields"] == [
"created_by",
"created_at",
]
assert "duplicate_multiplicity" in semantic["claim_edges_from_resolved_staged_claim_edges"]["not_replayed_fields"]
assert semantic["proposal_apply_payload_coverage"]["applied_proposal_payload_coverage"]["percent"] == 50.0
gap_codes = {gap["code"] for gap in semantic["explicit_gaps"]}
assert "canonical_claims_without_mapping" in gap_codes
assert "source_mappings_without_first_run_stage" in gap_codes
assert "mapped_source_projection_mismatch" in gap_codes
assert "canonical_claim_evidence_not_reconstructible" in gap_codes
assert "canonical_claim_edges_not_reconstructible" in gap_codes
assert "applied_proposals_without_valid_apply_payload" in gap_codes
assert semantic["import_run_metadata"][0]["inventory_path"] == "/inventory/fixture.jsonl"
assert report["safety"]["contains_private_bodies_or_source_excerpts"] is False
def test_audit_uses_named_container_database_and_injected_runner() -> None:
captured: dict[str, Any] = {}
def fake_runner(command: Sequence[str], stdin: str, timeout: int) -> CommandResult:
captured.update(command=list(command), stdin=stdin, timeout=timeout)
return CommandResult(0, json.dumps(aggregate_fixture()) + "\n", "")
report = audit_database(
container="teleo-local",
database="teleo",
db_user="postgres",
timeout=45,
runner=fake_runner,
)
assert captured["command"] == [
"docker",
"exec",
"-i",
"teleo-local",
"psql",
"-X",
"-U",
"postgres",
"-d",
"teleo",
"-Atq",
"-v",
"ON_ERROR_STOP=1",
]
assert captured["timeout"] == 45
assert "READ ONLY" in captured["stdin"]
assert report["target"]["container"] == "teleo-local"
assert report["safety"]["transaction_read_only_readback"] == "on"
def test_missing_schema_fails_closed_with_structured_json() -> None:
def fake_runner(_command: Sequence[str], _stdin: str, _timeout: int) -> CommandResult:
payload = {
"status": "error",
"error": "expected_schema_absent",
"missing_relations": ["kb_stage.canonical_mappings"],
"missing_columns": ["kb_stage.canonical_mappings.legacy_key"],
}
return CommandResult(3, json.dumps(payload) + "\n", "")
report = audit_database(container="empty-postgres", database="teleo", runner=fake_runner)
assert report["audit_status"] == "error"
assert report["error"] == "expected_schema_absent"
assert report["details"]["missing_relations"] == ["kb_stage.canonical_mappings"]
assert report["details"]["missing_columns"] == ["kb_stage.canonical_mappings.legacy_key"]
assert "source_derived_recompile_readiness" not in report
def test_invalid_docker_identifier_is_rejected_before_runner() -> None:
called = False
def fake_runner(_command: Sequence[str], _stdin: str, _timeout: int) -> CommandResult:
nonlocal called
called = True
return CommandResult(0, "{}", "")
with pytest.raises(ValueError, match="container must match"):
audit_database(container="--privileged", database="teleo", runner=fake_runner)
assert called is False