#!/usr/bin/env python3 """Archive legacy HERDR metadata before the direct CLI lane takes over.""" from __future__ import annotations import json import os import shutil from datetime import datetime, timezone from pathlib import Path from typing import Any DATA_ROOT = Path("/opt/data") def _load_json(path: Path) -> dict[str, Any]: try: value = json.loads(path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): return {} return value if isinstance(value, dict) else {} def archive_legacy_state(data_root: Path = DATA_ROOT) -> Path: """Persist non-secret worker references and retire the exact HERDR binary.""" source = data_root / "home/.config/herdr/session.json" archive = data_root / "cli-lanes/migration/herdr-retirement.json" archive.parent.mkdir(parents=True, exist_ok=True) previous = _load_json(archive) legacy = _load_json(source) value = { "schema_version": 1, "migrated_at": previous.get("migrated_at") or datetime.now(timezone.utc).isoformat(), "source": str(source), "legacy_session": legacy, "provider_state_preserved": [ str(data_root / "home/.claude"), str(data_root / "home/.codex"), ], } temporary = archive.with_name(f".{archive.name}.{os.getpid()}.tmp") temporary.write_text(json.dumps(value, indent=2, sort_keys=True) + "\n", encoding="utf-8") temporary.chmod(0o600) os.replace(temporary, archive) # Provider transcripts remain in .claude and .codex. HERDR itself is # reproducibly reinstallable from Git history, so only its pinned binary is # retired after the migration record is durable. binary = data_root / "tools/bin/herdr" if binary.is_file(): binary.unlink() for legacy_dir in (data_root / "home/.config/herdr", data_root / "herdr"): if legacy_dir.is_dir(): shutil.rmtree(legacy_dir) return archive if __name__ == "__main__": print(archive_legacy_state())