Code / tools/check_headers.py
tools/check_headers.py
107 lines
#!/usr/bin/env python3
# =============================================================================
# Project : modelmap
# File : tools/check_headers.py
# Purpose : Fail if any tracked source file lacks the mandatory author header
# Author : Simon-Pierre Boucher
# Contact : contact@spboucher.ai
# Website : https://modelmap.io
# Created : 2026-08-12
# Modified : 2026-08-12
# Platform : macOS / Apple Silicon (arm64)
# License : All rights reserved (research code)
# =============================================================================
"""Header compliance checker (charter §0.1).
Scans git-tracked source files and verifies each begins (after an optional
shebang) with the standardized author header, or — for markdown — with YAML
front matter carrying the author fields. Exits non-zero on any violation,
so it can gate commits.
"""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
HASH_COMMENT_EXT = {".py", ".sh", ".zsh", ".yaml", ".yml", ".toml", ".cff"}
SLASH_COMMENT_EXT = {".c", ".cpp", ".h", ".hpp", ".metal", ".swift", ".m", ".js", ".ts", ".css"}
MARKDOWN_EXT = {".md"}
HASH_COMMENT_NAMES = {"Makefile"}
REQUIRED_TOKENS = (
"Project : modelmap",
"Author : Simon-Pierre Boucher",
"Contact : contact@spboucher.ai",
)
MD_REQUIRED_TOKENS = (
"project: modelmap",
"author: Simon-Pierre Boucher",
"contact: contact@spboucher.ai",
)
# Files that carry no comments / are data or licenses. CLAUDE.md is the
# authoritative charter (its content is the spec itself, not a research doc).
EXEMPT = {"LICENSE", ".gitignore", "package.json", "package-lock.json", "CLAUDE.md"}
def tracked_files() -> list[Path]:
out = subprocess.run(
["git", "ls-files"], cwd=ROOT, capture_output=True, text=True, check=True
).stdout
return [ROOT / line for line in out.splitlines() if line.strip()]
def head_of(path: Path, n_bytes: int = 4096) -> str:
try:
return path.read_text(errors="replace")[:n_bytes]
except OSError:
return ""
def check(path: Path) -> str | None:
"""Return an error string, or None if compliant / not applicable."""
name = path.name
if name in EXEMPT:
return None
ext = path.suffix.lower()
text = head_of(path)
if text.startswith("#!"):
text = text.split("\n", 1)[1] if "\n" in text else ""
if ext in MARKDOWN_EXT:
if not text.lstrip().startswith("---"):
return "missing YAML front matter"
missing = [t for t in MD_REQUIRED_TOKENS if t not in text]
return f"front matter missing: {', '.join(missing)}" if missing else None
if ext in HASH_COMMENT_EXT or ext in SLASH_COMMENT_EXT or name in HASH_COMMENT_NAMES:
missing = [t for t in REQUIRED_TOKENS if t not in text]
return f"header missing: {', '.join(missing)}" if missing else None
return None # extension not governed by the header rule
def main() -> int:
errors: list[tuple[Path, str]] = []
for f in tracked_files():
if not f.is_file():
continue
err = check(f)
if err:
errors.append((f, err))
if errors:
print(f"check_headers: {len(errors)} non-compliant file(s):")
for f, err in errors:
print(f" {f.relative_to(ROOT)}: {err}")
return 1
print("check_headers: all tracked source files carry the mandatory header.")
return 0
if __name__ == "__main__":
sys.exit(main())