Some checks failed
joule-moq-remote host agent / joule-moq-remote · does this change touch it (pull_request) Successful in 8s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 9s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 7s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 8s
wai-audit collector and player integration / does this change touch it (pull_request) Successful in 7s
WAI operation catalogue / does this change touch it (pull_request) Successful in 8s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Successful in 9s
WAI conformance / does this change touch it (pull_request) Successful in 9s
wai-app and Create / wai-app · does this change touch it (pull_request) Successful in 20s
wai-fleet service / does this change touch it (pull_request) Successful in 10s
wai-ledger service / does this change touch it (pull_request) Successful in 11s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 14s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 8s
WAI energy receipts / does this change touch it (pull_request) Successful in 19s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 8s
wai-sink-android native sink library / does this change touch it (pull_request) Successful in 10s
WAI Studio / does this change touch it (pull_request) Successful in 9s
wai-sink-swift native sink package / does this change touch it (pull_request) Successful in 9s
wai-web wasm32 / does this change touch it (pull_request) Successful in 8s
wai-quantum for JavaScript / does this change touch it (pull_request) Successful in 24s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 21s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 4m33s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Successful in 1m50s
wai-quantum studio and desktop / desktop app · windows (pull_request) Successful in 10m8s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 38s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (pull_request) Successful in 39s
wai-audit collector and player integration / collector · linux (pull_request) Successful in 5m23s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m32s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m18s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (pull_request) Successful in 3m50s
WAI operation catalogue / the catalogue and every door · linux (pull_request) Successful in 6m15s
wai-pack / wai-pack · linux (pull_request) Successful in 1m44s
wai-fleet service / service · linux (pull_request) Successful in 2m51s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 54s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m26s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 4m23s
wai-ledger service / service · linux (pull_request) Successful in 7m25s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 5m58s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m27s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 10m37s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 9m11s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 14m35s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 10m53s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 13m10s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 13m0s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (pull_request) Successful in 1m19s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Successful in 1m40s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 31s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m53s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m20s
wai-fleet service / service · macos (pull_request) Successful in 58s
wai-ledger service / service · macos (pull_request) Successful in 1m11s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (pull_request) Successful in 8m27s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 18m13s
wai-pack / wai-pack · macos (pull_request) Successful in 3m25s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 16m29s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 7m3s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 18m13s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m42s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 10m42s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 18m58s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 24m5s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 17m33s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 1m21s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 19s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 3m39s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 11m56s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 35s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 16m9s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 16m19s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 47s
wai-pack / wai-pack · linux-arm64 (pull_request) Failing after 7h34m11s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Failing after 7h34m29s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Failing after 7h34m55s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Failing after 7h49m22s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 36s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 47s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m34s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
The registry's unregistered labels now hold every wai.quantum string the tree uses that no revision registers, each saying what it names, grouped: the receipt kinds, the modules of wai-quantum, the names a record's members carry, the fabric's kernels and corpora, the circuit contracts' revisions, the documents with no schema file, the digest domains, and the strings the tests and the provider corpus give a reader to see it refuse them. A document's name, wai.quantum.<document>/<major>, is accounted for by its schema file (schemas/<document>.v<major>.json, its title the name) and needs no row. scripts/check-wai-quantum-names.py reads the registry export and the schema files and every text file but the changelog, and names the file and line of any string neither accounts for; it also fails on a pattern that matches nothing, a schema file whose title is not its file's name, a quantum label nothing outside the registry uses, and a string held twice. The repository checks run it and its self-test. The wai-quantum constants test compares the receipt kinds alone, and the registry test refuses a label listed twice. Co-Authored-By: Claude Opus 5.5 <[email protected]>
216 lines
9 KiB
Python
Executable file
216 lines
9 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""check-wai-quantum-names.py: every `wai.quantum.*` string in the tree is accounted for.
|
|
|
|
A string of the quantum namespace is one of:
|
|
|
|
- a string the registry registers (a capability or a record), or one of its named
|
|
identifiers, unregistered labels or wire identifiers. The registry is one table,
|
|
wai/wai-rs/src/codecs/registry.rs, exported by `wai registry export` as
|
|
wai/registry/capabilities.json (CI holds the export to the table with
|
|
`wai registry export --check`). This reads the export. A label there says what it
|
|
names: a module of the quantum crates, a receipt kind, a kernel, a document with no
|
|
schema file, or a string a test gives a reader to see it refused.
|
|
- the name of a document a quantum crate writes, `wai.quantum.<document>/<major>`,
|
|
kept as a JSON Schema at `schemas/<document>.v<major>.json` beside the crate's
|
|
manifest, whose `title` is the name (wai/wai-quantum/VERSIONING.md, *The schemas*).
|
|
A name such a file gives as the `const` of a member (a document carried inside
|
|
another) is accounted for the same way. The schema files are the list: a new
|
|
document adds its file, and no line anywhere else.
|
|
|
|
A string is `wai.quantum.` followed by dot-separated segments of letters, digits, `_`
|
|
and `-`, and optionally `/` and a revision (`wai.quantum.circuit2`,
|
|
`wai.quantum.cal.noise_learn`, `wai.quantum.job-result/1`, `wai.quantum.sv/run-wide`).
|
|
A pattern `wai.quantum.<segments>.*` is accounted for when some accounted string starts
|
|
with `wai.quantum.<segments>.`. A placeholder (`wai.quantum.<document>`) or a prefix
|
|
(`"wai.quantum."`) is not a string and is not read.
|
|
|
|
Every text file git tracks or would track is read, except the changelog
|
|
(wai/CHANGELOG.md and the entry files of wai/changes/): it records names as they were
|
|
when each change was made. Binary files are not read.
|
|
|
|
Findings, one line each:
|
|
|
|
- a string accounted for by none of the above, with its file and line;
|
|
- a quantum schema file whose `title` is not the name its file name gives;
|
|
- a `wai.quantum.*` label or wire identifier that nothing outside the registry's own
|
|
files (registry.rs, its export, REGISTRY.md) uses, so the list stays the set of
|
|
strings in use;
|
|
- a `wai.quantum.*` string the registry holds twice.
|
|
|
|
check-wai-quantum-names.py [--root DIR]
|
|
|
|
Exit 0 when every string is accounted for, 1 with one line a finding otherwise, 2 when
|
|
the tree cannot be read. Standard library only.
|
|
"""
|
|
import json
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
PREFIX = "wai.quantum."
|
|
# A string of the namespace, with its revision and a trailing `.*` (a pattern).
|
|
TOKEN = re.compile(
|
|
r"wai\.quantum\.([A-Za-z0-9_][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_][A-Za-z0-9_-]*)*)"
|
|
r"(/[A-Za-z0-9_-]+)?(\.\*)?"
|
|
)
|
|
EXPORT = "wai/registry/capabilities.json"
|
|
# The registry's own files: the table, its export and the page that prints it.
|
|
REGISTRY_FILES = {"wai/wai-rs/src/codecs/registry.rs", EXPORT, "wai/REGISTRY.md"}
|
|
# The record of past changes, read by nothing here.
|
|
HISTORY = ("wai/CHANGELOG.md", "wai/changes/")
|
|
SCHEMA_FILE = re.compile(r"(?:^|/)schemas/([a-z0-9_-]+(?:\.[a-z0-9_-]+)*)\.v([0-9]+)\.json$")
|
|
|
|
|
|
def fail(msg):
|
|
print(f"check-wai-quantum-names: {msg}", file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
|
|
def git(root, *args):
|
|
r = subprocess.run(["git", "-C", root, *args], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
return r.returncode, r.stdout.decode("utf-8", "replace"), r.stderr.decode("utf-8", "replace")
|
|
|
|
|
|
def occurrences(root):
|
|
"""Every string of the namespace in the text files git tracks or would track:
|
|
[(path, line, string, is_pattern)]."""
|
|
rc, out, err = git(root, "grep", "-I", "-n", "-z", "--untracked", "-F", "-e", PREFIX)
|
|
if rc == 1:
|
|
return []
|
|
if rc != 0:
|
|
fail(f"git grep failed ({rc}): {err.strip()}")
|
|
found = []
|
|
for rec in out.split("\n"):
|
|
if not rec:
|
|
continue
|
|
parts = rec.split("\0", 2)
|
|
if len(parts) != 3:
|
|
fail(f"unreadable git grep line: {rec[:120]!r}")
|
|
path, line, text = parts
|
|
if path == HISTORY[0] or path.startswith(HISTORY[1]):
|
|
continue
|
|
for m in TOKEN.finditer(text):
|
|
name = PREFIX + m.group(1) + (m.group(2) or "")
|
|
found.append((path, int(line), name, bool(m.group(3))))
|
|
return found
|
|
|
|
|
|
def registry(root):
|
|
"""The strings the export holds, by table, and the quantum strings it holds twice."""
|
|
path = os.path.join(root, EXPORT)
|
|
try:
|
|
with open(path, encoding="utf-8") as fh:
|
|
doc = json.load(fh)
|
|
except (OSError, ValueError) as e:
|
|
fail(f"cannot read {EXPORT}: {e}")
|
|
tables = {
|
|
"registered": [c["capability"] for c in doc.get("capabilities", [])],
|
|
"identifier": [i["identifier"] for i in doc.get("identifiers", [])],
|
|
"label": [l["label"] for l in doc.get("unregistered_labels", [])],
|
|
"wire identifier": [w["name"] for w in doc.get("wire_identifiers", [])],
|
|
}
|
|
if not tables["registered"]:
|
|
fail(f"{EXPORT} registers nothing")
|
|
held = {}
|
|
twice = []
|
|
for table, names in tables.items():
|
|
for n in names:
|
|
if n.startswith(PREFIX):
|
|
if n in held:
|
|
twice.append(f"{EXPORT}: {n} is held twice ({held[n]}, {table})")
|
|
held.setdefault(n, table)
|
|
return tables, held, twice
|
|
|
|
|
|
def schema_names(root):
|
|
"""The document names the quantum schema files give, and the findings about them."""
|
|
rc, out, err = git(root, "ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", "wai/")
|
|
if rc != 0:
|
|
fail(f"git ls-files failed ({rc}): {err.strip()}")
|
|
names, findings = {}, []
|
|
|
|
def consts(v, acc):
|
|
if isinstance(v, dict):
|
|
for k, x in v.items():
|
|
if k == "const" and isinstance(x, str):
|
|
acc.append(x)
|
|
else:
|
|
consts(x, acc)
|
|
elif isinstance(v, list):
|
|
for x in v:
|
|
consts(x, acc)
|
|
|
|
for path in sorted(p for p in out.split("\0") if p):
|
|
m = SCHEMA_FILE.search(path)
|
|
if not m or not os.path.isfile(os.path.join(root, path)):
|
|
continue
|
|
try:
|
|
with open(os.path.join(root, path), encoding="utf-8") as fh:
|
|
doc = json.load(fh)
|
|
except (OSError, ValueError) as e:
|
|
findings.append(f"{path}: not a JSON document ({e})")
|
|
continue
|
|
title = doc.get("title") if isinstance(doc, dict) else None
|
|
if not (isinstance(title, str) and title.startswith(PREFIX)):
|
|
continue
|
|
want = f"{PREFIX}{m.group(1)}/{m.group(2)}"
|
|
if title != want:
|
|
findings.append(f"{path}: its title is {title}, but a schema of that file is named {want}")
|
|
continue
|
|
names.setdefault(title, path)
|
|
acc = []
|
|
consts(doc, acc)
|
|
for c in acc:
|
|
t = TOKEN.fullmatch(c)
|
|
if t and not t.group(3):
|
|
names.setdefault(c, path)
|
|
return names, findings
|
|
|
|
|
|
def main(argv):
|
|
root = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
|
|
if len(argv) == 2 and argv[0] == "--root":
|
|
root = os.path.abspath(argv[1])
|
|
elif argv:
|
|
fail("usage: check-wai-quantum-names.py [--root DIR]")
|
|
tables, held, findings = registry(root)
|
|
accounted = {n for names in tables.values() for n in names}
|
|
schemas, schema_findings = schema_names(root)
|
|
findings += schema_findings
|
|
accounted |= set(schemas)
|
|
|
|
used_outside = set()
|
|
seen = 0
|
|
for path, line, name, pattern in occurrences(root):
|
|
seen += 1
|
|
if path not in REGISTRY_FILES:
|
|
used_outside.add(name)
|
|
if pattern:
|
|
stem = name + "."
|
|
if not any(a.startswith(stem) for a in accounted):
|
|
findings.append(f"{path}:{line}: {name}.* matches no registered string, label or schema's name")
|
|
continue
|
|
if name not in accounted:
|
|
findings.append(f"{path}:{line}: {name} is not registered, listed as a label or wire identifier, "
|
|
f"or the name of a quantum schema file")
|
|
for n, table in sorted(held.items()):
|
|
if table in ("label", "wire identifier") and n not in used_outside:
|
|
findings.append(f"{EXPORT}: the {table} {n} is used nowhere outside the registry's own files")
|
|
|
|
if findings:
|
|
for f in findings:
|
|
print(f)
|
|
sys.stdout.flush()
|
|
print(f"\n{len(findings)} finding(s). A new `wai.quantum.*` string is registered, or listed with what it "
|
|
"names in UNREGISTERED_LABELS (wai/wai-rs/src/codecs/registry.rs, beside its group), then "
|
|
"`wai registry export` is run; a document's name is its schema file "
|
|
"(`schemas/<document>.v<major>.json`, its `title` the name).", file=sys.stderr)
|
|
return 1
|
|
print(f"check-wai-quantum-names: every wai.quantum string is accounted for "
|
|
f"({seen} occurrences read; {len(schemas)} named by schema files)")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv[1:]))
|