from __future__ import annotations from pathlib import Path from storage.artifact_store import ArtifactStore from storage.timeline import Timeline from tests.fakes import PNG_10X20 def test_timeline_records_survive_reopening_store(tmp_path) -> None: store = ArtifactStore(tmp_path / "history") timeline = Timeline(store) timeline.append( task_id="task-1", scene={"screen": {"width": 1, "height": 1}, "elements": []}, prompt="goal", tool_call={"action": "tap"}, result={"ok": True}, screenshot=PNG_10X20, ) timeline.append( task_id="task-1", scene={"screen": {"width": 1, "height": 1}, "elements": []}, prompt="goal", tool_call={"action": "input_text"}, result={"ok": True}, screenshot=PNG_10X20, ) reopened = Timeline(ArtifactStore(tmp_path / "history")) records = reopened.read("task-1") assert [record["index"] for record in records] == [1, 2] assert records[0]["screenshot_path"].endswith("001.png") def test_timeline_records_per_step_prompt_not_task_goal(tmp_path) -> None: """The prompt field should persist exactly what was passed to append(), not a pre-D9 task goal fallback.""" store = ArtifactStore(tmp_path / "history") timeline = Timeline(store) per_step_prompt = "Goal:\nsend a message\n\nCurrent Scene (JSON):\n{...}\n\nCall exactly one tool." timeline.append( task_id="task-42", scene={"screen": {"width": 1, "height": 1}, "elements": []}, prompt=per_step_prompt, tool_call={"action": "tap"}, result={"ok": True}, screenshot=PNG_10X20, ) records = timeline.read("task-42") assert len(records) == 1 assert records[0]["prompt"] == per_step_prompt assert "Call exactly one tool" in records[0]["prompt"] def test_timeline_records_before_and_after_screenshots_with_ocr(tmp_path) -> None: timeline = Timeline(ArtifactStore(tmp_path / "history")) before = b"before-image" after = b"after-image" timeline.append( task_id="task-evidence", scene={"screen": {"width": 1, "height": 1}, "elements": []}, prompt="goal", tool_call={"action": "tap", "description": "tap search"}, result={"ok": True}, before_screenshot=before, after_screenshot=after, ocr_results=[ { "text": "Search", "confidence": 0.98, "bounds": {"x": 1, "y": 2, "width": 3, "height": 4}, } ], ) record = timeline.read("task-evidence")[0] assert Path(record["before_screenshot_path"]).read_bytes() == before assert Path(record["after_screenshot_path"]).read_bytes() == after assert record["screenshot_path"] == record["after_screenshot_path"] assert record["ocr_results"][0]["text"] == "Search"