"""Tests for the LangGraph-introspected pipeline topology (``agent_team.topology``).""" from __future__ import annotations from agent_team.topology import ( NODE_META, PHASE_TO_NODE, build_topology, missing_meta, node_for_phase, ) def test_every_graph_node_has_meta() -> None: """A newly added graph node must fail loudly until its NODE_META is filled in.""" assert missing_meta() == [] def test_topology_has_expected_nodes_and_trees() -> None: topo = build_topology() ids = {n["id"] for n in topo["nodes"]} # The maximal P3+ wiring nodes, derived from the real graph. assert {"intake", "clarify", "plan", "review", "build_node", "verify_node"} <= ids # __start__/__end__ are not drawn. assert "__start__" not in ids and "__end__" not in ids # intake roots the core tree; the SDLC pipeline branches off it. tree_ids = {t["id"] for t in topo["trees"]} assert {"core", "sdlc"} <= tree_ids by_id = {n["id"]: n for n in topo["nodes"]} assert by_id["intake"]["tree"] == "core" assert by_id["clarify"]["kind"] == "gate" # human gate lives at clarify # P3 nodes render but are flagged inert. assert by_id["build_node"]["gated"] is True def test_edges_classified_spine_branch_loopback() -> None: topo = build_topology() kinds = {(e["from"], e["to"]): e["kind"] for e in topo["edges"]} assert kinds[("intake", "clarify")] == "spine" assert kinds[("clarify", "plan")] == "spine" # review -> plan is the revise loop; verify -> build_node is the build loop. assert kinds[("review", "plan")] == "loopback" assert kinds[("verify_node", "build_node")] == "loopback" # No edge references the framework terminals. nodes = {n["id"] for n in topo["nodes"]} for e in topo["edges"]: assert e["from"] in nodes and e["to"] in nodes def test_phase_to_node_mapping() -> None: assert node_for_phase("build") == "build_node" assert node_for_phase("verify") == "verify_node" assert node_for_phase("clarify") == "clarify" # Terminal/exception phases map to no node. assert node_for_phase("done") is None assert node_for_phase("parked") is None assert node_for_phase("") is None # Every mapped target is a real meta node. for node_id in PHASE_TO_NODE.values(): assert node_id in NODE_META