refactor(contract): contrat kaaops en donnée, lu par check ET par fix
Le contrat était écrit deux fois : en conditionnelles dans check.sh pour auditer, en conditionnelles dans conform.sh pour réparer. Rien ne garantissait que les deux copies restent d'accord — seuls des commentaires de garde, semés à chaque endroit dangereux. La divergence de 2026-07-16 (✗ GET /health incorrigeable) n'était pas un accident : c'était le comportement par défaut.
Les 36 règles vivent maintenant dans contract.yaml. check et fix la lisent tous les deux ; ils ne peuvent plus diverger.
- contract.yaml les règles : test, formes concernées, réparation, why
- lib/contract.sh lecteur YAML (awk, ~40 l.), project_shape, run_predicate
- lib/predicates.sh les tests que le YAML ne sait pas exprimer (pred_*)
- lib/conform.sh les réparations découpées en fix_*, pilotées par le contrat
- lib/check.sh ne contient plus aucune règle : parcourt et rend
- konform check --json sortie machine, exploitable en CI
- konform explain [id] ce que le contrat sait d'une règle, y compris pourquoi
Nouvelle règle backend-config : un backend kaapi sans app/core/config.py rend la conformité CORS invérifiable ; sans elle, ce silence serait indistinguable d'un « tout va bien ». Avertissement, pas échec.
Deux changements de comportement, assumés :
- fix n'annonce plus la correction CORS quand config.py est absent (avant : annoncée, jamais appliquée, aucun message) ;
- l'ordre des lignes de fix suit l'ordre du contrat (cosmétique, ensemble identique).
Parité konform check byte-identique sur 9 cibles pour le refactor seul ; la règle backend-config ajoute ensuite exactement une ligne sur les formes full et backend-only. Verdicts et codes de sortie inchangés partout.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com