diff --git a/app-instance/backend/tests/unit/test_process_projection.py b/app-instance/backend/tests/unit/test_process_projection.py index 1b1b47c..7c47320 100644 --- a/app-instance/backend/tests/unit/test_process_projection.py +++ b/app-instance/backend/tests/unit/test_process_projection.py @@ -158,6 +158,57 @@ def test_process_projection_maps_task_team_events(tmp_path: Path) -> None: assert acceptance_event["metadata"]["timeline_type"] == "acceptance" +def test_process_projection_maps_failed_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="failed-sub-run", + session_id="failed-sub-session", + task_id="task-1", + attempt_index=1, + task_text="failed sub task", + started_at="2026-01-01T00:00:01+00:00", + ended_at="2026-01-01T00:00:02+00:00", + success=False, + finish_reason="error", + ) + ) + session.append_message( + "web:test", + role="system", + event_type="task_team_run_failed", + event_payload={ + "task_id": "task-1", + "attempt_index": 1, + "team_success": False, + "team_run_ids": ["failed-sub-run"], + "error": "research node failed", + "node_results": [ + { + "node_id": "research", + "success": False, + "error": "source unavailable", + "run_id": "failed-sub-run", + "finish_reason": "error", + } + ], + }, + context_visible=False, + ) + + projection = SessionProcessProjector(session, run_store).project("web:test") + + team_event = next(event for event in projection["events"] if event["kind"] == "agent_team_created") + assert team_event["status"] == "error" + assert team_event["metadata"]["timeline_type"] == "agent_team" + assert team_event["metadata"]["team_run_ids"] == ["failed-sub-run"] + + node_event = next(event for event in projection["events"] if event["kind"] == "agent_finished") + assert node_event["status"] == "error" + assert node_event["metadata"]["timeline_type"] == "agent_progress" + + def test_process_projection_exposes_ephemeral_guidance_artifacts(tmp_path: Path) -> None: session = SessionManager(tmp_path) run_store = RunMemoryStore(tmp_path / "memory" / "runs")