| |
| """Offline integrity checks for the l35QweVxgn static candidate.""" |
|
|
| from __future__ import annotations |
|
|
| import hashlib |
| import json |
| import re |
| import stat |
| import sys |
| from html.parser import HTMLParser |
| from pathlib import Path |
|
|
|
|
| ROOT = Path(__file__).resolve().parents[1] |
| ALLOWED = { |
| "README.md", |
| "index.html", |
| "docs/reproducibility-audit.md", |
| "evidence/active_claims.json", |
| "evidence/pins.json", |
| "evidence/repository_tree.json", |
| "evidence/route.json", |
| "evidence/safety_screen.json", |
| "pages/01-overview.md", |
| "pages/02-judge-claims.md", |
| "pages/03-paper-proof-audit.md", |
| "pages/04-release-code-audit.md", |
| "pages/05-safety-and-licence.md", |
| "pages/06-evidence-boundaries.md", |
| "scripts/test_verifier.py", |
| "scripts/verify_release.py", |
| } |
| ACTIVE_CLAIMS_SHA256 = "9f6c6afb77f9c65abe1d162f8c0ebd2d2cac24d41f622510b7eacc3af2241885" |
| CHALLENGE_REVISION = "7b5b56aebf3abe590eab9f2c241a796125cab928" |
| PAPER_ID = "l35QweVxgn" |
| SPACE_CARD = """--- |
| title: Continual Learning Theory Evidence |
| emoji: "🔎" |
| colorFrom: blue |
| colorTo: indigo |
| sdk: static |
| app_file: index.html |
| tags: |
| - icml2026-repro |
| - paper-l35QweVxgn |
| - source-proof-audit |
| - continual-learning-theory |
| --- |
| |
| """ |
| README_BODY_SHA256 = "dc607bc0cd2114f0005f1e2e08b2cb8bba0b00b76841b3d8c7f8680497027322" |
| EXPECTED_PINS = { |
| "paper": { |
| "openreview_id": PAPER_ID, |
| "openreview_pdf_url": "https://openreview.net/pdf?id=l35QweVxgn", |
| "title": "On the Theory of Continual Learning with Gradient Descent for Neural Networks", |
| "authors": ["Hossein Taheri", "Avishek Ghosh", "Arya Mazumdar"], |
| "direct_openreview_access": "challenge-gated from this machine; official search index exposed the current PDF text", |
| "author_preprint": { |
| "url": "https://arxiv.org/abs/2510.05573v2", |
| "source_url": "https://arxiv.org/e-print/2510.05573v2", |
| "source_sha256": "c9e327f4e26929d282b9481af3a6fc884e387fc08a48a344dfc38b7f95d587c5", |
| "main_tex_sha256": "23fc0c0daefd957095a412d6d6e08f8d03ac22b3128096b939b8ed10535202d3", |
| "metadata_sha256": "13531c175594e0bc3c804e75b0c3df29980fc8909991a02481c0081ab755d4f6", |
| }, |
| }, |
| "judge_feeds": { |
| "challenge_space_revision": CHALLENGE_REVISION, |
| "default": { |
| "url": "https://huggingface.co/spaces/ICML-2026-agent-repro/challenge/resolve/7b5b56aebf3abe590eab9f2c241a796125cab928/claims.json", |
| "sha256": "af5ab2d62f786ae36861957cbd08b4188f6d4c86e67152becc661a9c5bbb9d57", |
| "paper_claim_count": 2, |
| }, |
| "anchored": { |
| "url": "https://huggingface.co/spaces/ICML-2026-agent-repro/challenge/resolve/7b5b56aebf3abe590eab9f2c241a796125cab928/claims_anchored.json", |
| "sha256": "eb3f2d878646ca5c40da121741a613c1f9e1e10c14845f373db107e74a4ef439", |
| "paper_claim_count": 6, |
| }, |
| "merge": "anchored_overrides_default", |
| "active_source": "claims_anchored.json", |
| }, |
| "retrieved_utc": "2026-07-19T21:15:00Z", |
| } |
| EXPECTED_REPOSITORY_TREE = { |
| "repository": "https://github.com/hosseinta2/continual-learning-with-neural-nets.git", |
| "commit": "5e7329081bc948d4aa4159def5feed50160411b1", |
| "commit_time": "2025-11-20T13:44:57-08:00", |
| "tracked_file_count": 5, |
| "tracked_files": [ |
| {"path": "FashionMNIST", "git_blob": "5bf6480c3000ec007946bb325805fbd07a2d8ec2", "sha256": "aebd6e8561d21bdbfb5ba968c23ad96c8327da2f94ae7d8dc519686fdd4467c6"}, |
| {"path": "README.md", "git_blob": "ac23a6611a1f0392d9b180a3ae3e1221f236c038", "sha256": "7a482f22fbf823ae60f50ba4a3d53bf344670839fddfdbce24ddc89abe35c300"}, |
| {"path": "continual learning codes MNIST-2.ipynb", "git_blob": "5ce1279ccb62af755e019ab807b59021ede88869"}, |
| {"path": "continual learning codes_transformer-2.ipynb", "git_blob": "4309d3baca18e26637edb9fbd33fb129bd1a3448"}, |
| {"path": "continual_learning_codes-XOR.ipynb", "git_blob": "dd0c846b9e761016de0632800dd8b0d57a0cc5cb"}, |
| ], |
| "licence_status": "no licence, copying, or notice file found in the tracked tree; author material is not redistributed", |
| } |
| ALLOWED_HTML_TAGS = {"html", "head", "meta", "title", "body", "main", "h1", "p", "ul", "li", "a"} |
| ALLOWED_PAGE_LINKS = { |
| "pages/01-overview.md", |
| "pages/02-judge-claims.md", |
| "pages/03-paper-proof-audit.md", |
| "pages/04-release-code-audit.md", |
| "pages/05-safety-and-licence.md", |
| "pages/06-evidence-boundaries.md", |
| } |
|
|
|
|
| def fail(message: str) -> None: |
| raise AssertionError(message) |
|
|
|
|
| class InertHtmlPolicyParser(HTMLParser): |
| """Accept only the deliberately small, local static-document subset.""" |
|
|
| def __init__(self) -> None: |
| super().__init__(convert_charrefs=True) |
| self.stack: list[str] = [] |
| self.saw_doctype = False |
|
|
| def handle_decl(self, declaration: str) -> None: |
| if self.saw_doctype or declaration.lower() != "doctype html": |
| fail("index.html has an invalid declaration") |
| self.saw_doctype = True |
|
|
| def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: |
| if tag not in ALLOWED_HTML_TAGS: |
| fail(f"index.html has forbidden tag: {tag}") |
| values: dict[str, str | None] = {} |
| for name, value in attrs: |
| if name.startswith("on"): |
| fail(f"index.html has event-handler attribute: {name}") |
| if name in values: |
| fail(f"index.html repeats attribute: {name}") |
| values[name] = value |
| self.verify_attributes(tag, values) |
| if tag != "meta": |
| self.stack.append(tag) |
|
|
| def handle_endtag(self, tag: str) -> None: |
| if tag == "meta" or not self.stack or self.stack[-1] != tag: |
| fail(f"index.html has invalid closing tag: {tag}") |
| self.stack.pop() |
|
|
| def handle_startendtag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: |
| fail(f"index.html has self-closing tag: {tag}") |
|
|
| def handle_comment(self, data: str) -> None: |
| fail("index.html has comments") |
|
|
| def handle_pi(self, data: str) -> None: |
| fail("index.html has a processing instruction") |
|
|
| def unknown_decl(self, data: str) -> None: |
| fail("index.html has an unknown declaration") |
|
|
| def verify_attributes(self, tag: str, values: dict[str, str | None]) -> None: |
| if tag == "html": |
| if values != {"lang": "en"}: |
| fail("index.html html attributes differ from the inert policy") |
| elif tag == "meta": |
| if values not in ({"charset": "utf-8"}, {"name": "viewport", "content": "width=device-width, initial-scale=1"}): |
| fail("index.html meta attributes differ from the inert policy") |
| elif tag == "a": |
| if set(values) != {"href"} or values["href"] not in ALLOWED_PAGE_LINKS: |
| fail("index.html link is not an allowlisted local evidence page") |
| elif values: |
| fail(f"index.html tag has forbidden attributes: {tag}") |
|
|
| def verify_complete(self) -> None: |
| if not self.saw_doctype: |
| fail("index.html is missing the HTML doctype") |
| if self.stack: |
| fail(f"index.html has unclosed tags: {self.stack}") |
|
|
|
|
| def release_files() -> set[str]: |
| found: set[str] = set() |
| for path in ROOT.rglob("*"): |
| relative = path.relative_to(ROOT) |
| if relative.parts and relative.parts[0] == ".git": |
| continue |
| if path.is_symlink(): |
| fail(f"symlink not allowed: {relative}") |
| if path.is_file(): |
| if not stat.S_ISREG(path.stat().st_mode): |
| fail(f"non-regular file not allowed: {relative}") |
| if path.stat().st_mode & 0o111: |
| fail(f"executable bit not allowed: {relative}") |
| found.add(relative.as_posix()) |
| return found |
|
|
|
|
| def verify_allowlist() -> None: |
| found = release_files() |
| unexpected = sorted(found - ALLOWED) |
| missing = sorted(ALLOWED - found) |
| if unexpected: |
| fail(f"unexpected release files: {unexpected}") |
| if missing: |
| fail(f"missing release files: {missing}") |
|
|
|
|
| def verify_claims() -> None: |
| path = ROOT / "evidence/active_claims.json" |
| digest = hashlib.sha256(path.read_bytes()).hexdigest() |
| if digest != ACTIVE_CLAIMS_SHA256: |
| fail("active claims digest does not match the pinned extraction") |
| claims = json.loads(path.read_text(encoding="utf-8")) |
| if claims.get("paper_id") != PAPER_ID: |
| fail("active claims paper id mismatch") |
| if claims.get("source") != "claims_anchored.json": |
| fail("active claims source is not anchored") |
| if claims.get("challenge_revision") != CHALLENGE_REVISION: |
| fail("active claims revision mismatch") |
| records = claims.get("claims") |
| if not isinstance(records, list) or len(records) != 6: |
| fail("expected exactly six active anchored claims") |
| if any(record.get("status") != "unverified" for record in records): |
| fail("active statuses must remain unverified") |
|
|
|
|
| def verify_space_card() -> None: |
| readme = (ROOT / "README.md").read_text(encoding="utf-8") |
| if not readme.startswith(SPACE_CARD): |
| fail("README.md does not contain the expected static Space card") |
| body = readme.removeprefix(SPACE_CARD) |
| if hashlib.sha256(body.encode("utf-8")).hexdigest() != README_BODY_SHA256: |
| fail("README.md body differs from the reviewed scientific boundary") |
|
|
|
|
| def verify_pins() -> None: |
| pins = json.loads((ROOT / "evidence/pins.json").read_text(encoding="utf-8")) |
| if pins != EXPECTED_PINS: |
| fail("immutable provenance pins differ from the expected manifest") |
|
|
|
|
| def verify_pages_and_html() -> None: |
| for page in sorted((ROOT / "pages").glob("*.md")): |
| stripped = re.sub(r"\s+", "", page.read_text(encoding="utf-8")) |
| if len(stripped) < 200: |
| fail(f"page below 200 stripped characters: {page.name}") |
| parser = InertHtmlPolicyParser() |
| parser.feed((ROOT / "index.html").read_text(encoding="utf-8")) |
| parser.close() |
| parser.verify_complete() |
|
|
|
|
| def verify_fixed_outcomes() -> None: |
| tree = json.loads((ROOT / "evidence/repository_tree.json").read_text(encoding="utf-8")) |
| safety = json.loads((ROOT / "evidence/safety_screen.json").read_text(encoding="utf-8")) |
| route = json.loads((ROOT / "evidence/route.json").read_text(encoding="utf-8")) |
| if tree != EXPECTED_REPOSITORY_TREE: |
| fail("repository provenance and five-file inventory differ from the expected manifest") |
| if safety.get("decision") != "admitted_static_only": |
| fail("safety decision mismatch") |
| if route.get("execution") != "not attempted": |
| fail("execution boundary mismatch") |
| if route.get("route") != "source_and_proof_audit_only": |
| fail("route boundary mismatch") |
|
|
|
|
| def main() -> int: |
| verify_allowlist() |
| verify_claims() |
| verify_space_card() |
| verify_pins() |
| verify_pages_and_html() |
| verify_fixed_outcomes() |
| print("PASS: static candidate integrity verified offline") |
| return 0 |
|
|
|
|
| if __name__ == "__main__": |
| try: |
| raise SystemExit(main()) |
| except AssertionError as error: |
| print(f"FAIL: {error}", file=sys.stderr) |
| raise SystemExit(1) |
|
|