#!/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())