"""Tests for activity review CLI (ACTIVITY-WP-0028).""" from __future__ import annotations import json from datetime import datetime, timezone from pathlib import Path import pytest from activity_core.review_cli.checkpoint import ack, load_checkpoint, save_checkpoint from activity_core.review_cli.defs import load_local_automations from activity_core.review_cli.main import main from activity_core.review_cli.merge import classify_row from activity_core.review_cli.repo import resolve_repo, _slug_from_remote_url from activity_core.review_cli.timewin import parse_since def test_slug_from_remote() -> None: assert ( _slug_from_remote_url("forgejo-remote:coulomb/freedom-intelligence.git") == "freedom-intelligence" ) assert ( _slug_from_remote_url("https://forgejo.example/coulomb/binky-control.git") == "binky-control" ) def test_resolve_repo_explicit(tmp_path: Path) -> None: r = resolve_repo(cwd=tmp_path, explicit="freedom-intelligence") assert r["slug"] == "freedom-intelligence" assert r["source"] == "flag" def test_parse_since_today() -> None: now = datetime(2026, 8, 6, 15, 0, tzinfo=timezone.utc) s = parse_since("today", now=now, tz_name="UTC") assert s is not None assert s.day == 6 assert s.hour == 0 def test_parse_since_checkpoint() -> None: cp = {"reviewed_at": "2026-08-05T14:00:00+00:00"} s = parse_since("checkpoint", checkpoint=cp) assert s is not None assert s.day == 5 def test_classify_trust_matrix() -> None: assert classify_row(git_present=True, hub_present=True) == "ok" assert classify_row(git_present=True, hub_present=False) == "partial" assert classify_row(git_present=False, hub_present=True) == "lag" assert classify_row(git_present=False, hub_present=False) == "missing" assert classify_row(git_present=None, hub_present=None, ops_failed=True) == "failed" def test_checkpoint_ack_roundtrip(tmp_path: Path) -> None: save_checkpoint("freedom-intelligence", {"reviewed_paths": []}, tmp_path) ack( "freedom-intelligence", paths=["briefs/2026/08/2026-08-06.md"], state_dir=tmp_path, ) cp = load_checkpoint("freedom-intelligence", tmp_path) assert "briefs/2026/08/2026-08-06.md" in cp["reviewed_paths"] assert cp["reviewed_at"] def test_load_local_fi_definition(tmp_path: Path) -> None: defs = tmp_path / "activity-definitions" defs.mkdir() (defs / "fi-daily-research-brief.md").write_text( """--- id: fi-daily-research-brief name: Freedom Intelligence Daily Research Brief enabled: true trigger: type: cron cron_expression: "30 7 * * 1-5" timezone: Europe/Berlin --- ```rule id: emit action: target_repo: freedom-intelligence labels: ["freedom-intelligence"] ``` """, encoding="utf-8", ) items, warnings = load_local_automations(tmp_path, "freedom-intelligence") assert not warnings assert len(items) == 1 assert items[0]["id"] == "fi-daily-research-brief" assert "briefs/**/*.md" in items[0]["review"]["deliverable_globs"] def test_cli_list_json(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None: defs = tmp_path / "activity-definitions" defs.mkdir() (defs / "fi-daily-research-brief.md").write_text( """--- id: fi-daily-research-brief name: Freedom Intelligence Daily Research Brief enabled: true trigger: type: cron cron_expression: "30 7 * * 1-5" timezone: Europe/Berlin --- ```rule id: emit action: target_repo: freedom-intelligence ``` """, encoding="utf-8", ) code = main( [ "list", "--cwd", str(tmp_path), "--repo", "freedom-intelligence", "--format", "json", ] ) assert code in (0, 2) out = capsys.readouterr().out data = json.loads(out) assert data["repo"] == "freedom-intelligence" assert data["count"] == 1 def test_cli_status_offline(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None: defs = tmp_path / "activity-definitions" defs.mkdir() briefs = tmp_path / "briefs" / "2026" / "08" briefs.mkdir(parents=True) (briefs / "2026-08-06.md").write_text("# brief\n", encoding="utf-8") (defs / "fi-daily-research-brief.md").write_text( """--- id: fi-daily-research-brief name: Freedom Intelligence Daily Research Brief enabled: true trigger: type: cron cron_expression: "30 7 * * 1-5" timezone: Europe/Berlin --- ```rule id: emit action: target_repo: freedom-intelligence ``` """, encoding="utf-8", ) # init git for deliverables import subprocess subprocess.run(["git", "init"], cwd=tmp_path, check=True, capture_output=True) subprocess.run(["git", "add", "."], cwd=tmp_path, check=True, capture_output=True) subprocess.run( ["git", "-c", "user.email=t@t", "-c", "user.name=t", "commit", "-m", "init"], cwd=tmp_path, check=True, capture_output=True, ) code = main( [ "status", "--cwd", str(tmp_path), "--repo", "freedom-intelligence", "--state-dir", str(tmp_path / "state"), "--since", "week", ] ) assert code in (0, 2) out = capsys.readouterr().out assert "freedom-intelligence" in out assert "Automations:" in out