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 7s
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-app and Create / wai-app · does this change touch it (pull_request) Successful in 7s
wai-audit collector and player integration / does this change touch it (pull_request) Successful in 7s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Successful in 7s
wai cross-architecture byte-equality / does this change touch it (pull_request) Successful in 7s
WAI operation catalogue / does this change touch it (pull_request) Successful in 7s
WAI conformance / does this change touch it (pull_request) Successful in 13s
WAI energy receipts / does this change touch it (pull_request) Successful in 8s
wai-fleet service / does this change touch it (pull_request) Successful in 8s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 13s
wai formal verification (integer core) / does this change touch it (pull_request) Successful in 8s
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Successful in 12s
wai-ledger service / does this change touch it (pull_request) Successful in 10s
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Successful in 8s
WAI neural sink gates / does this change touch it (pull_request) Successful in 13s
wai-ops-npu integer operators on neural processors / does this change touch it (pull_request) Successful in 6s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 8s
wai-ops integer operators / does this change touch it (pull_request) Successful in 15s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 8s
wai-quantum for JavaScript / does this change touch it (pull_request) Successful in 13s
wai-sink-android native sink library / does this change touch it (pull_request) Successful in 8s
wai-sink-swift native sink package / does this change touch it (pull_request) Successful in 13s
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Successful in 8s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 8s
WAI Studio / does this change touch it (pull_request) Successful in 13s
wai-web wasm32 / does this change touch it (pull_request) Successful in 8s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 3m28s
wai-ops-npu integer operators on neural processors / neural processor (framework-128gb silicon) (pull_request) Successful in 13s
wai formal verification (integer core) / kani (isqrt512) (pull_request) Successful in 29m16s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (pull_request) Successful in 32s
wai-audit collector and player integration / collector · linux (pull_request) Successful in 1m17s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Successful in 32s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Failing after 1m42s
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 3m1s
wai formal verification (integer core) / kani (rans64-t2) (pull_request) Successful in 13m17s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 40s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m52s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m29s
wai-quantum studio and desktop / desktop app · windows (pull_request) Successful in 8m59s
wai formal verification (integer core) / every harness in one shard (pull_request) Successful in 24s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m28s
WAI operation catalogue / the catalogue and every door · linux (pull_request) Successful in 4m44s
wai-fleet service / service · linux (pull_request) Successful in 2m5s
wai formal verification (integer core) / kani (stage) (pull_request) Successful in 3m0s
wai formal verification (integer core) / kani (plan) (pull_request) Successful in 5m52s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 8m12s
wai-ledger service / service · linux (pull_request) Successful in 1m38s
wai formal verification (integer core) / kani (integer-core) (pull_request) Successful in 5m39s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m45s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 5m56s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 3m4s
wai-ops integer operators / linux-x86_64 (pull_request) Successful in 50s
wai-ops integer operators / wasm32-wasip2 (wasmtime) (pull_request) Successful in 30s
wai-ops integer operators / wasm32 under Node (pull_request) Successful in 21s
wai-ops integer operators / independent checker (Python) (pull_request) Successful in 12s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 12m57s
wai-pack / wai-pack · linux (pull_request) Successful in 1m43s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 15m38s
WAI neural sink gates / the exact JPEG-AI decoder reports its path (pinned inputs, required) (pull_request) Successful in 5m23s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m28s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 2m48s
wai formal verification (integer core) / kani (sound) (pull_request) Successful in 13m40s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 4m2s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 2m40s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m28s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 5m24s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 5m11s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 5m30s
wai formal verification (integer core) / kani (stage-long) (pull_request) Successful in 20m33s
wai formal verification (integer core) / kani (arith) (pull_request) Successful in 25m17s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 11m9s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (pull_request) Successful in 57s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 1m16s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 3m34s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 30s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 22s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (pull_request) Successful in 7m7s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 6m17s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 11m55s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Successful in 1m49s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 37s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 35s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m24s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 16m11s
wai-fleet service / service · macos (pull_request) Successful in 2m5s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 9m26s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 12m23s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 12s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 34s
wai-ledger service / service · macos (pull_request) Successful in 1m8s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 18m20s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m8s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 20m55s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 6m35s
wai-ops-npu integer operators on neural processors / builds · no device is not a pass (linux-arm64) (pull_request) Successful in 21s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 16m58s
wai-ops integer operators / macos-arm64 (pull_request) Successful in 1m0s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m56s
wai-pack / wai-pack · macos (pull_request) Successful in 3m19s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 26s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 14s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 12m3s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 1m11s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 13m4s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m46s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 5m19s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 9m20s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 8m15s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 11m44s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 18m0s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h30m13s
The change of wai/neural-corpus-licence (44d5f2264..6bddde42d, 5 commits), on the fix branch: its changelog entries as files of wai/changes/, its wai-conformance.yml edits as step files, corpus files and test tags, and every other file as the branch has it. - 40052a902 wai: the trained int_synth vector's tool generates its own pictures from a seed - c86d58210 wai: neural-conformance's photo, trained and coded on generated pictures - 4321d68cc wai: every neural-conformance vector has a licence record, and a lint requires one - 63aea099a wai: photo's licence record gives its training pictures as streams 1 to 512 - 6bddde42d wai: the trained int_synth vector's check holds its licence record to meta.json Co-Authored-By: Claude Opus 5.5 <[email protected]>
171 lines
7.5 KiB
Python
Executable file
171 lines
7.5 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""check-wai-corpus-licences.py: every vector of a WAI corpus that keeps licence records
|
|
has one, and every record states a licence that permits redistribution.
|
|
|
|
A corpus listed in CORPORA keeps `licences.json` beside its README:
|
|
|
|
{"format": "wai-corpus-licences/1",
|
|
"vectors": {"<name>": {"licence": "<SPDX id>", "content": "generated" | "third-party",
|
|
"generator": "<path below wai/>", "input": "<what it reads>",
|
|
"source": "<where a third-party input comes from>",
|
|
"training": {"content": ..., "generator": ..., "input": ...,
|
|
"source": ..., "licence": ...}}}}
|
|
|
|
What each corpus is held to:
|
|
|
|
1. `licences.json` exists, parses, and has this format.
|
|
2. Every vector has a record: each directory under `vectors/`, and each name in the
|
|
corpus's `expected_hashes.json` and `sha256.json`, is a key of `vectors`. Every key
|
|
names a directory under `vectors/`.
|
|
3. `licence` is one of LICENCES, the licences that permit redistribution.
|
|
4. `content` "generated" names a `generator` that exists below `wai/` and a non-empty
|
|
`input`, and no `source`. `content` "third-party" names a non-empty `source`; its
|
|
`licence` is the source's, and any `generator` it names exists.
|
|
5. A vector whose `expected_hashes.json` entry has `"trained": true` has a `training`
|
|
record, held to rule 4, whose `licence`, required when its content is third-party,
|
|
is one of LICENCES; a vector not marked trained has none.
|
|
6. A record has no member other than these.
|
|
|
|
The check holds what the records state, not their truth: that is a reviewer's, and for
|
|
`neural-conformance`'s trained vector also `tools/wai_int_synth_real.py --check`'s.
|
|
|
|
check-wai-corpus-licences.py [--root DIR]
|
|
|
|
Exit 0 when every corpus holds, printing each corpus's vectors by licence; 1 with one
|
|
line a finding otherwise. Standard library only.
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
# The corpora that keep a licence record for each vector, relative to the root.
|
|
CORPORA = ["wai/neural-conformance"]
|
|
|
|
FORMAT = "wai-corpus-licences/1"
|
|
|
|
# SPDX identifiers of the licences a committed vector, or the data a committed model was
|
|
# trained on, may carry: each permits redistribution.
|
|
LICENCES = {"Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "CC-BY-4.0", "CC0-1.0", "MIT"}
|
|
|
|
VECTOR_KEYS = {"licence", "content", "generator", "input", "source", "training"}
|
|
TRAINING_KEYS = {"content", "generator", "input", "source", "licence"}
|
|
|
|
|
|
def names_in(path):
|
|
"""The top-level keys of a JSON object file, or None when the file does not exist."""
|
|
if not os.path.exists(path):
|
|
return None
|
|
with open(path, encoding="utf-8") as fh:
|
|
doc = json.load(fh)
|
|
return doc if isinstance(doc, dict) else {}
|
|
|
|
|
|
def nonempty(v):
|
|
return isinstance(v, str) and v.strip() != ""
|
|
|
|
|
|
def check_content(root, where, rec, findings):
|
|
"""Rule 4, for a vector record or a training record."""
|
|
content = rec.get("content")
|
|
gen = rec.get("generator")
|
|
if gen is not None and not (nonempty(gen) and os.path.isfile(os.path.join(root, "wai", gen))):
|
|
findings.append(f"{where}: generator {gen!r} is not a file below wai/")
|
|
if content == "generated":
|
|
if gen is None:
|
|
findings.append(f"{where}: generated content names no generator")
|
|
if not nonempty(rec.get("input")):
|
|
findings.append(f"{where}: generated content names no input")
|
|
if "source" in rec:
|
|
findings.append(f"{where}: generated content has a source")
|
|
elif content == "third-party":
|
|
if not nonempty(rec.get("source")):
|
|
findings.append(f"{where}: third-party content names no source")
|
|
else:
|
|
findings.append(f"{where}: content {content!r} is neither \"generated\" nor \"third-party\"")
|
|
|
|
|
|
def check_corpus(root, corpus, findings, split):
|
|
base = os.path.join(root, corpus)
|
|
path = os.path.join(base, "licences.json")
|
|
if not os.path.isfile(path):
|
|
findings.append(f"{corpus}: no licences.json")
|
|
return
|
|
try:
|
|
with open(path, encoding="utf-8") as fh:
|
|
doc = json.load(fh)
|
|
except (OSError, ValueError) as e:
|
|
findings.append(f"{corpus}/licences.json: does not parse: {e}")
|
|
return
|
|
if not isinstance(doc, dict) or doc.get("format") != FORMAT or not isinstance(doc.get("vectors"), dict):
|
|
findings.append(f"{corpus}/licences.json: not a {FORMAT} document with a `vectors` object")
|
|
return
|
|
records = doc["vectors"]
|
|
vdir = os.path.join(base, "vectors")
|
|
dirs = sorted(d for d in os.listdir(vdir) if os.path.isdir(os.path.join(vdir, d))) if os.path.isdir(vdir) else []
|
|
try:
|
|
hashes = names_in(os.path.join(base, "expected_hashes.json")) or {}
|
|
sha = names_in(os.path.join(base, "sha256.json")) or {}
|
|
except ValueError as e:
|
|
findings.append(f"{corpus}: a hash manifest does not parse: {e}")
|
|
return
|
|
for name in sorted(set(dirs) | set(hashes) | set(sha)):
|
|
if name not in records:
|
|
findings.append(f"{corpus}: vector {name} has no licence record")
|
|
for name in sorted(records):
|
|
where = f"{corpus}/licences.json: {name}"
|
|
rec = records[name]
|
|
if name not in dirs:
|
|
findings.append(f"{where}: no directory vectors/{name}")
|
|
if not isinstance(rec, dict):
|
|
findings.append(f"{where}: not an object")
|
|
continue
|
|
for k in sorted(set(rec) - VECTOR_KEYS):
|
|
findings.append(f"{where}: unknown member {k!r}")
|
|
lic = rec.get("licence")
|
|
if lic not in LICENCES:
|
|
findings.append(f"{where}: licence {lic!r} is not one of {', '.join(sorted(LICENCES))}")
|
|
check_content(root, where, rec, findings)
|
|
trained = isinstance(hashes.get(name), dict) and hashes[name].get("trained") is True
|
|
tr = rec.get("training")
|
|
if trained and tr is None:
|
|
findings.append(f"{where}: a trained model with no training record")
|
|
elif not trained and tr is not None:
|
|
findings.append(f"{where}: a training record on a vector whose model is not marked trained")
|
|
if isinstance(tr, dict):
|
|
tw = where + " training"
|
|
for k in sorted(set(tr) - TRAINING_KEYS):
|
|
findings.append(f"{tw}: unknown member {k!r}")
|
|
check_content(root, tw, tr, findings)
|
|
if (tr.get("content") == "third-party" or "licence" in tr) and tr.get("licence") not in LICENCES:
|
|
findings.append(f"{tw}: licence {tr.get('licence')!r} is not one of {', '.join(sorted(LICENCES))}")
|
|
elif tr is not None:
|
|
findings.append(f"{where}: training is not an object")
|
|
if lic in LICENCES:
|
|
split.setdefault(corpus, {}).setdefault(lic, []).append(name)
|
|
|
|
|
|
def main(argv):
|
|
root = "."
|
|
args = argv[1:]
|
|
if args[:1] == ["--root"] and len(args) == 2:
|
|
root = args[1]
|
|
elif args:
|
|
print("usage: check-wai-corpus-licences.py [--root DIR]", file=sys.stderr)
|
|
return 2
|
|
findings, split = [], {}
|
|
for corpus in CORPORA:
|
|
check_corpus(root, corpus, findings, split)
|
|
for f in findings:
|
|
print(f)
|
|
if findings:
|
|
print(f"check-wai-corpus-licences: {len(findings)} finding(s)")
|
|
return 1
|
|
for corpus in CORPORA:
|
|
for lic, names in sorted(split.get(corpus, {}).items()):
|
|
print(f"{corpus}: {lic}: {', '.join(names)}")
|
|
print("check-wai-corpus-licences: every vector has a licence record")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv))
|