Files
felhom.eu/documentation/audits/pg-calcom-claper-2026-09-28/tools/drillmove.py
T
admin 5340aec56b
gates / gates (push) Successful in 25s
audits: claper PG 16->17 bench + box proofs; calcom crash evidence
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-28 10:55:25 +02:00

40 lines
2.4 KiB
Python

"""drillmove.py <app> <svc> <from-ref> <to-ref> <from-major> <to-major>
DRILL-ONLY commit: move one PostgreSQL service in the drill catalog and add the ladder entry that carries the
engine_conversion mark, so the box (9202) can prove the conversion through its own guarded Update. The live
catalog's entry is written later ONLY by `upgrade-test.py --write-ladder` from both verdicts."""
import json, re, subprocess, sys
D = "/mnt/5_hdd/felhom.eu/drill/app-catalog-drill"
app, svc, frm, to, fmj, tmj = sys.argv[1:7]
subprocess.run(["git", "-C", D, "pull", "-q", "--rebase", "origin", "main"], check=True)
comp = f"{D}/templates/{app}/docker-compose.yml"
fy = f"{D}/templates/{app}/.felhom.yml"
s = open(comp).read()
assert f"image: {frm}" in s, "from ref not in compose"
pins = {}
cur = None
for line in s.splitlines():
m = re.match(r"^ ([a-z0-9-]+):\s*$", line)
if m: cur = m.group(1)
m = re.match(r"^\s+image:\s*(\S+)", line)
if m and cur: pins[cur] = m.group(1)
s = s.replace(f"image: {frm}", f"image: {to}")
if int(tmj) >= 18: # 18+ wants the volume at /var/lib/postgresql (09 decision 37)
s = re.sub(r"(-\s+[A-Za-z0-9_.-]*postgres[A-Za-z0-9_.-]*:)/var/lib/postgresql/data(\s*)$", r"\1/var/lib/postgresql\2", s, flags=re.M)
open(comp, "w").write(s)
top = dict(pins); top[svc] = to
entry = {"from": pins, "to": top, "verdict": "proven", "tested_at": "DRILL", "harness_version": 4,
"evidence": "DRILL (box proof in progress)", "marks": {"files_may_change": False, "needs_person": None, "memory_tight": False},
"engine_conversion": {"service": svc, "engine": "postgres", "from": int(fmj), "to": int(tmj)}}
f = open(fy).read()
line = " - " + json.dumps(entry) + "\n"
if "update_ladder:" in f:
f = f.replace("update_ladder:\n", "update_ladder:\n", 1)
f = f.rstrip("\n") + "\n" + line if f.rstrip("\n").endswith("}") else f + line
else:
f = f.rstrip("\n") + "\nupdate_ladder:\n" + line
open(fy, "w").write(f)
subprocess.run(["git", "-C", D, "commit", "-q", "-am", f"DRILL {app}: {svc} {frm} -> {to} with the engine_conversion mark (box proof)"], check=True)
subprocess.run(["git", "-C", D, "push", "-q", "origin", "main"], check=True, capture_output=True)
print(subprocess.run(["git", "-C", D, "log", "--oneline", "-1"], capture_output=True, text=True).stdout.strip())
print(subprocess.run(["git", "-C", D, "show", "--stat", "HEAD"], capture_output=True, text=True).stdout[-300:])