Verify the standing picture against source: 12 downgrades, and the decay ran both ways
gates / gates (push) Successful in 21s

55 claims verified. Twelve moved, all downwards: walked 32 -> 20, built 5 -> 17.
Register ceiling R-284 -> R-290.

THE RULE DID NOT FIRE THE WAY IT WAS EXPECTED TO. Not one downgrade came from
code moving under an old proof. All twelve came from step 1 of the same rule --
the cited evidence does not exist. Measured: of the 28 capability-map rows
behind the page's claims, 8 carry a tests/ or audits/ path and 20 carry prose
only. The green dots were drawn from rows that cite an argument, not a walk
(R-290). The map, not the dataset, is what needs fixing -- it still says
PROVEN-LIVE for all twelve.

And once it ran backwards: fault.operator-email looked contradicted by R-182,
but live source shows the backup_run_failures digest allowlisted, operator-only
and templated, with recovery_unit_capture_failed now record-only. The claim is
right and the REGISTER ROW is stale (R-289). The session went looking for stale
proofs and found a stale defect.

R-281 WITHDRAWN -- wrong in both directions, settled by the operator's mailbox.
The tripwire DID fire (escrow_blob_served 10:19:41Z = 12:19 CEST) and false
error-severity alarms fired too, for deliberate attended work (R-285). The
measurement's cause is ESTABLISHED: the P7 query copied hub.db without hub.db-wal,
and the signature is exact -- it reported "2 events all day, newest 00:30:07",
and the rows at or before 00:30:07 number exactly 2. Timezone and wrong-key were
tested and refuted. The control had been drawn from the same stale snapshot as
the measurement, which is why it agreed (R-286).

Part 4: NO WORKFLOW CHANGED, deliberately. The gate is not ref-sensitive -- it
enumerates from the Gitea tags API, and both previous tag pushes passed. The red
is TRUE: run 267 saw v0.120.0 downloadable, run 284 on the same commit saw 404.
Who deleted the package is NOT established and is not guessed (R-287).

The page is now generated from where-felhom-stands.yaml by scripts/render_stands.py:
static, zero script tags, every moved status carrying a visible "changed, was X"
chip. The React bundle -- whose content was gzip+base64 inside a JS module map --
is kept as a dated snapshot. scripts/check_stands.py gates the data and convicted
51 problems in my own first draft before the staged positive control ever ran.
This commit is contained in:
2026-08-09 18:40:49 +02:00
parent a199c492f4
commit 6088afcbed
8 changed files with 1274 additions and 148 deletions
+118
View File
@@ -0,0 +1,118 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""check_stands.py — the gate on documentation/architecture/where-felhom-stands.yaml.
The page that dataset renders is the operator's picture of where the product stands. Its whole
value is that every claim on it is traceable, so this checks the traceability rather than the
claims: a claim nobody can trace is not a weaker claim, it is not a claim at all.
WHAT IT CONVICTS ON (each is a FAIL, exit 1):
1. an entry with NO source — §4 rule 1: that is a defect, not a claim
2. an `evidence:` path that does not resolve — a citation nobody opened
3. a `register:` id absent from OPEN-ITEMS.md — a dangling register reference
4. a `capability-map:` anchor not found — the row it derives from has moved or gone
5. status `walked` with no `evidence:` source — THE LOAD-BEARING ONE. "Walked" means done end
to end on real hardware with evidence on file. If no evidence document is cited, the page is
drawing a green dot from an opinion. This is the rule the positive control exercises: take a
claim the page marks `missing`, mark it `walked`, and this fires.
WHAT IT DOES NOT DO, said plainly so the green is not over-read: it does not read the evidence and
judge whether it supports the claim, and it cannot. A human verdict lives in each entry's
`verified:` block; this gate checks that the paperwork exists, not that the paperwork is right.
Run: python3 scripts/check_stands.py [path-to-yaml]
"""
import os
import re
import sys
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DEFAULT = os.path.join(ROOT, "documentation", "architecture", "where-felhom-stands.yaml")
REGISTER = os.path.join(ROOT, "documentation", "backlog", "OPEN-ITEMS.md")
CAPMAP = os.path.join(ROOT, "documentation", "architecture", "00-capability-map.md")
DOCS = os.path.join(ROOT, "documentation")
def load(path):
"""Minimal parser for the shape this file is written in.
Deliberately not PyYAML: the runner image and the gate hosts carry python3 and nothing else
(the same constraint that keeps `uses:` out of the CI workflow), and a gate that needs a pip
install is a gate that silently stops running.
"""
claims, cur, in_sources = [], None, False
for raw in open(path, encoding="utf-8"):
line = raw.rstrip("\n")
if line.startswith(" - id:"):
cur = {"id": line.split(":", 1)[1].strip(), "sources": []}
claims.append(cur)
in_sources = False
continue
if cur is None:
continue
if line.strip() == "sources:":
in_sources = True
continue
m = re.match(r'\s+- (capability-map|evidence|register): (.*)$', line)
if in_sources and m:
cur["sources"].append((m.group(1), m.group(2).strip().strip('"')))
continue
m = re.match(r'\s+(status|title|verdict|depth): (.*)$', line)
if m:
in_sources = False
cur[m.group(1)] = m.group(2).strip().strip('"')
return claims
def main():
path = sys.argv[1] if len(sys.argv) > 1 else DEFAULT
claims = load(path)
register = open(REGISTER, encoding="utf-8").read()
# Normalise the map before matching: its row labels carry ** and ` markup, so a literal
# substring probe against the raw file fails on text that is plainly there. Matching the
# rendered words is what the citation means.
capmap = open(CAPMAP, encoding="utf-8").read()
capmap = re.sub(r"[`*]", "", capmap)
capmap = re.sub(r"\s+", " ", capmap).lower()
print("check_stands — %d claim(s) in %s" % (len(claims), os.path.relpath(path, ROOT)))
fails = []
for c in claims:
cid = c["id"]
if not c["sources"]:
fails.append("%s: NO SOURCE — an entry with no source is a defect, not a claim" % cid)
for kind, ref in c["sources"]:
if kind == "evidence":
if not os.path.exists(os.path.join(DOCS, ref)):
fails.append("%s: evidence path does not resolve: documentation/%s" % (cid, ref))
elif kind == "register":
if not re.search(r"\*\*%s\*\*" % re.escape(ref), register):
fails.append("%s: register id %s is not in OPEN-ITEMS.md" % (cid, ref))
elif kind == "capability-map":
probe = " ".join(ref.split()[:4])
probe = re.sub(r"[`*]", "", probe)
if probe and probe.lower() not in capmap:
fails.append("%s: capability-map anchor not found: %r" % (cid, probe))
if c.get("status") == "walked" and not any(k == "evidence" for k, _ in c["sources"]):
fails.append("%s: status 'walked' but NO evidence document cited — a green dot "
"drawn from an opinion" % cid)
counts = {}
for c in claims:
counts[c.get("status")] = counts.get(c.get("status"), 0) + 1
print(" statuses: " + ", ".join("%s=%d" % kv for kv in sorted(counts.items())))
if fails:
print("\nCONVICTED — %d problem(s):" % len(fails))
for f in fails:
print(" " + f)
return 1
print("\ncheck_stands: OK — every claim cites a source, every citation resolves, and every "
"'walked' cites a walk.")
return 0
if __name__ == "__main__":
sys.exit(main())