content-explorer/scripts/audit_upstream.py
tegwick 2b1706559b Record the OnCo baseline pin and reuse audit.
Pin b594d743, typecheck the checkout, and keep the corpus and assets out of this repo. Leave screenshots and the production build open.

Assistant: grok
Assistant-Session: 01a130f1-abfb-7d71-9cd6-a8b75ec7f95a
2026-10-12 18:50:21 +02:00

129 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""Read-only inventory of a local OnCo checkout. Writes nothing into the checkout.
The checkout stays gitignored. This script counts files and import edges so the
baseline report can be committed without copying upstream source or corpus text.
"""
from __future__ import annotations
import re
import subprocess
import sys
from collections import Counter
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
UPSTREAM = Path(sys.argv[1] if len(sys.argv) > 1 else ROOT / "upstream-onco")
CODE_DIRS = ("src/components", "src/lib", "src/app", "scripts", "packages", "mcp")
NAME_TOKENS = re.compile(
r"cancer|oncolog|drug|target|trial|biomarker|tumou?r|adc|payload",
re.I,
)
IMPORT_RE = re.compile(
r"""^import\s+(?:type\s+)?(?:[\w*\s{},]+\s+from\s+)?["']([^"']+)["']""",
re.M,
)
KIND_LITERAL = re.compile(r"""kind\s*===?\s*["']([a-z0-9-]+)["']""")
def git(*args: str) -> str:
proc = subprocess.run(
["git", "-C", str(UPSTREAM), *args],
capture_output=True,
text=True,
check=False,
)
return proc.stdout.strip() if proc.returncode == 0 else ""
def rel_files(folder: str) -> list[Path]:
base = UPSTREAM / folder
if not base.is_dir():
return []
return [p for p in base.rglob("*") if p.is_file()]
def imports_of(path: Path) -> list[str]:
try:
text = path.read_text(encoding="utf-8", errors="replace")
except OSError:
return []
return IMPORT_RE.findall(text)
def main() -> int:
if not (UPSTREAM / ".git").is_dir():
print(f"missing checkout: {UPSTREAM}", file=sys.stderr)
return 1
sha = git("rev-parse", "HEAD")
subject = git("log", "-1", "--format=%ci %s")
print(f"pin {sha}")
print(f"commit {subject}")
print(f"license_exists { (UPSTREAM / 'LICENSE').is_file() }")
print(f"license_data_exists { (UPSTREAM / 'LICENSE-DATA').is_file() }")
print(f"notice_exists { (UPSTREAM / 'NOTICE').is_file() }")
for folder in ("src", "src/data", "src/components", "src/lib", "src/app", "public", "scripts"):
files = rel_files(folder) if folder != "src" else [
p for p in (UPSTREAM / "src").rglob("*") if p.is_file()
]
code = [p for p in files if p.suffix in {".ts", ".tsx", ".js", ".mjs"}]
print(f"count {folder} files={len(files)} code={len(code)}")
named = []
for folder in ("src/components", "src/lib", "src/app"):
for path in rel_files(folder):
if path.suffix not in {".ts", ".tsx"}:
continue
if NAME_TOKENS.search(path.name):
named.append(str(path.relative_to(UPSTREAM)))
print(f"oncology_named_code {len(named)}")
for item in sorted(named)[:40]:
print(f" named {item}")
if len(named) > 40:
print(f" named … {len(named) - 40} more")
focus = [
"src/components/EntityBrowser.tsx",
"src/components/EntityDetail.tsx",
"src/lib/graph.ts",
"src/lib/schema.ts",
"src/lib/kinds.ts",
"src/app/[kind]/page.tsx",
"src/lib/nav.ts",
"src/lib/tables/kinds.ts",
]
for rel in focus:
path = UPSTREAM / rel
print(f"focus {rel} exists={path.is_file()} bytes={path.stat().st_size if path.is_file() else 0}")
if not path.is_file():
continue
imps = imports_of(path)
local = [i for i in imps if i.startswith(".") or i.startswith("@/")]
print(f" imports {len(imps)} local={len(local)}")
for item in local:
print(f" {item}")
text = path.read_text(encoding="utf-8", errors="replace")
kinds = Counter(KIND_LITERAL.findall(text))
if kinds:
print(" kind_branches " + ", ".join(f"{k}:{v}" for k, v in kinds.most_common(12)))
# Kind enum from schema if present.
schema = UPSTREAM / "src/lib/schema.ts"
if schema.is_file():
text = schema.read_text(encoding="utf-8", errors="replace")
kinds_block = re.search(r"KINDS\s*=\s*\[(.*?)\]\s*as\s+const", text, re.S)
if kinds_block:
kinds = re.findall(r"""["']([a-z0-9-]+)["']""", kinds_block.group(1))
print(f"kinds {len(kinds)} " + " ".join(kinds))
rels = re.search(r"REL_FIELDS\s*=\s*\[(.*?)\]\s*as\s+const", text, re.S)
if rels:
fields = re.findall(r"""["']([A-Za-z0-9_]+)["']""", rels.group(1))
print(f"rel_fields {len(fields)} " + " ".join(fields[:40]))
return 0
if __name__ == "__main__":
raise SystemExit(main())