spb/anomaly-atlas Public License
Systematic discovery & rigorous validation of statistical anomalies in open HF market data (hfmarketdata.io) — pre-registered, artifact-null-driven, fully reproducible. Live atlas: www.anomaly-atlas.io
Python 61.4%
JavaScript 28.7%
CSS 8.6%
Shell 0.7%
Makefile 0.5%
1#!/usr/bin/env python32# =============================================================================3# Project : anomaly-atlas4# File : tools/check_headers.py5# Purpose : CI-style enforcement of the mandatory author header (CLAUDE.md §0.1)6# Author : Simon-Pierre Boucher7# Contact : contact@spboucher.ai8# Data src : hfmarketdata.io (sole data source)9# Created : 2026-08-1210# Modified : 2026-08-1211# Platform : macOS / Apple Silicon (arm64)12# License : All rights reserved (research code)13# =============================================================================14"""Fail (exit 1) if any tracked source file lacks a conforming author header.1516Usage:17 python3 tools/check_headers.py # check all git-tracked files18 python3 tools/check_headers.py FILE... # check specific files1920Rules enforced (see CLAUDE.md §0.1):21 * Comment-style sources (.py .sh .zsh .yaml .yml .toml .cff .sql Makefile22 CMakeLists.txt .gitignore) must contain the '#'-style header block near23 the top, including the 'Data src' field.24 * C-family / TS / JS / CSS sources must contain the '//'-style header block25 ('/*'-style for .css) near the top.26 * Markdown documents must begin with YAML front matter declaring27 project/author/contact/data_source.28 * A shebang line may precede the header.2930Exemptions: generated results under results/, atlas payload JSON, LICENSE,31package-lock.json, CLAUDE.md (the charter is the specification itself).32"""3334from __future__ import annotations3536import subprocess37import sys38from pathlib import Path3940REPO_ROOT = Path(__file__).resolve().parent.parent4142REQUIRED_FIELDS = (43 "Project",44 "File",45 "Purpose",46 "Author",47 "Contact",48 "Data src",49 "Created",50 "Modified",51 "Platform",52 "License",53)54AUTHOR = "Simon-Pierre Boucher"55CONTACT = "contact@spboucher.ai"56DATA_SOURCE = "hfmarketdata.io"5758HASH_EXTS = {".py", ".sh", ".zsh", ".bash", ".yaml", ".yml", ".toml", ".cff", ".sql"}59SLASH_EXTS = {60 ".c",61 ".cc",62 ".cpp",63 ".h",64 ".hpp",65 ".metal",66 ".swift",67 ".m",68 ".mm",69 ".js",70 ".mjs",71 ".ts",72 ".tsx",73 ".css",74}75HASH_NAMES = {"Makefile", "CMakeLists.txt", ".gitignore"}7677EXEMPT_NAMES = {"LICENSE", "CLAUDE.md", "MEMORY.md", "package-lock.json"}78EXEMPT_DIRS = {"results"}79# How many leading lines to scan for the header block (allows shebang etc.).80SCAN_LINES = 22818283def tracked_files() -> list[Path]:84 out = subprocess.run(85 ["git", "ls-files"], cwd=REPO_ROOT, capture_output=True, text=True, check=True86 ).stdout87 return [REPO_ROOT / line for line in out.splitlines() if line.strip()]888990def is_exempt(path: Path) -> bool:91 rel = path.relative_to(REPO_ROOT)92 if rel.name in EXEMPT_NAMES:93 return True94 return bool(rel.parts and rel.parts[0] in EXEMPT_DIRS)959697def check_comment_header(lines: list[str], prefixes: tuple[str, ...]) -> list[str]:98 """Check for a comment-style header with all required fields near the top."""99 head = "\n".join(lines[:SCAN_LINES])100 errors = []101 for field in REQUIRED_FIELDS:102 if not any(f"{p} {field}" in head or f"{p} {field}" in head for p in prefixes):103 errors.append(f"missing header field: {field}")104 if AUTHOR not in head:105 errors.append(f"missing author name '{AUTHOR}'")106 if CONTACT not in head:107 errors.append(f"missing contact '{CONTACT}'")108 if DATA_SOURCE not in head:109 errors.append(f"missing data source '{DATA_SOURCE}'")110 return errors111112113def check_markdown_front_matter(lines: list[str]) -> list[str]:114 if not lines or lines[0].strip() != "---":115 return ["markdown file must start with YAML front matter (---)"]116 errors = []117 try:118 end = next(i for i in range(1, min(len(lines), SCAN_LINES)) if lines[i].strip() == "---")119 except StopIteration:120 return ["unterminated YAML front matter"]121 block = "\n".join(lines[1:end])122 for key in (123 "project: anomaly-atlas",124 f"author: {AUTHOR}",125 f"contact: {CONTACT}",126 f"data_source: {DATA_SOURCE}",127 ):128 if key not in block:129 errors.append(f"front matter missing '{key}'")130 return errors131132133def check_file(path: Path) -> list[str]:134 try:135 text = path.read_text(encoding="utf-8", errors="replace")136 except OSError as exc:137 return [f"unreadable: {exc}"]138 lines = text.splitlines()139 if lines and lines[0].startswith("#!"):140 lines = lines[1:]141142 name, ext = path.name, path.suffix143 if ext in HASH_EXTS or name in HASH_NAMES:144 return check_comment_header(lines, ("#",))145 if ext in SLASH_EXTS:146 return check_comment_header(lines, ("//", "*", "/*"))147 if ext == ".md":148 return check_markdown_front_matter(lines)149 return [] # other file types are not subject to the header rule150151152def main(argv: list[str]) -> int:153 paths = [Path(p).resolve() for p in argv] if argv else tracked_files()154 failures: dict[str, list[str]] = {}155 checked = 0156 for path in paths:157 if not path.is_file() or is_exempt(path):158 continue159 errors = check_file(path)160 if path.suffix in HASH_EXTS | SLASH_EXTS | {".md"} or path.name in HASH_NAMES:161 checked += 1162 if errors:163 failures[str(path.relative_to(REPO_ROOT))] = errors164165 if failures:166 print(f"HEADER CHECK FAILED — {len(failures)} non-conforming file(s):\n")167 for rel, errors in sorted(failures.items()):168 print(f" {rel}")169 for err in errors:170 print(f" - {err}")171 return 1172 print(f"Header check passed ({checked} files checked).")173 return 0174175176if __name__ == "__main__":177 sys.exit(main(sys.argv[1:]))178