← Files Oximy Reality ChecksARCHIVED FILE
skills/did-it-land/scripts/validate_outcome.py
2.83 KB · Oct 2, 2026 · 00:34 UTC
#!/usr/bin/env python3
"""Validate a did-it-land JSON evidence ledger."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
VERDICTS = {"verified", "partial", "failed", "claimed-only", "unknown", "not-applicable"}
OVERALL = {"verified-complete", "partially-verified", "failed", "not-verifiable"}
def validate(payload: object) -> list[str]:
errors: list[str] = []
if not isinstance(payload, dict):
return ["root must be an object"]
for field in ("task", "checked_at", "overall_status", "claims"):
if field not in payload:
errors.append(f"missing root field: {field}")
if payload.get("overall_status") not in OVERALL:
errors.append(f"overall_status must be one of {sorted(OVERALL)}")
claims = payload.get("claims")
if not isinstance(claims, list) or not claims:
errors.append("claims must be a non-empty array")
return errors
for index, claim in enumerate(claims):
prefix = f"claims[{index}]"
if not isinstance(claim, dict):
errors.append(f"{prefix} must be an object")
continue
for field in ("claim", "required", "system_of_record", "verdict"):
if field not in claim:
errors.append(f"{prefix} missing {field}")
if claim.get("verdict") not in VERDICTS:
errors.append(f"{prefix}.verdict must be one of {sorted(VERDICTS)}")
if not isinstance(claim.get("required"), bool):
errors.append(f"{prefix}.required must be boolean")
evidence = claim.get("evidence", [])
gap = claim.get("evidence_gap", "")
if claim.get("verdict") == "verified" and not evidence:
errors.append(f"{prefix} is verified without evidence")
if claim.get("verdict") in {"claimed-only", "unknown"} and not gap:
errors.append(f"{prefix} needs evidence_gap for {claim.get('verdict')}")
required = [c for c in claims if isinstance(c, dict) and c.get("required")]
if payload.get("overall_status") == "verified-complete" and any(c.get("verdict") != "verified" for c in required):
errors.append("verified-complete requires every required claim to be verified")
return errors
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("report", type=Path)
args = parser.parse_args()
try:
payload = json.loads(args.report.read_text())
except (OSError, json.JSONDecodeError) as error:
print(f"validate_outcome: {error}", file=sys.stderr)
return 2
errors = validate(payload)
if errors:
print(json.dumps({"valid": False, "errors": errors}, indent=2))
return 1
print(json.dumps({"valid": True, "claims": len(payload["claims"])}, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())
SHA-256: df9c8c1b9b5f158a8a78bdfd8a918521b16282a0cf5e316dcdcc0e03afe2de9e