"""ENG-389: a parent reads a child's work off our own record instead of asking the child model to say it again. The class this closes is not a wording bug. Asking a model to restate its prior output IS a reproduction request, on a lane whose filter looks for exactly that; delegation-bearing chats block at 13.0% against a 2.7% baseline. `defuse_extraction_ask` lowers the rate and cannot close the class, because the 4th real blocked prompt was already well-worded ("Quick handoff: what project were you working on... Summarize the build plan you landed on"). The fix is that the prompt is never written.""" import json from backend.apps.agents import invoke_agent_mcp_server as inv from backend.apps.agents.core.models import AgentSession, Message from backend.apps.agents.manager.session.history_compaction import ( get_branch_messages, render_agent_trail, ) P_TOOL_NAMES = [t["name"] for t in inv.TOOLS] def p_session() -> AgentSession: s = AgentSession(id="child1", name="Build agent", status="completed") s.messages = [ Message(role="user", content="Port the exporter to the new schema", branch_id="main"), Message(role="tool_call", content={"tool": "Bash", "input": {"command": "pytest backend/tests"}}, branch_id="main"), Message(role="tool_result", content={"tool_name": "Bash", "text": "3 failed, 20 passed"}, branch_id="main"), Message(role="assistant", content="Three tests fail on the date column; I stopped there.", branch_id="main"), ] return s def test_the_tool_exists_and_is_the_one_the_description_points_at(): assert "ReadAgentWork" in P_TOOL_NAMES invoke = next(t for t in inv.TOOLS if t["name"] == "InvokeAgent") assert "ReadAgentWork" in invoke["description"], "InvokeAgent must name the read tool as the alternative" def test_invoke_agent_no_longer_teaches_the_extraction_ask(): """The tool description used to say 'query another agent about its prior work', which is the exact shape the filter refuses. A tool that teaches the bad prompt makes every wording gate downstream a losing game.""" d = next(t for t in inv.TOOLS if t["name"] == "InvokeAgent")["description"].lower() assert "query another agent about its prior work" not in d for shape in ("restate", "reproduce", "verbatim", "say it again", "repeat what"): assert shape not in d, f"InvokeAgent's description still asks a model to {shape}" def test_no_delegation_prompt_anywhere_asks_a_model_to_restate_its_output(): """The issue's acceptance criterion, as a grep with teeth. It reads the delegation sources rather than one function, because the shape only has to survive in ONE of them to keep the class alive.""" p_files = [ "backend/apps/agents/invoke_agent_mcp_server.py", "backend/apps/agents/spawn_agent_mcp_server.py", "backend/apps/agents/manager/AgentLaunch.py", ] p_bad = ("verbatim", "word for word", "word-for-word", "exactly as you", "repeat what you", "restate your", "reproduce your", "dump of your") for path in p_files: body = open(path, encoding="utf-8").read().lower() for shape in p_bad: assert shape not in body, f"{path} still carries an extraction-shaped phrase: {shape!r}" def test_the_work_it_returns_is_the_trail_we_already_store(): """Reused, not reinvented: what is safe to send another model has one definition, shared with the session recap and the workflow transcript.""" s = p_session() trail = render_agent_trail(get_branch_messages(s)) assert "Port the exporter" in trail assert "pytest backend/tests" in trail, "the tool trail is the point; it must survive" assert "3 failed, 20 passed" in trail assert "Three tests fail on the date column" in trail, "the run's own outcome must come home" def test_it_never_emits_a_role_tagged_replay(): """The shape ENG-358 removed from the recap and ENG-396 found in two more renderers. A third door for it is how the class comes back.""" trail = render_agent_trail(get_branch_messages(p_session())) for line in trail.splitlines(): assert not line.lstrip().startswith(("USER:", "ASSISTANT:", "User:", "Assistant:")) def test_a_missing_session_is_an_error_not_an_empty_success(): """A read that quietly returns nothing reads to a model as 'that agent did nothing', which is a lying status, not a missing one.""" out = inv.handle_read_agent_work({"session_id": ""}) assert out.get("isError") and "session_id is required" in out["content"][0]["text"] def test_a_session_with_no_work_says_so_rather_than_looking_empty(): inv.read_work = lambda sid: {"session_id": sid, "name": "Idle", "status": "completed", "work": ""} out = inv.handle_read_agent_work({"session_id": "x"}) assert not out.get("isError") assert "has not done any work yet" in out["content"][0]["text"] def test_read_agent_work_inherits_a_denied_invoke_policy(): """Never widen a tool surface silently: a user who denied delegation denied this too, unless they say otherwise.""" from backend.apps.agents.manager.register_builtin_mcp_servers import register_builtin_mcp_servers s = p_session() perms = {"InvokeAgent": "deny"} servers = {} register_builtin_mcp_servers(servers, s, perms, None, None) assert perms["ReadAgentWork"] == "deny" mods = servers["openswarm-core"]["env"]["OSW_MCP_MODULES"].split(",") assert "invoke" not in mods, "denying InvokeAgent must not leave the module loaded for the read tool" def test_it_is_reachable_by_default(): """The liveness half: a guard that never fires and a tool nobody can call look identical.""" from backend.apps.agents.manager.register_builtin_mcp_servers import register_builtin_mcp_servers servers = {} perms = {} register_builtin_mcp_servers(servers, p_session(), perms, None, None) assert "invoke" in servers["openswarm-core"]["env"]["OSW_MCP_MODULES"].split(",") assert perms["ReadAgentWork"] == "always_allow" def test_the_route_reads_a_session_that_is_only_on_DISK(): """The bug the packaged drill found: the route used the in-memory map alone, so it 404'd on every session the dashboard had not restored -- which is most of them, and exactly the ones worth reading. GET /sessions/{id} already had this fallback; the read tool did not.""" src = open("backend/apps/agents/agents.py", encoding="utf-8").read() i = src.index('async def get_session_work') body = src[i:src.index("@agents.router", i + 10)] assert "resume_session" in body, "a read tool that 404s on a stored session defeats its purpose" assert body.index("agent_manager.get_session") < body.index("resume_session"), \ "memory first, disk second: resuming every read would be a pointless load" def test_only_the_close_route_marks_a_session_dismissed(): """ENG-421, found on the packaged build: `closed_at` cannot mean "the user put this away", because the workflow executor stamps it at the end of every step including a stopped one. Stop and Close were therefore indistinguishable and a card the user stopped to READ vanished ~2s later. The flag belongs at the close DOOR, not in agent_manager.close_session, which the executor also calls.""" src = open("backend/apps/agents/agents.py", encoding="utf-8").read() i_close = src.index("async def close_session(") i_stop = src.index("async def stop_agent(") close_body = src[i_close:i_close + 700] stop_body = src[i_stop:i_stop + 700] assert "dismissed_by_user = True" in close_body, "Close must say the user put it away" assert "dismissed_by_user" not in stop_body, "Stop must NOT read as a dismissal" helper = open("backend/apps/agents/manager/SessionControl.py", encoding="utf-8").read() assert "dismissed_by_user" not in helper, \ "the executor calls this helper for bookkeeping; a flag here would dismiss stopped runs again"