diff --git a/graphify/__main__.py b/graphify/__main__.py index 758278ba..52c1874f 100644 --- a/graphify/__main__.py +++ b/graphify/__main__.py @@ -4611,7 +4611,7 @@ def main() -> None: out_path.parent.mkdir(parents=True, exist_ok=True) out_path.write_text(json.dumps(merged, ensure_ascii=False), encoding="utf-8") print( - f"Merged {len(chunk_files)} chunks: {merged['nodes']} nodes, {len(merged['edges'])} edges, " + f"Merged {len(chunk_files)} chunks: {len(merged['nodes'])} nodes, {len(merged['edges'])} edges, " f"{merged['input_tokens']:,} in / {merged['output_tokens']:,} out tokens" ) diff --git a/graphify/global_graph.py b/graphify/global_graph.py index 4c4817fa..4597268d 100644 --- a/graphify/global_graph.py +++ b/graphify/global_graph.py @@ -16,8 +16,27 @@ def _load_manifest() -> dict: if _GLOBAL_MANIFEST.exists(): try: return json.loads(_GLOBAL_MANIFEST.read_text(encoding="utf-8")) - except Exception: - pass + except Exception as exc: + # Don't silently wipe the user's manifest on a parse error: that + # deletes every tracked repo. Back the bad file up and surface the + # error so the user can recover or report it. + backup = _GLOBAL_MANIFEST.with_suffix( + _GLOBAL_MANIFEST.suffix + f".corrupt.{int(datetime.now(timezone.utc).timestamp())}" + ) + try: + _GLOBAL_MANIFEST.rename(backup) + print( + f"[graphify global] manifest at {_GLOBAL_MANIFEST} failed to parse ({exc}); " + f"moved to {backup} and starting fresh. Restore from the backup if this was " + f"unexpected.", + file=sys.stderr, + ) + except Exception as rename_exc: + print( + f"[graphify global] manifest at {_GLOBAL_MANIFEST} failed to parse ({exc}) " + f"and could not be backed up ({rename_exc}). Starting fresh.", + file=sys.stderr, + ) return {"version": 1, "repos": {}}