Git hooky a agenti

Pre-commit hook, který mlčí, dokud je čisto, a formát bare pro nástroje a AI agenty, kteří potřebují vědět, které soubory se pod nimi přepsaly.

Pre-commit

Hook má být rychlý a tichý: zkontrolovat jen soubory, které jdou do commitu, a když je všechno v pořádku, nevypsat nic. Přesně na to je formát bare, a přepínač --stdin navíc umožňuje kontrolovat obsah z indexu, ne z pracovního stromu, který se od něj může lišit:

#!/bin/sh
status=0
for file in $(git diff --cached --name-only --diff-filter=ACM -- '*.php'); do
	git show ":$file" | dresscode check --stdin "$file" -f bare || status=1
done
exit $status

Uložte jako .git/hooks/pre-commit a nastavte spustitelný bit. Když je vše v pořádku, hook nic nevypíše a commit projde; jinak vypíše soubor a pod ním porušení s řádkem, zprávou a jménem pravidla, a commit zastaví.

Kdo chce hook, který rovnou opravuje, pustí fix nad pracovním stromem a opravené soubory přidá do indexu. Je to pohodlné, ale znamená to, že commit obsahuje změny, které vývojář neviděl. Mně je bližší první varianta a oprava na jedno stisknutí přímo v editoru.

S nástrojem pre-commit je to jeden záznam v konfiguraci:

repos:
  - repo: local
    hooks:
      - id: dresscode
        name: DressCode
        entry: dresscode check -f bare
        language: system
        types: [php]

Agenti

Kdo nechává kód psát AI agenta, potřebuje dvě věci: aby se soubor po každém zápisu srovnal podle standardu, a aby se agent dozvěděl, že se soubor pod ním změnil. Bez toho nastane známá smyčka: agent zapíše use, hook ho jako nepoužitý smaže, agent přidá kód, který ten import potřeboval, a diví se, kde se stala chyba.

Formát bare na to odpovídá jedním řádkem:

dresscode fix src/Cart.php -f bare
src/Cart.php  rewritten

Řádek rewritten říká agentovi, že si má soubor přečíst znovu, než na něj zase sáhne. Porušení, která zůstala neopravená, dostane ve stejném výpisu a může je opravit sám. Čistý soubor nevypíše nic, takže hook nezahlcuje kontext. Přesně takhle je zapojený hook v pluginu Nette pro Claude Code a stejný tvar funguje pro jakýkoli nástroj, který umí spustit příkaz po zápisu souboru.

Rizikové opravy hook neudělá, jen je ohlásí. Aby jich zbývalo co nejméně, patří do dresscode.neon i klíč nameResolution: certain: s ním přestanou být rizikové opravy, které stojí na tom, že je funkce globální, a hook je udělá sám.