#!/usr/bin/env python3 import argparse import hashlib import json import os from pathlib import Path import yaml ROOT = Path(__file__).resolve().parent.parent def file_sha256(path: Path) -> str: if not path.exists(): return "" h = hashlib.sha256() try: with path.open("rb") as f: for chunk in iter(lambda: f.read(65536), b""): h.update(chunk) return h.hexdigest() except Exception: return "" def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--out", required=True) args = parser.parse_args() out_path = Path(args.out) if not out_path.is_absolute(): out_path = ROOT / out_path # Load active artifact manifest manifest_path = ROOT / "runtime" / "active_artifact_manifest.yaml" manifest_data = {} if manifest_path.exists(): try: manifest_data = yaml.safe_load(manifest_path.read_text(encoding="utf-8")) except Exception as e: print(f"Error reading manifest: {e}") # Load canonical metrics from final_decision_packet_active.json packet_path = ROOT / "Temp" / "final_decision_packet_active.json" packet_hash = file_sha256(packet_path) # Count files files = [p for p in ROOT.rglob("*") if p.is_file() and not p.parts[len(ROOT.parts):].count("Temp") and not p.parts[len(ROOT.parts):].count(".git")] baseline = { "formula_id": "REFACTOR_BASELINE_MANIFEST_V2", "total_files": len(files), "active_manifest_rows": manifest_data.get("manifest_rows", []), "canonical_metrics_hash": packet_hash, "lock_temp_edits": True, "source_zip_sha256": "c8d214d3c880392b176c26947367d832a55fd9f4a107bad69c7f272cd4c6b01e" } # Write baseline manifest out_path.parent.mkdir(parents=True, exist_ok=True) out_path.write_text(yaml.safe_dump(baseline, allow_unicode=True, default_flow_style=False), encoding="utf-8") print(f"Written baseline manifest to {out_path}") # Write rollback manifest v2 rollback_path = ROOT / "runtime" / "rollback_manifest_v2.yaml" rollback = { "formula_id": "REFACTOR_ROLLBACK_MANIFEST_V2", "previous_active_packet": "Temp/final_decision_packet_active.json", "previous_manifest": "runtime/active_artifact_manifest.yaml", "rollback_files": [ {"path": "runtime/active_artifact_manifest.yaml", "sha256": file_sha256(manifest_path)}, {"path": "Temp/final_decision_packet_active.json", "sha256": packet_hash} ] } rollback_path.write_text(yaml.safe_dump(rollback, allow_unicode=True, default_flow_style=False), encoding="utf-8") print(f"Written rollback manifest to {rollback_path}") # Ensure lineage events log exists lineage_log = ROOT / "runtime" / "lineage_events.jsonl" if not lineage_log.exists(): lineage_log.touch() return 0 if __name__ == "__main__": raise SystemExit(main())