from datetime import UTC, datetime from zerto_rewind_mcp.checkpoints import ( TAG_MAX_LEN, checkpoint_id, checkpoint_tag, make_tag, ) WHEN = datetime(2026, 9, 21, 15, 4, 5, tzinfo=UTC) def test_tag_describes_agent_and_action(): tag = make_tag( "claude", "chg-99", WHEN, action="edit /home/justin/app-config.yaml", vm_name="jp-ubuntu", ) assert tag == ( "ai:claude | edit /home/justin/app-config.yaml | vm=jp-ubuntu " "| change=chg-99 | 20260921T150405Z" ) def test_tag_without_action_or_vm(): assert make_tag("codex", "chg-99", WHEN) == "ai:codex | change=chg-99 | 20260921T150405Z" def test_tag_keeps_separators_unambiguous(): # ';' is what Zerto appends to its own tags; '|' is our field separator. tag = make_tag("a;b", "c|d", WHEN, action="rm -rf /tmp;x", vm_name="v|m") assert tag.count(" | ") == 4 assert ";" not in tag def test_tag_collapses_whitespace_and_caps_length(): tag = make_tag("agent one", "chg 1", WHEN, action="do\n many things") assert "\n" not in tag assert "do many things" in tag long_tag = make_tag("a" * 200, "b" * 200, WHEN, action="c" * 400) assert len(long_tag) <= TAG_MAX_LEN def test_checkpoint_row_keys(): row = {"CheckpointId": "cp-1", "Tag": "ai:x:y:z", "Timestamp": 1} assert checkpoint_id(row) == "cp-1" assert checkpoint_tag(row) == "ai:x:y:z" row2 = {"checkpointId": "cp-2", "tag": "t"} assert checkpoint_id(row2) == "cp-2" assert checkpoint_tag(row2) == "t"