#!/usr/bin/env python3 """Undo trailing-punctuation damage by restoring lines that match HEAD exactly except for a stripped trailing `,` / `;` / removed trailing word. The repair pass over-reached: its "dangling pointer" cleanup also matched every wrapped prose line ending in a comma, and deleted the comma. A line whose text is otherwise byte-identical to its HEAD version, differing only by trailing punctuation, is not an edit — it is damage, so HEAD's line goes back. Usage: restore-punctuation.py [--apply] """ import pathlib import subprocess import sys REPO = pathlib.Path(".") VAULT = REPO / "serverAppConfigs-docs" def head_text(rel): r = subprocess.run(["git", "show", f"HEAD:{rel}"], capture_output=True, text=True) return r.stdout if r.returncode == 0 else None def main(argv): apply = "--apply" in argv restored = 0 pages = 0 for p in sorted(VAULT.rglob("*.md")): s = str(p) if ".AGENTTRASH" in s or ".obsidian" in s: continue rel = s head = head_text(rel) if head is None: continue cur = p.read_text(errors="replace").split("\n") # Key on (length, prefix) of the HEAD line minus trailing punctuation so a # damaged line can find its original. index = {} for hl in head.split("\n"): h = hl.rstrip() if h.endswith((",", ";")) or True: key = (len(h.rstrip(",;. ")), h.rstrip(",;. ")[:60]) index.setdefault(key, h) touched = 0 for i, cl in enumerate(cur): c = cl.rstrip() if not c or c.endswith((".", ":", "|", "`", ")", "," , ";")): continue key = (len(c), c[:60]) hl = index.get(key) if hl and hl != c and hl.startswith(c): cur[i] = hl touched += 1 if touched: pages += 1 restored += touched if apply: p.write_text("\n".join(cur)) print(f"{'APPLIED' if apply else 'dry run'}: {restored} lines restored across {pages} pages") return 0 if __name__ == "__main__": sys.exit(main(sys.argv))