teleo-infrastructure/scripts/validate_working_leo_production_receipt.py
twentyOne2x 0e2c37e8fa
Some checks are pending
CI / lint-and-test (push) Waiting to run
Validate Leo production apply receipts
2026-07-10 03:26:18 +02:00

271 lines
11 KiB
Python

#!/usr/bin/env python3
"""Validate a Working Leo production-apply receipt.
This validator is intentionally offline. It reads the retained authorized apply
runbook plus a receipt JSON file and checks that the receipt proves the
post-apply state expected by the runbook. It never opens a database connection,
never runs SQL, and never posts to Telegram.
"""
from __future__ import annotations
import argparse
import json
import re
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
REPORT_DIR = Path("docs/reports/leo-working-state-20260709")
DEFAULT_RUNBOOK = REPORT_DIR / "working-leo-authorized-apply-runbook-current.json"
DEFAULT_RECEIPT = REPORT_DIR / "working-leo-production-apply-receipt-current.json"
DEFAULT_OUT = REPORT_DIR / "working-leo-production-apply-receipt-validation-current.json"
DEFAULT_MARKDOWN_OUT = REPORT_DIR / "working-leo-production-apply-receipt-validation-current.md"
EMPTY_PLACEHOLDERS = {"", "todo", "tbd", "n/a", "none", "null", "placeholder"}
def _load_json(path: Path) -> dict[str, Any]:
return json.loads(path.read_text(encoding="utf-8"))
def _is_nonempty(value: Any) -> bool:
if value is None:
return False
if isinstance(value, str):
return value.strip().lower() not in EMPTY_PLACEHOLDERS
if isinstance(value, dict | list):
return bool(value)
return True
def _as_list(value: Any) -> list[Any]:
if isinstance(value, list):
return value
if value is None:
return []
return [value]
def _resolve(path: str, *, repo_root: Path) -> Path:
candidate = Path(path)
return candidate if candidate.is_absolute() else repo_root / candidate
def _paths_exist(receipt: dict[str, Any], field: str, *, repo_root: Path) -> tuple[bool, list[str]]:
values = _as_list(receipt.get(field))
missing = [str(value) for value in values if not _resolve(str(value), repo_root=repo_root).exists()]
return bool(values) and not missing, missing
def _counts_match(expected: dict[str, Any], actual: Any) -> bool:
if not isinstance(actual, dict):
return False
try:
normalized_actual = {str(key): int(value) for key, value in actual.items()}
normalized_expected = {str(key): int(value) for key, value in expected.items()}
except (TypeError, ValueError):
return False
return normalized_actual == normalized_expected
def _direct_claim_score_passes(path_value: Any, *, repo_root: Path) -> tuple[bool, str]:
values = _as_list(path_value)
if not values:
return False, "missing direct_claim_score_path"
path = _resolve(str(values[0]), repo_root=repo_root)
if not path.exists():
return False, f"missing direct claim score artifact: {path}"
text = path.read_text(encoding="utf-8")
if path.suffix == ".json":
data = json.loads(text)
score = data.get("score", {})
if score.get("pass") is True and score.get("passes") == score.get("expected_prompt_count") == 6:
return True, "json score pass"
return False, "json score is not 6/6 pass"
if "Overall pass for scored coverage: `True`" in text and "Prompts scored: `6/6`" in text:
return True, "markdown score pass"
return False, "score artifact does not show 6/6 pass"
def _service_readback_ok(value: Any) -> bool:
if not isinstance(value, dict):
return False
return (
value.get("ActiveState") == "active"
and value.get("SubState") == "running"
and _is_nonempty(value.get("MainPID"))
and _is_nonempty(value.get("NRestarts"))
)
def _cleanup_readback_ok(value: Any) -> bool:
if not isinstance(value, dict):
return False
checks = value.get("checks") if isinstance(value.get("checks"), dict) else value
leftovers = checks.get("leftover_rehearsal_clone_or_staging_databases", [])
return checks.get("cleanup_ok") is True and leftovers == []
def validate_receipt(receipt_path: Path, runbook_path: Path = DEFAULT_RUNBOOK, *, repo_root: Path = Path(".")) -> dict[str, Any]:
repo_root = repo_root.resolve()
runbook = _load_json(runbook_path)
required_fields = list(runbook["production_apply_receipt_required_fields"])
expected_counts = dict(runbook["expected_after_apply_counts"])
if not receipt_path.exists():
return {
"generated_at_utc": datetime.now(timezone.utc).isoformat(),
"status": "missing_receipt",
"valid": False,
"receipt_path": str(receipt_path),
"runbook_path": str(runbook_path),
"missing_fields": required_fields,
"errors": [f"receipt file does not exist: {receipt_path}"],
"claim_ceiling": "No production apply receipt was validated.",
}
receipt = _load_json(receipt_path)
missing_fields = [field for field in required_fields if field not in receipt]
errors: list[str] = []
warnings: list[str] = []
checks: dict[str, bool] = {}
checks["all_required_fields_present"] = not missing_fields
if missing_fields:
errors.append(f"missing required fields: {', '.join(missing_fields)}")
for field in ("explicit_authorization_record", "operator_identity", "git_commit_sha"):
checks[f"{field}_present"] = _is_nonempty(receipt.get(field))
if not checks[f"{field}_present"]:
errors.append(f"{field} is missing or placeholder")
git_sha = str(receipt.get("git_commit_sha", ""))
checks["git_commit_sha_shape"] = bool(re.fullmatch(r"[0-9a-f]{7,40}", git_sha))
if not checks["git_commit_sha_shape"]:
errors.append("git_commit_sha must be a 7-40 char lowercase hex SHA")
authorization = receipt.get("explicit_authorization_record")
checks["authorization_record_not_false"] = not (
isinstance(authorization, dict) and authorization.get("authorized") is False
)
if not checks["authorization_record_not_false"]:
errors.append("explicit_authorization_record explicitly says authorized=false")
for field in (
"preflight_output_paths",
"apply_output_paths",
"postflight_output_paths",
"telegram_or_handler_regression_paths",
"rollback_packet_paths",
):
ok, missing = _paths_exist(receipt, field, repo_root=repo_root)
checks[f"{field}_exist"] = ok
if missing:
errors.append(f"{field} contains missing path(s): {', '.join(missing)}")
elif not _as_list(receipt.get(field)):
errors.append(f"{field} must be a non-empty path list")
checks["expected_counts_match_runbook"] = _counts_match(expected_counts, receipt.get("expected_after_apply_counts"))
if not checks["expected_counts_match_runbook"]:
errors.append("expected_after_apply_counts does not match the authorized runbook")
checks["actual_counts_match_expected"] = _counts_match(expected_counts, receipt.get("actual_after_apply_counts"))
if not checks["actual_counts_match_expected"]:
errors.append("actual_after_apply_counts does not match the authorized runbook expected counts")
score_ok, score_note = _direct_claim_score_passes(receipt.get("direct_claim_score_path"), repo_root=repo_root)
checks["direct_claim_score_passes"] = score_ok
if not score_ok:
errors.append(score_note)
checks["service_readback_ok"] = _service_readback_ok(receipt.get("service_readback"))
if not checks["service_readback_ok"]:
errors.append("service_readback must show active/running service with MainPID and NRestarts")
checks["cleanup_readback_ok"] = _cleanup_readback_ok(receipt.get("cleanup_readback"))
if not checks["cleanup_readback_ok"]:
errors.append("cleanup_readback must show cleanup_ok=true and no rehearsal/clone/staging DB leftovers")
checks["known_residual_risks_list"] = isinstance(receipt.get("known_residual_risks"), list)
if not checks["known_residual_risks_list"]:
errors.append("known_residual_risks must be a list")
elif not receipt["known_residual_risks"]:
warnings.append("known_residual_risks is empty; verify that this is intentional")
valid = all(checks.values()) and not errors
return {
"generated_at_utc": datetime.now(timezone.utc).isoformat(),
"status": "valid" if valid else "invalid",
"valid": valid,
"receipt_path": str(receipt_path),
"runbook_path": str(runbook_path),
"checks": checks,
"missing_fields": missing_fields,
"errors": errors,
"warnings": warnings,
"claim_ceiling": (
"This validates a retained production-apply receipt against the authorized runbook. It does not run SQL, "
"does not mutate production, and does not create authorization."
),
}
def write_markdown(path: Path, result: dict[str, Any]) -> None:
lines = [
"# Working Leo Production Apply Receipt Validation",
"",
f"Generated UTC: `{result['generated_at_utc']}`",
f"Status: `{result['status']}`",
f"Valid: `{result['valid']}`",
f"Receipt: `{result['receipt_path']}`",
f"Runbook: `{result['runbook_path']}`",
"",
"## Checks",
"",
]
for key, value in sorted(result.get("checks", {}).items()):
lines.append(f"- `{key}`: `{value}`")
lines.extend(["", "## Errors", ""])
errors = result.get("errors", [])
lines.extend(f"- {item}" for item in errors) if errors else lines.append("- none")
lines.extend(["", "## Warnings", ""])
warnings = result.get("warnings", [])
lines.extend(f"- {item}" for item in warnings) if warnings else lines.append("- none")
lines.extend(["", "## Claim Ceiling", "", result["claim_ceiling"], ""])
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("\n".join(lines), encoding="utf-8")
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--receipt", type=Path, default=DEFAULT_RECEIPT)
parser.add_argument("--runbook", type=Path, default=DEFAULT_RUNBOOK)
parser.add_argument("--out", type=Path, default=DEFAULT_OUT)
parser.add_argument("--markdown-out", type=Path, default=DEFAULT_MARKDOWN_OUT)
return parser.parse_args(argv)
def main(argv: list[str] | None = None) -> int:
args = parse_args(argv)
result = validate_receipt(args.receipt, args.runbook)
args.out.parent.mkdir(parents=True, exist_ok=True)
args.out.write_text(json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8")
write_markdown(args.markdown_out, result)
print(
json.dumps(
{
"out": str(args.out),
"markdown_out": str(args.markdown_out),
"status": result["status"],
"valid": result["valid"],
},
indent=2,
sort_keys=True,
)
)
return 0 if result["valid"] else 1
if __name__ == "__main__":
raise SystemExit(main())