Files
JulesandClaude Fable 5.1 4f593d2edf Épingles : écarts correctifs face à l'épingle d'origine, écarts d'harmonisation refigés (05/10)
L'épingle d'origine (fixtures/sorties-origine-2026-09-28.json, générée depuis
le code d'astro-pro) porte les défauts corrigés par 91c755f (eg_phytostation ×3
sur C/eau, basse_planche_bec ×2 sur B et C/alim, lignes forcées orphelines,
FORCE ×4 dans le journal, A/eau par axe en INSUFFISANT). La regénérer depuis
astro-pro reproduirait les défauts ; la regénérer depuis ce paquet en ferait
une épingle sur soi-même. Elle reste donc telle quelle, et :

- scripts/ecarts-correctifs.mjs + fixtures/ecarts-correctifs-2026-10-05.json :
  chaque cellule (profil × mode × axe × champ) qui s'écarte de l'origine est
  figée, avec le détail des lignes ; une cellule absente doit rester identique.
- test/decoupage.test.mjs : test 1 compare aux écarts figés (et vérifie qu'un
  correctif n'introduit jamais un INSUFFISANT ni un total hors ±5 % en global ;
  budgets alloués et poids des axes inchangés) ; test 2 vérifie la propriété du
  découpage contre selectionner() de ce paquet ; test 3 inchangé dans l'esprit.
- Écarts d'harmonisation REFIGÉS (npm run ecarts -- --ecrire 2026-10-05) après
  relecture de docs/CONSTANTES.md : neuf lignes au lieu de onze. Les deux lignes
  perdues (A énergie global 22 → 6 %, C énergie par axe 10 → 3 %) étaient des
  taux calculés sur des kWc fantômes hérités par une batterie ; la couverture y
  est null avec les deux tables. Aucun coefficient ne change. Note datée posée
  dans CONSTANTES.md §1. (La suppression du fichier du 28/09 est partie par
  erreur dans 8465bf7, avec la version : même intention, deux commits.)
- fixtures/README.md et AGENTS.md (règles 6 et 8) : l'épingle d'origine ne se
  regénère pas pour absorber un correctif ; invariants tenus depuis v0.1.1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tgtn7bJxTLiL2fRCkQMgtR
2026-10-05 16:39:51 +02:00

8.1 KiB

AGENTS.md — @transformer/moteurs

Ce que c'est

Moteurs de calcul purs pour la rénovation et l'autonomie d'une maison, partagés par calculs.trans-former.fr (repo astro-pro) et plateforme.trans-former.fr (repo reinnover). Code et coefficients sourcés ; JAMAIS de prix. Dépôt Gitea public jules/moteurs, nom npm @transformer/moteurs, consommé par étiquette : git+https://git.trans-former.fr/jules/moteurs.git#vX.Y.Z.

Version v0.1.0 (LOT P1.0, 28/09/2026) : commun (contrat, coefficients, contexte, géométrie, argent, validation) et autonomie (noyau V2 extrait de calculs, trois moteurs d'axe, intégrateur, taux de couverture, prix des options). isolation, autoconstruction, estimatif arrivent en v0.2.0 (P1.3).

Règles opposables (un agent qui les viole a tort, quel que soit le prompt)

  1. calculer(entrees, donnees) ne lit ni réseau, ni disque, ni horloge, ni DOM, ni globale, ni aléa. Mêmes entrées + mêmes données = même résultat. test/paquet.test.mjs grep src/ et refuse fetch, require, node:*, process, Date, Math.random, console, localStorage, import *.json.
  2. Les données (prix, barèmes, options, tables) entrent en paramètre, validées par valider(table, json) par l'appelant. Aucune constante de prix dans src/. Une mise à jour de prix ne produit jamais une version du paquet. algo-config.json est une donnée : livrée dans fixtures/, injectée, jamais importée.
  3. Chaque coefficient physique existe une fois, dans src/commun/coefficients.ts, avec valeur, source, date (et note pour le veto). Tout coefficient lu apparaît dans resultat.sources (les moteurs d'axe enregistrent les lectures de la table par Proxy) ; toute valeur par défaut appliquée dans resultat.avertissements. Les heuristiques de conception (poids, modulateurs, matrices, tolérances) restent dans algo-config.json, marquées non sourcées. La table lisible par Jules est docs/CONSTANTES.md ; sans veto sous une semaine, la table du code est la référence.
  4. Aucune dépendance de production (typescript en dev seulement). dist/ (JS ESM + .d.ts) est committé à chaque étiquette ; schemas/*.schema.json est réécrit par npm run build depuis src/commun/schemas.ts (source de vérité).
  5. Une formule change → nouvelle étiquette (patch : correction ; mineur : nouvelle sortie ; majeur : entrée modifiée) et montée de version chez les deux consommateurs le même jour. Jamais de branche épinglée chez un consommateur. src/version.ts = package.json (test).
  6. Tests hors ligne (node --test test/, sur dist/), fixtures figées et datées dans fixtures/. Les 28 tests d'origine du cœur autonomie (test/noyau-origine.test.mjs) et le test de découpage par axe (test/decoupage.test.mjs, épingle générée depuis le code d'astro-pro) ne se désactivent jamais. Refiger une épingle (scripts/pin-origine.mjs, npm run ecarts -- --ecrire <date>) est un acte volontaire, écrit dans le commit, après relecture de docs/CONSTANTES.md. L'épingle d'origine ne se regénère pas pour absorber un correctif : depuis v0.1.1 elle porte des défauts corrigés, et chaque cellule qui s'en écarte est figée dans fixtures/ecarts-correctifs-<date>.json (node scripts/ecarts-correctifs.mjs --ecrire <date>) ; une cellule absente de ce fichier doit rester identique à l'origine. Les tests de correctifs (test/correctifs-v0.1.1.test.mjs) et de monotonie (test/monotonie.test.mjs) ne se désactivent pas non plus.
  7. Français avec accents dans les libellés, la doc et les messages ; identifiants en français sans accents (sous_total_eur_ht, taux_couverture) ; codes d'axe internes eau / energie / alim (les postes publiés disent alimentation).
  8. Un module du noyau (src/autonomie/noyau/) se modifie pour corriger un bug avec un test qui le montre et une ligne dans le CHANGELOG du commit ; jamais « en passant ». Les bugs latents connus sont listés dans le RECAP du lot P1.0 (scoreurs sans parse de parametre_dim, _conflit_avec perdu, Intl dans les messages de reajuste). Invariants tenus depuis v0.1.1 : une typologie n'apparaît qu'une fois par axe, un poste n'a qu'une ligne (la quantité est dimension), une ligne forcée par couplage est lâchée dès que plus rien ne la requiert, le journal n'écrit chaque FORCE qu'une fois.

Carte du dépôt

src/
├── version.ts                  étiquette portée par chaque résultat (= package.json)
├── commun/
│   ├── contrat.ts              Source, Resultat, Moteur, Trace (collecteur sources/avertissements)
│   ├── coefficients.ts         LA table (valeur, source, date, note) + verifieTableCoefficients
│   ├── contexte.ts             commun.contexte : CP → département (2A/2B, 97x) → zone RT, biogéo, pluvio, DJU
│   ├── geometrie.ts            commun.geometrie : emprise, niveaux, hauteur, pente, mitoyenneté → parois, SHAB, volume
│   ├── argent.ts               fourchettes, arrondis, mensualité / annuité / coût du crédit
│   ├── schemas.ts              forme de chaque JSON de données (→ schemas/*.schema.json au build)
│   └── valider.ts              valider(table, json) : type, required, properties, items, enum, minItems
└── autonomie/
    ├── noyau/                  V2 de calculs, sans singleton : algo (selectionner + finaliseSelection),
    │                           pondere-axes, alloue-budget, selectionne-poste, adequation, scoreurs,
    │                           dimension, couplages (copie, ne mute plus), reajuste, axes-actifs, types
    ├── axe.ts                  fabrique des moteurs d'axe (selectionnePoste + finaliseSelection à un axe + taux)
    ├── eau.ts · energie.ts · alimentation.ts
    ├── integrateur.ts          contexte + poids + budgets ; mode 'global' (= calculs) ou 'par_axe' (= plateforme)
    ├── taux.ts                 couverture eau / énergie (autoconsommation appliquée) / alimentation
    └── prix.ts                 prixOption, prixPreset, presetLePlusProche (données d'options, pas de montant)
schemas/    fixtures/    test/    scripts/    docs/CONSTANTES.md    dist/

Comment ajouter un moteur (P1.3 : isolation, autoconstruction, estimatif → v0.2.0)

  1. Ses tables de données : une entrée par table dans src/commun/schemas.ts (NomTable s'étend seul, valider suit) ; les fixtures datées dans fixtures/ ; jamais un prix dans src/.
  2. Ses coefficients physiques : dans TableCoefficients + COEFFICIENTS (valeur, source, date, note) et dans fixtures/coefficients-2026-05.json (le test exige les mêmes clés ; pour une grandeur absente du code d'origine, mettre la même valeur et le dire en source), puis une ligne dans docs/CONSTANTES.md.
  3. Le moteur : src/<domaine>/<nom>.ts exporte un Moteur<E, D, S> avec un id '<domaine>.<nom>', construit son résultat avec Trace (chaque coefficient lu → trace.source, chaque défaut → trace.avertit), rend VERSION. Un index.ts par domaine ; l'id ajouté à MOTEURS (src/index.ts).
  4. package.json : une entrée exports par sous-chemin (./isolation, …) ; version mineure.
  5. Tests hors ligne dans test/<domaine>.test.mjs (contrat : déterminisme, sources, avertissements, un cas chiffré à la main), npm test vert, dist/ reconstruit, étiquette, montée chez reinnover.

Comment publier

npm test                # pretest = build ; 4 fichiers de tests + les 28 d'origine, tous hors ligne
git add -A && git commit
git tag vX.Y.Z && git push && git push --tags

puis monter #vX.Y.Z dans reinnover/package.json (et astro-pro à partir de P1.5) le même jour, npm install chez le consommateur, commit du lockfile.

Ce qu'un agent ne fait pas ici

Lire NocoDB · appeler une API · écrire un prix ou un barème · importer depuis astro-pro ou reinnover · importer un JSON dans src/ · désactiver ou affaiblir un test · épingler une branche · ajouter une dépendance de production · publier sans dist/ reconstruit et committé.