#!/usr/bin/env python3 """Probe read-only Argus KB diagnostics for current approved-proposal state.""" from __future__ import annotations import argparse import base64 import json import urllib.error import urllib.request from datetime import datetime, timezone from pathlib import Path from typing import Any, Callable from urllib.parse import urljoin DEFAULT_BASE_URL = "http://77.42.65.182:8081" REPORT_DIR = Path("docs/reports/leo-working-state-20260709") DEFAULT_OUT = REPORT_DIR / "argus-kb-state-current.json" DEFAULT_MARKDOWN_OUT = REPORT_DIR / "argus-kb-state-current.md" FetchJson = Callable[[str, int], dict[str, Any]] def fetch_json(url: str, timeout: int) -> dict[str, Any]: request = urllib.request.Request(url, headers={"Accept": "application/json"}) try: with urllib.request.urlopen(request, timeout=timeout) as response: # noqa: S310 - operator-supplied URL return json.loads(response.read().decode("utf-8")) except (urllib.error.URLError, TimeoutError, json.JSONDecodeError) as exc: return {"_fetch_error": str(exc)} def endpoint(base_url: str, path: str) -> str: return urljoin(base_url.rstrip("/") + "/", path.lstrip("/")) def decode_supplied_json(value: str | None) -> dict[str, Any] | None: if not value: return None try: return json.loads(base64.b64decode(value, validate=True).decode("utf-8")) except Exception as exc: # noqa: BLE001 - retained as a structured fetch error return {"_fetch_error": f"failed to parse supplied base64 JSON: {exc}"} def supplied_payloads(args: argparse.Namespace) -> dict[str, dict[str, Any] | None]: return { "kb_proposals": decode_supplied_json(args.kb_proposals_json_base64), "vital_signs": decode_supplied_json(args.vital_signs_json_base64), "metrics": decode_supplied_json(args.metrics_json_base64), } def proposal_summary(kb_proposals: dict[str, Any]) -> dict[str, Any]: packets = kb_proposals.get("packets") if isinstance(kb_proposals.get("packets"), list) else [] return { "generated_at": kb_proposals.get("generated_at"), "filters": kb_proposals.get("filters"), "total": kb_proposals.get("total"), "status_counts": kb_proposals.get("status_counts") or {}, "review_state_counts": kb_proposals.get("review_state_counts") or {}, "worker_applyable_count": kb_proposals.get("worker_applyable_count"), "read_only": kb_proposals.get("read_only"), "proposal_ids": [packet.get("proposal_id") for packet in packets], "proposal_review_states": { packet.get("proposal_id"): packet.get("review_state") for packet in packets if packet.get("proposal_id") }, "proposal_applyability": { packet.get("proposal_id"): { "worker_applyable": packet.get("worker_applyable"), "has_apply_payload": packet.get("has_apply_payload"), "next_admin_action": packet.get("next_admin_action"), } for packet in packets if packet.get("proposal_id") }, } def collect(args: argparse.Namespace, *, fetcher: FetchJson = fetch_json) -> dict[str, Any]: urls = { "kb_proposals": endpoint(args.base_url, "/api/kb-proposals"), "vital_signs": endpoint(args.base_url, "/api/vital-signs"), "metrics": endpoint(args.base_url, "/api/metrics"), } supplied = supplied_payloads(args) raw = {name: payload if payload is not None else fetcher(urls[name], args.timeout) for name, payload in supplied.items()} fetch_sources = {name: "supplied_base64_json" if payload is not None else "urllib" for name, payload in supplied.items()} proposals = proposal_summary(raw["kb_proposals"]) proposal_total = proposals.get("total") review_state_counts = proposals.get("review_state_counts") or {} status_counts = proposals.get("status_counts") or {} checks = { "http_readback_ok": all("_fetch_error" not in payload for payload in raw.values()), "approved_proposals_visible": isinstance(proposal_total, int) and proposal_total > 0 and status_counts.get("approved") == proposal_total, "approved_need_apply_payload": isinstance(proposal_total, int) and review_state_counts.get("approved_needs_apply_payload") == proposal_total, "no_worker_applyable_approved_proposals": proposals.get("worker_applyable_count") == 0, "kb_proposals_endpoint_read_only": proposals.get("read_only") is True, } return { "generated_at_utc": datetime.now(timezone.utc).isoformat(), "mode": "argus_kb_state_readonly_http_probe", "base_url": args.base_url, "urls": urls, "fetch_sources": fetch_sources, "status": "pass" if all(checks.values()) else "fail", "checks": checks, "summary": { "proposals": proposals, "vital_signs": { "claim_index_status": raw["vital_signs"].get("claim_index_status"), "review_throughput": raw["vital_signs"].get("review_throughput"), "funnel": raw["vital_signs"].get("funnel"), "queue_staleness": raw["vital_signs"].get("queue_staleness"), }, "metrics": { "status_map": raw["metrics"].get("status_map"), "source_map": raw["metrics"].get("source_map"), "breakers": raw["metrics"].get("breakers"), }, }, "raw": raw, "claim_ceiling": ( "This is public Argus HTTP diagnostics evidence only. It proves the diagnostics surface can see " "approved KB proposals and their applyability state; it does not prove Docker/Postgres row counts, " "gateway systemd state, Telegram-visible reply quality, or production apply execution." ), } def write_json(path: Path, data: dict[str, Any]) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8") def write_markdown(path: Path, data: dict[str, Any]) -> None: proposals = data["summary"]["proposals"] lines = [ "# Argus KB State Probe", "", f"Generated UTC: `{data['generated_at_utc']}`", f"Mode: `{data['mode']}`", f"Status: `{data['status']}`", f"Base URL: `{data['base_url']}`", "", "## Fetch Sources", "", ] lines.extend(f"- `{key}`: `{value}`" for key, value in sorted(data["fetch_sources"].items())) lines.extend( [ "", "## Checks", "", ] ) lines.extend(f"- `{key}`: `{value}`" for key, value in sorted(data["checks"].items())) lines.extend( [ "", "## Approved Proposal State", "", f"- Total: `{proposals.get('total')}`", f"- Status counts: `{json.dumps(proposals.get('status_counts'), sort_keys=True)}`", f"- Review state counts: `{json.dumps(proposals.get('review_state_counts'), sort_keys=True)}`", f"- Worker-applyable count: `{proposals.get('worker_applyable_count')}`", f"- Read-only endpoint: `{proposals.get('read_only')}`", "", "## Proposal IDs", "", ] ) lines.extend(f"- `{proposal_id}`" for proposal_id in proposals.get("proposal_ids") or []) lines.extend(["", "## Claim Ceiling", "", data["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("--base-url", default=DEFAULT_BASE_URL) parser.add_argument("--timeout", type=int, default=10) parser.add_argument("--kb-proposals-json-base64") parser.add_argument("--vital-signs-json-base64") parser.add_argument("--metrics-json-base64") 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) data = collect(args) write_json(args.out, data) write_markdown(args.markdown_out, data) print( json.dumps( { "out": str(args.out), "markdown_out": str(args.markdown_out), "status": data["status"], "checks": data["checks"], }, indent=2, sort_keys=True, ) ) return 0 if data["status"] == "pass" else 2 if __name__ == "__main__": raise SystemExit(main())