from __future__ import annotations import hashlib import json import subprocess import sys from pathlib import Path from .constants import GENESIS_DIR, METADATA_FILES def sha256_file(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as handle: for chunk in iter(lambda: handle.read(1 << 20), b""): digest.update(chunk) return digest.hexdigest() def check_metadata(model_dir: Path, genesis_dir: Path = GENESIS_DIR) -> dict: model_dir = Path(model_dir) genesis_dir = Path(genesis_dir) files = {} ok = True for name in METADATA_FILES: left = model_dir / name right = genesis_dir / name if not left.is_file(): files[name] = {"ok": False, "reason": "missing in model"} ok = False continue if not right.is_file(): files[name] = {"ok": False, "reason": "missing in genesis"} ok = False continue left_hash = sha256_file(left) right_hash = sha256_file(right) match = left_hash == right_hash files[name] = { "ok": match, "model": left_hash, "genesis": right_hash, "reason": "" if match else "sha256 mismatch (not byte-identical to genesis)", } ok = ok and match return {"ok": ok, "files": files} def check_model(model_dir: Path, genesis_dir: Path = GENESIS_DIR) -> dict: """sha256 metadata vs genesis, then `albedo check-model` (no OpenSearch dedup).""" model_dir = Path(model_dir) meta = check_metadata(model_dir, genesis_dir) cli = _albedo_check(model_dir) report = { "path": str(model_dir), "metadata_hash": meta, "check_model": cli, "ok": bool(meta["ok"] and cli.get("ok")), "note": "check-model does not run OpenSearch 0.95 fingerprint dedup or live metadata pins.", } print(json.dumps(report, indent=2), flush=True) return report def _albedo_check(model_dir: Path) -> dict: cmd = [sys.executable, "-m", "miner.cli", "check-model", "--path", str(model_dir)] try: proc = subprocess.run( cmd, cwd=str(Path(__file__).resolve().parents[1]), capture_output=True, text=True, check=False, ) except OSError as exc: return {"ok": False, "reason": str(exc), "stdout": "", "stderr": ""} stdout = proc.stdout or "" return { "ok": proc.returncode == 0 and _valid_line(stdout), "returncode": proc.returncode, "stdout": stdout, "stderr": proc.stderr or "", } def _valid_line(stdout: str) -> bool: lines = [line.strip() for line in stdout.splitlines() if line.strip()] return bool(lines) and lines[-1] == "VALID"