#!/usr/bin/env python3 # ============================================================================= # Job·Ka — Groupe KA # Auteur : Simon-Pierre Boucher # Contact : contact@spboucher.ai # Fichier : scripts/check_headers.py # Rôle : Vérification de l'en-tête d'auteur (règle nº 1) — utilisé par le # hook pre-commit : rejette tout fichier stagé sans en-tête # Créé : 2026-08-17 Modifié : 2026-08-17 # ============================================================================= """Vérifie que chaque fichier stagé porte l'en-tête d'auteur du projet. Usage : python3 scripts/check_headers.py # fichiers explicites python3 scripts/check_headers.py --staged # fichiers stagés (hook) """ from __future__ import annotations import subprocess import sys from pathlib import Path # Extensions soumises à la règle nº 1 (code, scripts, configs, docs, tests) CHECKED_EXTS = {".py", ".ts", ".tsx", ".js", ".jsx", ".css", ".html", ".md", ".sh", ".txt", ".yml", ".yaml", ".toml"} # Fichiers exemptés : données, verrous, artefacts générés EXEMPT_PARTS = {"node_modules", "dist", ".venv", "fixtures", "data", "__pycache__", ".git"} EXEMPT_NAMES = {"package-lock.json", "LICENSE"} REQUIRED = ("Job·Ka — Groupe KA", "Simon-Pierre Boucher", "contact@spboucher.ai") def needs_header(path: Path) -> bool: if path.name in EXEMPT_NAMES: return False if set(path.parts) & EXEMPT_PARTS: return False return path.suffix.lower() in CHECKED_EXTS def has_header(path: Path) -> bool: try: head = path.read_text(encoding="utf-8", errors="ignore")[:1500] except OSError: return False return all(tok in head for tok in REQUIRED) def staged_files() -> list[Path]: out = subprocess.run( ["git", "diff", "--cached", "--name-only", "--diff-filter=ACM"], capture_output=True, text=True, check=True).stdout return [Path(l) for l in out.splitlines() if l.strip()] def main() -> int: if len(sys.argv) > 1 and sys.argv[1] == "--staged": targets = staged_files() else: targets = [Path(a) for a in sys.argv[1:]] bad = [p for p in targets if p.exists() and needs_header(p) and not has_header(p)] if bad: print("✗ En-tête d'auteur manquant (règle nº 1 du CLAUDE.md) :", file=sys.stderr) for p in bad: print(f" {p}", file=sys.stderr) print(" -> ajouter le bloc « Job·Ka — Groupe KA / Auteur : " "Simon-Pierre Boucher / contact@spboucher.ai »", file=sys.stderr) return 1 return 0 if __name__ == "__main__": sys.exit(main())