Download scripts/provenance_check.py from logos42/headless: direct link, hf CLI and curl.
- Browser
- Download file 5.34 kB
-
https://huggingface.co/logos42/headless/resolve/main/scripts/provenance_check.py
- Command line
-
hf download hf://logos42/headless/scripts/provenance_check.py
-
curl -L -o provenance_check.py https://huggingface.co/logos42/headless/resolve/main/scripts/provenance_check.py
5.34 kB
| from __future__ import annotations | |
| # llm-wiki-version: 2.0.0 | |
| # runtime: dev-only (needs PROJECT_RAW_ROOT pointing at real raw files) | |
| # Use --ci to skip raw-file resolution and only verify that source_hash is | |
| # present in every non-session page. That sub-check is safe to run in CI. | |
| import argparse | |
| import csv | |
| import hashlib | |
| import os | |
| import re | |
| import sys | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parents[1] | |
| WIKI_ROOT = ROOT / "docs" / "wiki" | |
| MANIFEST = ROOT / "manifests" / "raw_sources.csv" | |
| FRONTMATTER_RE = re.compile(r"^---\n(.*?)\n---", re.DOTALL) | |
| SOURCE_HASH_RE = re.compile(r"source_hash:\s*([a-f0-9]{12,})") | |
| SKIP_FILES = {"index.md", "log.md", "README.md", "SCHEMA.md"} | |
| def file_hash(path: Path) -> str: | |
| h = hashlib.sha256() | |
| with open(path, "rb") as f: | |
| for chunk in iter(lambda: f.read(8192), b""): | |
| h.update(chunk) | |
| return h.hexdigest()[:16] | |
| def load_manifest_paths() -> dict[str, Path]: | |
| if not MANIFEST.exists(): | |
| return {} | |
| raw_root_env = os.environ.get("PROJECT_RAW_ROOT") | |
| raw_root = Path(raw_root_env).expanduser().resolve() if raw_root_env else None | |
| result: dict[str, Path] = {} | |
| with MANIFEST.open("r", encoding="utf-8-sig", newline="") as f: | |
| for row in csv.DictReader(f): | |
| sid = (row.get("source_id") or "").strip() | |
| rel = (row.get("raw_rel_path") or "").strip() | |
| if sid and rel and raw_root: | |
| result[sid] = (raw_root / rel).resolve() | |
| return result | |
| def main() -> int: | |
| parser = argparse.ArgumentParser(description="Verify wiki pages reflect current raw sources.") | |
| parser.add_argument("--ci", action="store_true", | |
| help="Skip raw-file resolution; only verify that every non-session " | |
| "page has a source_hash field. Safe to run without raw files.") | |
| args = parser.parse_args() | |
| # Explicit opt-in only. Don't auto-detect generic CI=true — users may | |
| # mount raw files in CI and want the full check. | |
| ci_mode = args.ci or os.environ.get("LLM_WIKI_CI") == "1" | |
| if not WIKI_ROOT.exists(): | |
| print("provenance_check: docs/wiki does not exist") | |
| return 1 | |
| manifest_paths = {} if ci_mode else load_manifest_paths() | |
| checked = 0 | |
| fresh = 0 | |
| stale: list[tuple[str, str, str]] = [] | |
| no_hash: list[str] = [] | |
| unresolved: list[str] = [] | |
| session_exempt = 0 | |
| for path in sorted(WIKI_ROOT.rglob("*.md")): | |
| if path.name in SKIP_FILES: | |
| continue | |
| text = path.read_text(encoding="utf-8") | |
| m = FRONTMATTER_RE.match(text) | |
| if not m: | |
| continue | |
| fm = m.group(1) | |
| source_line = "" | |
| for line in fm.splitlines(): | |
| if line.startswith("source:"): | |
| source_line = line.split(":", 1)[1].strip() | |
| break | |
| if source_line == "session": | |
| session_exempt += 1 | |
| continue | |
| hash_match = SOURCE_HASH_RE.search(fm) | |
| if not hash_match: | |
| no_hash.append(path.relative_to(ROOT).as_posix()) | |
| continue | |
| stored_hash = hash_match.group(1) | |
| checked += 1 | |
| if ci_mode: | |
| # Structural check only: source_hash exists, that's all CI can verify. | |
| fresh += 1 | |
| continue | |
| # Find the source file | |
| if not source_line: | |
| fresh += 1 | |
| continue | |
| # Try to resolve source path | |
| source_path = None | |
| if source_line.startswith("raw/"): | |
| candidate = ROOT / source_line | |
| if candidate.exists(): | |
| source_path = candidate | |
| for sid, spath in manifest_paths.items(): | |
| if sid in source_line or source_line in str(spath): | |
| source_path = spath | |
| break | |
| if source_path and source_path.exists(): | |
| current = file_hash(source_path) | |
| if current == stored_hash: | |
| fresh += 1 | |
| else: | |
| stale.append(( | |
| path.relative_to(ROOT).as_posix(), | |
| stored_hash, | |
| current, | |
| )) | |
| else: | |
| unresolved.append(path.relative_to(ROOT).as_posix()) | |
| if stale: | |
| print(f"provenance_check: {len(stale)} STALE page(s) detected") | |
| for page, old, new in stale: | |
| print(f" {page}: hash was {old}, source now {new}") | |
| print() | |
| print("These wiki pages were compiled from source files that have since changed.") | |
| print("Recompile them to update the wiki with current information.") | |
| if no_hash: | |
| print(f"provenance_check: {len(no_hash)} page(s) without source_hash (required for non-session sources)") | |
| for page in no_hash: | |
| print(f" {page}") | |
| if unresolved: | |
| print(f"provenance_check: {len(unresolved)} page(s) with unresolved source") | |
| for page in unresolved: | |
| print(f" {page}") | |
| if not stale and not no_hash and not unresolved: | |
| suffix = " [ci-mode: structural check only]" if ci_mode else "" | |
| print( | |
| f"provenance_check: OK ({checked} checked, {fresh} fresh, " | |
| f"{session_exempt} session-exempt){suffix}" | |
| ) | |
| return 0 | |
| return 1 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |