"""Read-only canonical KB claim routes for Argus.
These routes show the Postgres-backed claim graph that Leo uses through the
``teleo-kb`` bridge: one claim, its evidence rows, and its graph edges.
"""
from __future__ import annotations
import argparse
import json
import logging
import os
import re
import sys
from datetime import datetime, timezone
from html import escape
from pathlib import Path
from typing import Any
from aiohttp import web
from shared_ui import render_page
ROOT = Path(__file__).resolve().parent.parent
SCRIPT_DIR_CANDIDATES = [
ROOT / "scripts",
Path(os.environ.get("TELEO_INFRA_REPO_DIR", "/opt/teleo-eval/workspaces/deploy-infra")) / "scripts",
]
for scripts_dir in SCRIPT_DIR_CANDIDATES:
if str(scripts_dir) not in sys.path:
sys.path.insert(0, str(scripts_dir))
import kb_proposal_review_packet as proposal_review # noqa: E402
logger = logging.getLogger("argus.kb_claims")
KB_CLAIM_PUBLIC_PATHS = frozenset()
KB_CLAIM_PUBLIC_PREFIXES = ("/kb/claims/", "/api/kb/claims/")
KB_CLAIM_LOADER_KEY = web.AppKey("kb_claim_loader", object)
UUID_RE = re.compile(
r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
)
def is_claim_id(value: Any) -> bool:
return bool(UUID_RE.match(str(value or "")))
def claim_path(claim_id: str) -> str:
return f"/kb/claims/{claim_id}"
def claim_link_html(claim_id: Any, *, label: str | None = None) -> str:
value = str(claim_id or "")
if not is_claim_id(value):
return f"{escape(value or 'unknown')}"
text = label or value
return f'{escape(text)}'
def short_claim_link_html(claim_id: Any) -> str:
value = str(claim_id or "")
if not is_claim_id(value):
return f"{escape(value or 'unknown')}"
return claim_link_html(value, label=value[:8])
def _db_args() -> argparse.Namespace:
return argparse.Namespace(
secrets_file=os.environ.get(
"KB_CLAIM_REVIEW_SECRETS_FILE",
os.environ.get(
"KB_PROPOSAL_REVIEW_SECRETS_FILE",
os.environ.get("KB_APPLY_SECRETS_FILE", proposal_review.ap.DEFAULT_SECRETS_FILE),
),
),
container=os.environ.get("KB_CLAIM_REVIEW_CONTAINER", proposal_review.ap.DEFAULT_CONTAINER),
db=os.environ.get("KB_CLAIM_REVIEW_DB", proposal_review.ap.DEFAULT_DB),
host=os.environ.get("KB_CLAIM_REVIEW_HOST", proposal_review.ap.DEFAULT_HOST),
role=os.environ.get("KB_CLAIM_REVIEW_ROLE", proposal_review.ap.DEFAULT_ROLE),
)
def _load_claim_from_db(claim_id: str) -> dict[str, Any] | None:
password = proposal_review.ap.load_password(_db_args().secrets_file)
args = _db_args()
sql = f"""
with target as (
select c.id,
c.type,
c.text,
c.status,
c.confidence,
c.tags,
c.superseded_by,
c.created_at,
c.updated_at
from public.claims c
where c.id = {proposal_review.ap.sql_literal(claim_id)}::uuid
)
select jsonb_build_object(
'claim', jsonb_build_object(
'id', target.id::text,
'type', target.type,
'text', target.text,
'status', target.status,
'confidence', target.confidence,
'tags', coalesce(to_jsonb(target.tags), '[]'::jsonb),
'superseded_by', target.superseded_by::text,
'created_at', target.created_at::text,
'updated_at', target.updated_at::text
),
'evidence', coalesce((
select jsonb_agg(row_data order by rn)
from (
select row_number() over (
order by ce.role::text,
ce.weight desc nulls last,
s.storage_path nulls last,
s.url nulls last
) as rn,
jsonb_build_object(
'role', ce.role::text,
'weight', ce.weight,
'source_type', s.source_type,
'url', s.url,
'storage_path', s.storage_path,
'excerpt', left(coalesce(s.excerpt, ''), 1200)
) as row_data
from public.claim_evidence ce
join public.sources s on s.id = ce.source_id
where ce.claim_id = target.id
limit 30
) evidence_rows
), '[]'::jsonb),
'edges', coalesce((
select jsonb_agg(row_data order by rn)
from (
select row_number() over (
order by e.edge_type::text,
other.text
) as rn,
jsonb_build_object(
'direction', case when e.from_claim = target.id then 'outgoing' else 'incoming' end,
'edge_type', e.edge_type::text,
'connected_id', other.id::text,
'connected_text', other.text,
'connected_status', other.status,
'connected_confidence', other.confidence
) as row_data
from public.claim_edges e
join public.claims other
on other.id = case when e.from_claim = target.id then e.to_claim else e.from_claim end
where e.from_claim = target.id or e.to_claim = target.id
limit 40
) edge_rows
), '[]'::jsonb)
)::text
from target;
"""
out = proposal_review.ap.run_psql(args, sql, password).strip()
return json.loads(out) if out else None
def _load_claim(request: web.Request, claim_id: str) -> dict[str, Any] | None:
loader = request.app.get(KB_CLAIM_LOADER_KEY)
return loader(claim_id) if loader else _load_claim_from_db(claim_id)
def _metadata_table(claim: dict[str, Any]) -> str:
rows = [
("ID", claim_link_html(claim.get("id"))),
("Status", f"{escape(str(claim.get('status') or 'unknown'))}"),
("Type", f"{escape(str(claim.get('type') or 'unknown'))}"),
("Confidence", f"{escape(str(claim.get('confidence') or 'unknown'))}"),
("Tags", f"{escape(', '.join(claim.get('tags') or []) or 'none')}"),
("Created", f"{escape(str(claim.get('created_at') or 'unknown'))}"),
("Updated", f"{escape(str(claim.get('updated_at') or 'unknown'))}"),
]
if claim.get("superseded_by"):
rows.append(("Superseded by", claim_link_html(claim["superseded_by"])))
return "\n".join(f"
{escape(str(row.get('role') or 'unknown'))}{escape(str(row.get('weight') or ''))}{escape(str(row.get('source_type') or 'unknown'))}| Role | Weight | " "Source type | Source | Excerpt |
|---|
{escape(str(row.get('direction') or 'unknown'))}{escape(str(row.get('edge_type') or 'unknown'))}{escape(str(row.get('connected_status') or ''))}| Direction | Edge | " "Connected claim | Text | Status |
|---|
{escape(str(claim.get("text") or ""))}