#!/usr/bin/env python3 """Pipeline health check CLI runner. Exit codes: 0 = all healthy 1 = any warning 2 = any critical """ import argparse import json import sys import duckdb from config import config from health import run_checks from health.checks import check_embedding_coverage, check_llm_coverage, check_motion_freshness def main() -> int: parser = argparse.ArgumentParser(description="Check pipeline health") parser.add_argument( "--format", choices=["text", "json"], default="text", help="Output format", ) parser.add_argument( "--threshold-days", type=int, default=7, help="Max age in days for motion freshness check", ) parser.add_argument( "--min-embed-coverage", type=float, default=0.95, help="Minimum embedding coverage ratio", ) parser.add_argument( "--max-missing-llm", type=float, default=0.15, help="Maximum missing layman explanation ratio", ) args = parser.parse_args() try: conn = duckdb.connect(config.DATABASE_PATH) except Exception as e: print(f"CRITICAL: Could not connect to database: {e}", file=sys.stderr) return 2 checks = [ check_motion_freshness(conn, max_age_days=args.threshold_days), check_embedding_coverage(conn, min_coverage=args.min_embed_coverage), check_llm_coverage(conn, max_missing_ratio=args.max_missing_llm), ] report = run_checks(checks) if args.format == "json": output = { "status": report.status.value, "exit_code": report.exit_code, "checks": [ { "name": c.name, "status": c.status.value, "message": c.message, "details": c.details, } for c in report.checks ], } print(json.dumps(output, indent=2)) else: status_emoji = {"ok": "✅", "warning": "⚠️", "critical": "❌"} print(f"Health Report: {status_emoji.get(report.status.value, '?')} {report.status.value.upper()}") print("-" * 50) for check in report.checks: emoji = status_emoji.get(check.status.value, "?") print(f"{emoji} {check.name}: {check.message}") if check.details: for key, value in check.details.items(): print(f" {key}: {value}") try: conn.close() except Exception: pass return report.exit_code if __name__ == "__main__": sys.exit(main())