6088afcbed
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.
119 lines
5.3 KiB
Python
119 lines
5.3 KiB
Python
#!/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())
|