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

109 lines
8.1 KiB
Markdown

# 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é.