from __future__ import annotations from pathlib import Path from beaver.engine.session import SessionManager from beaver.memory.runs import RunMemoryStore, RunRecord from beaver.services.process_service import SessionProcessProjector def test_process_projection_maps_task_team_events(tmp_path: Path) -> None: session = SessionManager(tmp_path) run_store = RunMemoryStore(tmp_path / "memory" / "runs") run_store.append_run_record( RunRecord( run_id="sub-run", session_id="sub-session", task_id="task-1", attempt_index=1, task_text="sub task", started_at="2026-01-01T00:00:01+00:00", ended_at="2026-01-01T00:00:02+00:00", success=True, finish_reason="stop", ) ) run_store.append_run_record( RunRecord( run_id="main-run", session_id="web:test", task_id="task-1", attempt_index=1, task_text="main task", started_at="2026-01-01T00:00:03+00:00", ended_at="2026-01-01T00:00:04+00:00", success=True, finish_reason="stop", ) ) session.append_message( "web:test", role="system", event_type="task_execution_planned", event_payload={ "task_id": "task-1", "attempt_index": 1, "plan_mode": "team", "strategy": "sequence", "node_ids": ["research"], "skill_queries": ["research workflow"], "selected_skill_names": ["research-workflow"], "skill_resolution_report": [ { "node_id": "research", "skill_query": "research workflow", "selected_skill_names": ["research-workflow"], "ephemeral_guidance_id": None, "ephemeral_guidance_name": None, "ephemeral_used": False, "reason": "matched published skill", } ], "reason": "needs research", }, context_visible=False, ) session.append_message( "web:test", role="system", event_type="task_team_run_completed", event_payload={ "task_id": "task-1", "attempt_index": 1, "team_success": True, "team_run_ids": ["sub-run"], "node_results": [ { "node_id": "research", "success": True, "output_text": "evidence", "run_id": "sub-run", "skill_query": "research workflow", "selected_skill_names": ["research-workflow"], "ephemeral_skill_names": [], "ephemeral_guidance_id": None, "ephemeral_guidance_name": None, "ephemeral_used": False, "finish_reason": "stop", } ], }, context_visible=False, ) session.append_message( "web:test", role="system", event_type="task_synthesis_completed", event_payload={"task_id": "task-1", "attempt_index": 1, "main_run_id": "main-run"}, context_visible=False, ) session.append_message( "web:test", run_id="main-run", role="system", event_type="task_evidence_recorded", event_payload={ "task_id": "task-1", "attempt_index": 1, "evidence_status": "recorded", }, context_visible=False, ) projection = SessionProcessProjector(session, run_store).project("web:test") run_ids = {run["run_id"] for run in projection["runs"]} assert "task:task-1:attempt:1" in run_ids assert "sub-run" in run_ids assert "main-run" in run_ids sub_run = next(run for run in projection["runs"] if run["run_id"] == "sub-run") assert sub_run["metadata"]["selected_skill_names"] == ["research-workflow"] assert sub_run["metadata"]["skill_query"] == "research workflow" assert sub_run["metadata"]["ephemeral_guidance_id"] is None assert any(event["actor_name"] == "Evidence" for event in projection["events"]) assert any(run["session_id"] == "web:test" for run in projection["runs"]) def test_process_projection_exposes_ephemeral_guidance_artifacts(tmp_path: Path) -> None: session = SessionManager(tmp_path) run_store = RunMemoryStore(tmp_path / "memory" / "runs") run_store.append_run_record( RunRecord( run_id="sub-run", session_id="sub-session", task_id="task-1", attempt_index=1, task_text="sub task", started_at="2026-01-01T00:00:01+00:00", ended_at="2026-01-01T00:00:02+00:00", success=True, finish_reason="stop", ) ) session.append_message( "web:test", role="system", event_type="task_execution_planned", event_payload={ "task_id": "task-1", "attempt_index": 1, "plan_mode": "team", "strategy": "sequence", "node_ids": ["research"], "ephemeral_guidance_ids": ["eg_123"], "skill_resolution_report": [ { "node_id": "research", "skill_query": "research workflow", "selected_skill_names": [], "ephemeral_guidance_id": "eg_123", "ephemeral_guidance_name": "research-workflow", "ephemeral_used": True, "reason": "generated ephemeral guidance", } ], }, context_visible=False, ) session.append_message( "web:test", role="system", event_type="task_team_run_completed", event_payload={ "task_id": "task-1", "attempt_index": 1, "team_success": True, "team_run_ids": ["sub-run"], "node_results": [ { "node_id": "research", "success": True, "output_text": "evidence", "run_id": "sub-run", "skill_query": "research workflow", "selected_skill_names": [], "ephemeral_skill_names": ["ephemeral:research-workflow"], "ephemeral_guidance_id": "eg_123", "ephemeral_guidance_name": "research-workflow", "ephemeral_used": True, "finish_reason": "stop", } ], }, context_visible=False, ) projection = SessionProcessProjector(session, run_store).project("web:test") sub_run = next(run for run in projection["runs"] if run["run_id"] == "sub-run") assert sub_run["metadata"]["ephemeral_guidance_id"] == "eg_123" assert projection["artifacts"][0]["artifact_id"] == "sub-run:ephemeral-guidance:eg_123" assert projection["artifacts"][0]["metadata"]["ephemeral_guidance_name"] == "research-workflow"