#!/usr/bin/env python3
"""Red-proof for R-618, live on 9202 through the product.
The claim: three templates name a health probe the app does not answer. The proof must show BOTH
halves at the same moment, or it shows nothing:
(a) the PRODUCT says the app is unhealthy — the controller's state, and the app page's badge;
(b) the APP is fine — its own front door answers 200, and docker's healthcheck reads healthy.
A reading of (a) alone is equally consistent with "the app really is broken", which is exactly the
mistake this whole exercise exists to stop making.
"""
import json, re, sys, time
sys.path.insert(0, '.')
import walk as w
OUT = "../probe-fix-2026-09-22"
APPS = [("tandoor", "tandoor", "/accounts/login/"),
("zipline", "zipline", "/"),
("wger", "wger", "/")]
def observe(name, sub, path, tag):
st = w.stack(name)
ac = st.get("app_config") or {}
rc, code, body = w.app_curl(sub, path)
dk = w.guest(f"docker inspect --format '{{{{.State.Health.Status}}}}' "
f"$(docker ps -q --filter name={name}) 2>&1 | head -3").strip()
bg = w.badges(name)
# The health word the HOUSEHOLD reads, in both languages — the version badge is a different
# element and quoting it instead would prove nothing about health (it says "Naprakesz" either
# way). Taken from the rendered page, scripts and styles stripped first: a `|", "", h, flags=re.S)
txt = re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", h))
m = re.search(r"\u2190 Alkalmaz\u00e1sok .{0,80}?\s(Nem eg\u00e9szs\u00e9ges|Eg\u00e9szs\u00e9ges|Fut|Le\u00e1ll\u00edtva|Indul|Hib\u00e1s)\s", txt) or \
re.search(r"\u2190 (?:Apps|Alkalmaz\u00e1sok) .{0,80}?\s(Not healthy|Healthy|Running|Stopped|Starting|Failed)\s", txt)
health[lang] = m.group(1) if m else None
health[lang + "_context"] = txt[txt.find("\u2190"):txt.find("\u2190") + 220] if "\u2190" in txt else None
rec = {"when": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "tag": tag, "app": name,
"controller_state": st.get("state"), "deployed": st.get("deployed"),
"pinned_images": ac.get("pinned_images"), "installed_images": ac.get("installed_images"),
"front_door_rc": rc, "front_door_code": code, "front_door_bytes": len(body),
"docker_health": dk, "version_badge": bg, "health_word": health}
print(json.dumps(rec, ensure_ascii=False, indent=2))
return rec
if __name__ == "__main__":
w.login()
tag = sys.argv[1] if len(sys.argv) > 1 else "before"
only = sys.argv[2:] or [a[0] for a in APPS]
recs = []
for name, sub, path in APPS:
if name not in only:
continue
print(f"\n=== {name} ({tag})")
if tag == "before":
ok = w.deploy(name, sub)
print(f" deploy ok={ok}")
w.wait_app(sub, path)
recs.append(observe(name, sub, path, tag))
open(f"{OUT}/probe-{tag}.json", "w").write(json.dumps(recs, ensure_ascii=False, indent=2))
print(f"\nwritten {OUT}/probe-{tag}.json")