open-standards/scripts/check-wai-section-refs.py
Transaction Science 72e3300752 wai: key discovery, signing authority and module revocation
jwp-receipts §7: a did:web signer_id names a web origin, which publishes
a key log at /.well-known/wai-keys: revisions signed by a root key that
pre-commits to its successor, listing the origin's keys, the authorities
each holds, and whether each is active, retired or revoked. A verifier
that has anchored the origin, pinned or fetched, confirms an accepted
receipt, claim or module grant against the log offline, and reports the
outcome beside the item's own verdict, never in it. Hardware-class
energy, lawful-basis and pre-emption authorities are confirmed only
under a pinned anchor. Revocation refuses every item under a revoked key.

§7.9 authorises decoder and reconstruct modules, and pinned parameter
sets, by SHA-256 digest through signed module grants from the sink's
module origins, revokes them by digest in the key log, and bounds how
long a revoked module keeps running by grant_max_s + status_max_age_s,
under ceilings of 86400 s and 3600 s. Every failure, offline included,
leaves the module not held and dispatch falls back.

wai-rs gains signer_id (ungated) and key_log (feature key_discovery),
the wai_signer_vectors and wai-keys binaries, and the signer-conformance
corpus with an independent Python verifier. The reference meters and
the world demo sign under labels. A section-reference guard checks that
every section SPEC.md or an extension cites in another of them exists.

This commit is the stream as merged onto link 14. The commits after it
reconcile it with the parameter-set pin and the energy reports.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 07:12:20 -04:00

92 lines
3.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Every section a WAI specification text cites in another WAI text exists.
Reads wai/SPEC.md and wai/extensions/*.md. In each, a reference to a section of
SPEC.md or of an extension is checked against the headings of the file it names. Three
spellings are recognised, including where the reference breaks across lines:
[text](X.md) §N a link, then the section
[text §N](X.md) the section inside the link text
X §N, X.md §N, `X` §N an extension's file name (or SPEC) in prose, then the section
where §N is a section number of one or more parts (§7, §2.4.3), and a range written
§A–§B checks both ends. A heading is numbered when it begins `#`…, then the number, as
in `## 7.`, `### 6.4 ` or `## 7.1.`. Files under wai/research/ are dated records, kept as
written, and are not read.
Exit status 1, with one line per reference that names a missing section; 0 otherwise.
python3 scripts/check-wai-section-refs.py [repo-root]
"""
import os, re, sys
ROOT = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
WAI = os.path.join(ROOT, "wai")
EXT = os.path.join(WAI, "extensions")
HEADING = re.compile(r"^#{1,6}[ \t]+([0-9]+(?:\.[0-9]+)*)\.?(?=[ \t])", re.M)
SECTION = r"§[ \t]*([0-9]+(?:\.[0-9]+)*)"
RANGE = re.compile(r"[ \t]*[–-][ \t]*§[ \t]*([0-9]+(?:\.[0-9]+)*)")
def sections(path):
with open(path, encoding="utf-8") as f:
return set(HEADING.findall(f.read()))
def texts():
out = [os.path.join(WAI, "SPEC.md")]
out += sorted(os.path.join(EXT, n) for n in os.listdir(EXT) if n.endswith(".md"))
return out
def main():
files = texts()
known = {os.path.normpath(p): sections(p) for p in files}
stems = sorted((os.path.splitext(os.path.basename(p))[0] for p in files if os.path.dirname(p) == EXT),
key=len, reverse=True)
by_stem = {os.path.splitext(os.path.basename(p))[0]: os.path.normpath(p) for p in files if os.path.dirname(p) == EXT}
by_stem["SPEC"] = os.path.normpath(os.path.join(WAI, "SPEC.md"))
# A file name in prose, not inside a link target or a longer word or path.
bare = re.compile(r"(?<![\w/.(-])`?(" + "|".join(map(re.escape, stems + ["SPEC"])) + r")(?:\.md)?`?[ \t\n]+" + SECTION)
link_then = re.compile(r"\[[^\]]*\]\(([^)\s]+\.md)\)[ \t\n]*" + SECTION)
link_with = re.compile(r"\[([^\]]*?)" + SECTION + r"[^\]]*\]\(([^)\s]+\.md)\)")
findings = []
for path in files:
with open(path, encoding="utf-8") as f:
text = f.read()
here = os.path.dirname(path)
def check(target, num, at):
target = os.path.normpath(target)
if target not in known:
return # not a WAI specification text (a README, a research note)
if num not in known[target]:
line = text.count("\n", 0, at) + 1
rel = os.path.relpath(path, ROOT)
findings.append(f"{rel}:{line}: §{num} of {os.path.relpath(target, ROOT)} does not exist")
def check_range(target, m, end):
r = RANGE.match(text, end)
if r:
check(target, r.group(1), m.start())
for m in link_then.finditer(text):
target = os.path.join(here, m.group(1).split("#")[0])
check(target, m.group(2), m.start())
check_range(target, m, m.end())
for m in link_with.finditer(text):
target = os.path.join(here, m.group(3).split("#")[0])
check(target, m.group(2), m.start())
for m in bare.finditer(text):
check(by_stem[m.group(1)], m.group(2), m.start())
check_range(by_stem[m.group(1)], m, m.end())
for f in sorted(set(findings)):
print(f)
return 1 if findings else 0
if __name__ == "__main__":
sys.exit(main())