avoigt1121
feat: governed ToolUniverse core for the knowledge specialist (s1)
377417d
Raw History Blame Contribute Delete
5.11 kB
"""Payload assembly — every answer this Space returns goes through here.
The contract (ADR-0001 §5, accepted 2026-10-20), on top of the family invariants:
- Every payload is a dict with ``status`` in {"ok", "refused", "error", "denied"} plus a
human-readable ``reason`` on every non-ok status. Refusals are answers, never exceptions.
- Every payload except a denial carries a ``run_id`` (the gate mints none for a caller it
turned away).
- Every ``ok`` payload carries ``kind: "annotation"`` and **no** ``hierarchy`` or
``n_for_inference``. This is the deliberate break from the data specialists: a row count here
is not a sample size, and nothing downstream may render it as one.
- Every row carries a complete ``provenance`` block (:mod:`src.provenance`); :func:`ok` refuses to
build a payload around a row that does not.
- ``coverage_notes`` and ``attribution`` come from config for every source the payload used, and
the deterministic ``narrative`` says "according to <source> (queried <date>)".
"""
from __future__ import annotations
import datetime
import json
import secrets
from collections.abc import Iterable
from typing import Any
from src import config
from src.provenance import missing_fields
STATUSES = ("ok", "refused", "error", "denied")
SOURCE_ERROR_REASONS = ("source_unavailable", "rate_limited", "upstream_schema_drift")
KIND = "annotation"
DISCLAIMER = (
"External annotation, not analysis: these rows are what the named public sources say, "
"as of the query date on each row. Nothing here was computed from a dataset, and no "
"statistic was run."
)
def mint_run_id() -> str:
"""A sortable, collision-resistant run id (sibling-agent format)."""
stamp = datetime.datetime.now(datetime.UTC).strftime("%Y%m%d_%H%M%S")
return f"{stamp}_{secrets.randbelow(10**6):06d}"
def source_error(source: str, reason: str, detail: str) -> dict[str, str]:
if reason not in SOURCE_ERROR_REASONS:
raise ValueError(f"source error reason must be one of {SOURCE_ERROR_REASONS}")
return {"source": source, "reason": reason, "detail": detail}
def _attribution(source_ids: Iterable[str]) -> list[dict[str, str]]:
out = []
for sid in sorted(set(source_ids)):
src = config.source(sid)
out.append(
{
"source": sid,
"name": src["name"],
"citation": src["citation"],
"licence": src["licence"],
"licence_url": src["licence_url"],
}
)
return out
def _coverage_notes(source_ids: Iterable[str]) -> list[dict[str, str]]:
return [
{"source": sid, "note": note}
for sid in sorted(set(source_ids))
for note in config.source(sid)["coverage_notes"]
]
def ok(
endpoint: str,
*,
query: dict[str, Any],
rows: list[dict[str, Any]],
sources_used: Iterable[str],
narrative: str,
unresolved: Iterable[dict[str, str]] = (),
source_errors: Iterable[dict[str, str]] = (),
run_id: str | None = None,
**extra: Any,
) -> dict[str, Any]:
"""An ok payload. Raises ValueError (a programming error) on an unstamped row."""
for i, row in enumerate(rows):
gaps = missing_fields(row)
if gaps:
raise ValueError(f"row {i} is missing provenance fields {gaps}")
if not narrative.strip():
raise ValueError("an ok payload needs its deterministic narrative")
used = list(sources_used)
forbidden = {"hierarchy", "n_for_inference"} & set(extra)
if forbidden:
raise ValueError(f"annotation payloads never carry {sorted(forbidden)}")
payload: dict[str, Any] = {
"status": "ok",
"run_id": run_id or mint_run_id(),
"kind": KIND,
"endpoint": endpoint,
"query": query,
"rows": rows,
"unresolved": list(unresolved),
"source_errors": list(source_errors),
"coverage_notes": _coverage_notes(used),
"attribution": _attribution(used),
"narrative": narrative,
"disclaimer": DISCLAIMER,
}
payload.update(extra)
return payload
def refused(endpoint: str, reason: str, message: str, *, run_id: str | None = None) -> dict:
return {
"status": "refused",
"run_id": run_id or mint_run_id(),
"endpoint": endpoint,
"reason": reason,
"message": message,
}
def error(
endpoint: str,
reason: str,
message: str,
*,
source_errors: Iterable[dict[str, str]] = (),
run_id: str | None = None,
) -> dict:
return {
"status": "error",
"run_id": run_id or mint_run_id(),
"endpoint": endpoint,
"reason": reason,
"message": message,
"source_errors": list(source_errors),
}
def denied(message: str) -> dict:
return {"status": "denied", "reason": "access_denied", "message": message}
def to_json(payload: dict[str, Any]) -> str:
if payload.get("status") not in STATUSES:
raise ValueError(f"unknown status {payload.get('status')!r}")
return json.dumps(payload, ensure_ascii=False)