"""Build a standalone rein-aharness runtime for the fixed bwrap mount path. Only package installation occurs here. No credentials or model calls are used. Run with the sand-boxer Python environment; uv must be available on PATH. """ from __future__ import annotations import argparse import hashlib import json import os import re import subprocess from pathlib import Path from sandboxer.extensions.runtime import RUNTIME_MOUNT, runtime_digest def checked(command: list[str], *, env: dict[str, str] | None = None) -> str: result = subprocess.run(command, capture_output=True, text=True, timeout=300, env=env) if result.returncode: raise RuntimeError(f"runtime build command failed: {Path(command[0]).name}") return result.stdout.strip() def install_claude(output: Path, source: Path, sha256: str, version: str) -> dict: """Copy only an explicitly pinned native executable, never an interactive HOME.""" if not re.fullmatch(r"[0-9a-f]{64}", sha256) or not version.strip(): raise ValueError("Claude requires an exact SHA-256 and expected version") if source.is_symlink() or not source.is_file(): raise ValueError("Claude source must be a regular file, not a symlink") content = source.read_bytes() if hashlib.sha256(content).hexdigest() != sha256: raise ValueError("Claude executable digest mismatch") if not content.startswith(b"\x7fELF"): raise ValueError("Claude executable must be native ELF, not a host wrapper") destination = output / "bin/claude" with destination.open("xb") as stream: stream.write(content) destination.chmod(0o755) return {"path": f"{RUNTIME_MOUNT}/bin/claude", "sha256": sha256, "expected_version": version, "source": str(source)} def build(output: Path, rein_source: Path, llm_source: Path, claude_binary: Path | None = None, claude_sha256: str | None = None, claude_version: str | None = None, *, owner_runtime: bool = False) -> dict: supplied = (claude_binary, claude_sha256, claude_version) if any(x is not None for x in supplied) and not all(x is not None for x in supplied): raise ValueError("Claude binary, SHA-256 and expected version must be supplied together") revisions = {} for name, source in (("rein-aharness", rein_source), ("llm-connect", llm_source)): if checked(["git", "-C", str(source), "status", "--porcelain"]): raise ValueError(f"{name} source must be committed before building") revisions[name] = checked(["git", "-C", str(source), "rev-parse", "HEAD"]) lock_report = None if owner_runtime: lock_report = json.loads(checked([ "/usr/bin/python3", str(rein_source / "scripts/verify_runtime_lock.py") ])) if not lock_report.get("ok"): raise ValueError("owner runtime requires the verified sibling lock") if next(x["commit"] for x in lock_report["dependencies"] if x["distribution"] == "llm-connect") != revisions["llm-connect"]: raise ValueError("owner runtime llm source does not match sibling lock") revisions.update({x["distribution"]: x["commit"] for x in lock_report["dependencies"]}) output.mkdir(parents=True, exist_ok=False) checked(["/usr/bin/python3", "-m", "venv", "--copies", "--without-pip", str(output)]) if owner_runtime: checked(["uv", "sync", "--project", str(rein_source), "--frozen", "--no-editable", "--no-dev", "--extra", "glas", "--extra", "llm", "--python", "/usr/bin/python3"], env={**os.environ, "UV_PROJECT_ENVIRONMENT": str(output)}) else: checked(["uv", "pip", "install", "--python", str(output / "bin/python3"), str(rein_source), str(llm_source)]) # Console entrypoints must reference the in-sandbox mount, not the build host. for path in (output / "bin").iterdir(): if not path.is_file() or path.is_symlink(): continue with path.open("rb") as stream: first_line = stream.readline(4096) if first_line.startswith(f"#!{output}/bin/python".encode()): body = path.read_bytes().partition(b"\n")[2] path.write_bytes(f"#!{RUNTIME_MOUNT}/bin/python3\n".encode() + body) metadata = json.loads(checked([ str(output / "bin/python3"), "-c", "import importlib.metadata,json,platform; " "print(json.dumps({'python':platform.python_version(),'packages':" "{d.metadata['Name']:d.version for d in importlib.metadata.distributions()}}))", ])) if claude_binary is not None: metadata["claude"] = install_claude(output, claude_binary, claude_sha256, claude_version) metadata["source_revisions"] = revisions if owner_runtime: metadata["owner_runtime"] = True metadata["runtime_contract"] = lock_report metadata["uv_lock_sha256"] = hashlib.sha256( (rein_source / "uv.lock").read_bytes() ).hexdigest() (output / "build-info.json").write_text(json.dumps(metadata, indent=2) + "\n") return {"runtime": {"path": str(output), "sha256": runtime_digest(output)}, "build": metadata} def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--output", type=Path, required=True) parser.add_argument("--rein-source", type=Path, required=True) parser.add_argument("--llm-source", type=Path, required=True) parser.add_argument("--claude-binary", type=Path) parser.add_argument("--claude-sha256") parser.add_argument("--claude-version") parser.add_argument("--owner-runtime", action="store_true", help="Include the pinned owner packages from rein uv.lock") args = parser.parse_args() result = build(args.output.resolve(), args.rein_source.resolve(), args.llm_source.resolve(), args.claude_binary, args.claude_sha256, args.claude_version, owner_runtime=args.owner_runtime) print(json.dumps(result, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())