SPB Git forge

spb/job-ka

Public
226commits 1branches 0releases
37.5 MBsize
maindefault branch
9 h agolast push
HTML 82.1% Python 14.6% TypeScript 1.9% CSS 1% JavaScript 0.5%
2.7 KB · 77 lines python
Raw Blame History
1#!/usr/bin/env python32# =============================================================================3# Job·Ka — Groupe KA4# Auteur  : Simon-Pierre Boucher5# Contact : contact@spboucher.ai6# Fichier : scripts/check_headers.py7# Rôle    : Vérification de l'en-tête d'auteur (règle nº 1) — utilisé par le8#           hook pre-commit : rejette tout fichier stagé sans en-tête9# Créé    : 2026-08-17   Modifié : 2026-08-1710# =============================================================================11"""Vérifie que chaque fichier stagé porte l'en-tête d'auteur du projet.1213Usage :14    python3 scripts/check_headers.py <fichier ...>     # fichiers explicites15    python3 scripts/check_headers.py --staged          # fichiers stagés (hook)16"""17from __future__ import annotations1819import subprocess20import sys21from pathlib import Path2223# Extensions soumises à la règle nº 1 (code, scripts, configs, docs, tests)24CHECKED_EXTS = {".py", ".ts", ".tsx", ".js", ".jsx", ".css", ".html", ".md",25                ".sh", ".txt", ".yml", ".yaml", ".toml"}26# Fichiers exemptés : données, verrous, artefacts générés27EXEMPT_PARTS = {"node_modules", "dist", ".venv", "fixtures", "data",28                "__pycache__", ".git"}29EXEMPT_NAMES = {"package-lock.json", "LICENSE"}3031REQUIRED = ("Job·Ka — Groupe KA", "Simon-Pierre Boucher", "contact@spboucher.ai")323334def needs_header(path: Path) -> bool:35    if path.name in EXEMPT_NAMES:36        return False37    if set(path.parts) & EXEMPT_PARTS:38        return False39    return path.suffix.lower() in CHECKED_EXTS404142def has_header(path: Path) -> bool:43    try:44        head = path.read_text(encoding="utf-8", errors="ignore")[:1500]45    except OSError:46        return False47    return all(tok in head for tok in REQUIRED)484950def staged_files() -> list[Path]:51    out = subprocess.run(52        ["git", "diff", "--cached", "--name-only", "--diff-filter=ACM"],53        capture_output=True, text=True, check=True).stdout54    return [Path(l) for l in out.splitlines() if l.strip()]555657def main() -> int:58    if len(sys.argv) > 1 and sys.argv[1] == "--staged":59        targets = staged_files()60    else:61        targets = [Path(a) for a in sys.argv[1:]]62    bad = [p for p in targets63           if p.exists() and needs_header(p) and not has_header(p)]64    if bad:65        print("✗ En-tête d'auteur manquant (règle nº 1 du CLAUDE.md) :",66              file=sys.stderr)67        for p in bad:68            print(f"   {p}", file=sys.stderr)69        print("   -> ajouter le bloc « Job·Ka — Groupe KA / Auteur : "70              "Simon-Pierre Boucher / contact@spboucher.ai »", file=sys.stderr)71        return 172    return 0737475if __name__ == "__main__":76    sys.exit(main())77