#!/usr/bin/env python3 # -*- coding: utf-8 -*- """unproven.py — "which claims are not proven?", as a question a machine can answer (R-326). WHY THIS EXISTS. The operator asked on 2026-08-04 to see what is built and what is still unproven. The picture was built (`where-felhom-stands.yaml` → `.html`) and it is good — but the QUESTION could only be answered by a person reading it. On 2026-08-13 a session was asked for "the nine grey claims", could not determine which nine, and declined to guess. It was right to decline, and the refusal is the finding this closes. WHERE "NINE" CAME FROM, since a wrong number that matches nothing is worse than no number. It is real, and it answers a DIFFERENT question: nine claims carry `verdict: downgraded` — the count the 2026-08-09 verification pass LOWERED. The count of claims that are not walked is 32. Both are true; only one of them is "what is unproven". This reads the dataset only. It makes no judgement, opens no evidence and contacts no machine — a claim's status is the capability map's business (the map changes first; the dataset follows it), and `check_stands.py` is the gate that keeps the citations honest. This just answers the question. Run: python3 scripts/unproven.py # every claim that is not walked python3 scripts/unproven.py --summary # the counts only """ import io import os import re import sys ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DATA = os.path.join(ROOT, "documentation", "architecture", "where-felhom-stands.yaml") # The status that means "done end to end on real hardware, with evidence on file". Everything else is # a degree of not-that, which is the whole point of the question. PROVEN = "walked" # Widest first, so the output reads as a ladder down from nearly-there to not-started. ORDER = ["partial", "built", "missing"] def field(entry, name): m = re.search(r"^\s*%s:\s*\"?(.*?)\"?\s*$" % name, entry, re.M) return m.group(1) if m else "" def load(): if not os.path.exists(DATA): sys.exit("unproven: the dataset is missing: %s" % DATA) text = io.open(DATA, encoding="utf-8").read() parts = re.split(r"\n - id: ", text) header, entries = parts[0], parts[1:] if not entries: sys.exit("unproven: no claims parsed from %s — the file's shape changed" % DATA) claims = [] for e in entries: claims.append({ "id": e.split("\n", 1)[0].strip(), "status": field(e, "status") or "(none)", "title": field(e, "title"), "band": field(e, "band"), "verdict": field(e, "verdict"), "evidence": "evidence:" in e, }) return field(header, "verified_on"), claims def main(): verified_on, claims = load() not_walked = [c for c in claims if c["status"] != PROVEN] counts = {} for c in claims: counts[c["status"]] = counts.get(c["status"], 0) + 1 print("where felhom stands — %d claims, verified_on %s" % (len(claims), verified_on)) print(" %-8s %d" % (PROVEN, counts.get(PROVEN, 0))) for s in ORDER: n = counts.get(s, 0) with_ev = sum(1 for c in claims if c["status"] == s and c["evidence"]) print(" %-8s %d (%d cite evidence, %d prose only)" % (s, n, with_ev, n - with_ev)) for s in sorted(k for k in counts if k not in ORDER + [PROVEN]): print(" %-8s %d ⚠ status not known to this script" % (s, counts[s])) print(" NOT WALKED: %d of %d" % (len(not_walked), len(claims))) if "--summary" in sys.argv: return 0 print() for s in ORDER + sorted(k for k in counts if k not in ORDER + [PROVEN]): rows = [c for c in not_walked if c["status"] == s] if not rows: continue print("%s (%d)" % (s.upper(), len(rows))) for c in sorted(rows, key=lambda c: c["id"]): ev = "evidence" if c["evidence"] else "PROSE ONLY" vd = (" [%s]" % c["verdict"]) if c["verdict"] else "" print(" %-40s %-10s %s%s" % (c["id"], c["band"], ev, vd)) print(" %s" % c["title"][:110]) print() return 0 if __name__ == "__main__": sys.exit(main())