# SPDX-License-Identifier: AGPL-3.0-only # Copyright (c) 2026 sol pbc import json import pytest from PIL import Image from solstone.observe import depict def _segment_image(tmp_path): segment_dir = tmp_path / "chronicle" / "20240101" / "default" / "123456_300" segment_dir.mkdir(parents=True) image_path = segment_dir / "photo.png" Image.new("RGB", (4, 4), color="red").save(image_path) return image_path def test_run_writes_image_jsonl_with_header_metadata(tmp_path, monkeypatch): image_path = _segment_image(tmp_path) monkeypatch.setenv("OBSERVER_NAME", "camera") monkeypatch.setenv( "SEGMENT_META", json.dumps({"stream": "default", "facet": "personal"}) ) calls = [] def fake_generate(*, contents, context): calls.append((contents[0], contents[1].size, context)) return "A concise image description" monkeypatch.setattr(depict, "generate", fake_generate) output_path = depict.run(image_path) assert output_path == image_path.with_suffix(".jsonl") assert len(calls) == 1 assert calls[0][0] == depict._DESCRIBE_PROMPT assert calls[0][1] == (4, 4) assert calls[0][2] == "observe.depict" lines = output_path.read_text(encoding="utf-8").splitlines() header = json.loads(lines[0]) entry = json.loads(lines[1]) assert header["raw"] == "photo.png" assert header["kind"] == "image" assert header["observer"] == "camera" assert header["stream"] == "default" assert header["facet"] == "personal" assert entry == {"start": "00:00:00", "text": "A concise image description"} def test_run_attaches_still_detection_block(tmp_path, monkeypatch): image_path = _segment_image(tmp_path) def fake_generate(*, contents, context): return "A concise image description" canned = { "image": {"width": 4, "height": 4}, "detections": [ { "class_id": 7, "class_name": "bottle", "score": 0.67, "bbox": [0, 1, 2, 3], } ], } monkeypatch.setattr(depict, "generate", fake_generate) monkeypatch.setattr(depict, "detect_objects", lambda _image_bytes: canned) output_path = depict.run(image_path) lines = output_path.read_text(encoding="utf-8").splitlines() entry = json.loads(lines[1]) assert entry["detections"] == { "engine": "rf-detr.cpp", "engine_ref": "65c0ffcc", "model": "rfdetr-nano-f16", "threshold": 0.25, "source": "still", "gate": "still", "image": canned["image"], "objects": canned["detections"], } def test_run_writes_image_jsonl_bytes_unchanged(tmp_path, monkeypatch): image_path = _segment_image(tmp_path) monkeypatch.setenv("OBSERVER_NAME", "camera") monkeypatch.setenv( "SEGMENT_META", json.dumps({"stream": "default", "facet": "personal"}) ) description = "café — naïve" def fake_generate(*, contents, context): return description monkeypatch.setattr(depict, "generate", fake_generate) output_path = depict.run(image_path) header = { "raw": "photo.png", "kind": "image", "observer": "camera", "stream": "default", "facet": "personal", } entry = {"start": "00:00:00", "text": description} expected = (json.dumps(header) + "\n" + json.dumps(entry) + "\n").encode("utf-8") assert output_path.read_bytes() == expected def test_run_skips_existing_output_unless_redo(tmp_path, monkeypatch): image_path = _segment_image(tmp_path) output_path = image_path.with_suffix(".jsonl") output_path.write_text("existing\n", encoding="utf-8") calls = [] def fake_generate(*, contents, context): calls.append((contents, context)) return "Replacement description" monkeypatch.setattr(depict, "generate", fake_generate) assert depict.run(image_path) is None assert output_path.read_text(encoding="utf-8") == "existing\n" assert calls == [] assert depict.run(image_path, redo=True) == output_path assert len(calls) == 1 assert "Replacement description" in output_path.read_text(encoding="utf-8") def test_run_generate_failure_leaves_no_output(tmp_path, monkeypatch): image_path = _segment_image(tmp_path) def fail_generate(*, contents, context): raise RuntimeError("model failed") monkeypatch.setattr(depict, "generate", fail_generate) with pytest.raises(RuntimeError, match="model failed"): depict.run(image_path) assert not image_path.with_suffix(".jsonl").exists()