"""Manifest registry tests (ADR-0014). Each agent module exports a `MANIFEST: AgentManifest` whose id and version must agree with the agent class. The registry exposes both, and `to_dict()` must drop the `infer` callable so the wire payload is JSON-serialisable. """ from __future__ import annotations import json import os import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..")) import pytest # noqa: E402 from ml.agents.manifest import AgentManifest, InferredParam # noqa: E402 from ml.agents.registry import ( # noqa: E402 all_agents, all_manifests, get_agent, get_manifest, ) def test_every_agent_has_a_matching_manifest(): agents = {a.agent_id: a for a in all_agents()} manifests = {m.id: m for m in all_manifests()} assert agents.keys() == manifests.keys(), "agent / manifest registries diverged" for aid in agents: assert agents[aid].version == manifests[aid].version, ( f"version mismatch for {aid}: agent={agents[aid].version!r} " f"manifest={manifests[aid].version!r}" ) @pytest.mark.parametrize("agent_id", [ "overdue-task", "momentum", "time-of-day", "recent-patterns", "focus-area", ]) def test_manifest_required_fields(agent_id: str): m = get_manifest(agent_id) assert m.id == agent_id assert m.version assert m.description assert isinstance(m.pref_schema, dict) and m.pref_schema.get("type") == "object" assert isinstance(m.required_consents, list) and m.required_consents assert "data:core" in m.required_consents, "every agent should require data:core" assert m.ttl_sec == get_agent(agent_id).ttl_seconds, "ttl divergence" def test_to_dict_is_json_serialisable_and_drops_infer_callable(): m = AgentManifest( id="x", version="1.0.0", description="d", pref_schema={"type": "object"}, context_schema=[], required_consents=["data:core"], output_contract={"type": "snippet"}, ttl_sec=60, inferred_params=[InferredParam(key="k", ttl_sec=60, cold_start_default=0, min_history=10, infer=lambda h: 0)], ) payload = m.to_dict() # Round-trip through json to confirm no callables / non-JSON types leaked. data = json.loads(json.dumps(payload)) assert data["inferred_params"][0]["key"] == "k" assert "infer" not in data["inferred_params"][0] def test_get_manifest_unknown_raises(): with pytest.raises(KeyError): get_manifest("not-an-agent")