from backend.agents.base import AgentResult from backend.agents.runner import run_agent_pipeline def _patch_brain(monkeypatch): monkeypatch.setattr("backend.agents.runner.convert_pdf_to_images", lambda path: [{"page_number": 1, "base64": "x"}]) monkeypatch.setattr("backend.agents.runner.BrainAgent", lambda usage: type("B", (), {"run": lambda self, findings, sheet_index, jurisdiction: ([{"issue_id": "AGENT-0001", "severity": "high", "confidence": "high", "category": "note_or_spec_contradiction", "source_stage": "conflict"}], [])})()) def test_agent_runner_can_enter_review_mode(monkeypatch, tmp_path): _patch_brain(monkeypatch) pdf = tmp_path / "dummy.pdf" pdf.write_bytes(b"%PDF-1.4\n") report = run_agent_pipeline(str(pdf), out_dir=str(tmp_path), require_review=True) assert report["summary"]["agent_status"] == "needs_review" assert report["summary"]["review"]["required"] == 1 def test_review_mode_writes_memory_snapshot(monkeypatch, tmp_path): """The finalizer needs agent/memory.json for targeted clarification reruns.""" _patch_brain(monkeypatch) pdf = tmp_path / "dummy.pdf" pdf.write_bytes(b"%PDF-1.4\n") run_agent_pipeline(str(pdf), out_dir=str(tmp_path), require_review=True) assert (tmp_path / "agent" / "memory.json").is_file() def test_review_mode_summary_includes_agent_observability(monkeypatch, tmp_path): """Review-mode candidate reports must carry the same usage/stats block as the wave-7 path so finalizer fix-ups and feedback labels have real data.""" _patch_brain(monkeypatch) pdf = tmp_path / "dummy.pdf" pdf.write_bytes(b"%PDF-1.4\n") report = run_agent_pipeline(str(pdf), out_dir=str(tmp_path), require_review=True) summary = report["summary"] assert "agent_stats" in summary assert summary["by_stage"]["rfis"] == 0 assert summary["by_stage"]["validated"] == 1 assert "conflicts" in summary["by_stage"] assert "cost_usd" in summary assert "llm_calls" in summary assert "cached_calls" in summary assert "cost_by_stage" in summary assert "models_used" in summary def test_agent_runner_without_review_still_writes_rfis(monkeypatch, tmp_path): _patch_brain(monkeypatch) monkeypatch.setattr( "backend.agents.runner.RFIWriterAgent", lambda usage: type("R", (), { "name": "rfi_writer", "run": lambda self, scope: AgentResult( scope_id=scope.scope_id, artifacts=[{"issue_id": "AGENT-0001", "question": "Confirm intent?"}], ), })(), ) pdf = tmp_path / "dummy.pdf" pdf.write_bytes(b"%PDF-1.4\n") report = run_agent_pipeline(str(pdf), out_dir=str(tmp_path), require_review=False) assert report["summary"]["agent_status"] == "complete" assert "review" not in report["summary"] assert len(report["rfis"]) == 1 assert report["rfis"][0]["issue_id"] == "AGENT-0001"