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 par91c755f(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 dans8465bf7, 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
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)
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.mjsgrepsrc/et refusefetch,require,node:*,process,Date,Math.random,console,localStorage,import *.json.- 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 danssrc/. Une mise à jour de prix ne produit jamais une version du paquet.algo-config.jsonest une donnée : livrée dansfixtures/, injectée, jamais importée. - Chaque coefficient physique existe une fois, dans
src/commun/coefficients.ts, avecvaleur,source,date(etnotepour le veto). Tout coefficient lu apparaît dansresultat.sources(les moteurs d'axe enregistrent les lectures de la table par Proxy) ; toute valeur par défaut appliquée dansresultat.avertissements. Les heuristiques de conception (poids, modulateurs, matrices, tolérances) restent dansalgo-config.json, marquées non sourcées. La table lisible par Jules estdocs/CONSTANTES.md; sans veto sous une semaine, la table du code est la référence. - Aucune dépendance de production (
typescripten dev seulement).dist/(JS ESM +.d.ts) est committé à chaque étiquette ;schemas/*.schema.jsonest réécrit parnpm run builddepuissrc/commun/schemas.ts(source de vérité). - 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). - Tests hors ligne (
node --test test/, surdist/), fixtures figées et datées dansfixtures/. 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 dedocs/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 dansfixtures/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. - 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 interneseau/energie/alim(les postes publiés disentalimentation). - Un module du noyau (
src/autonomie/noyau/) se modifie pour corriger un bug avec un test qui le montre et une ligne dans leCHANGELOGdu commit ; jamais « en passant ». Les bugs latents connus sont listés dans le RECAP du lot P1.0 (scoreurs sans parse deparametre_dim,_conflit_avecperdu, Intl dans les messages dereajuste). 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é estdimension), 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)
- Ses tables de données : une entrée par table dans
src/commun/schemas.ts(NomTables'étend seul,validersuit) ; les fixtures datées dansfixtures/; jamais un prix danssrc/. - Ses coefficients physiques : dans
TableCoefficients+COEFFICIENTS(valeur, source, date, note) et dansfixtures/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 ensource), puis une ligne dansdocs/CONSTANTES.md. - Le moteur :
src/<domaine>/<nom>.tsexporte unMoteur<E, D, S>avec unid'<domaine>.<nom>', construit son résultat avecTrace(chaque coefficient lu →trace.source, chaque défaut →trace.avertit), rendVERSION. Unindex.tspar domaine ; l'idajouté àMOTEURS(src/index.ts). package.json: une entréeexportspar sous-chemin (./isolation, …) ; version mineure.- Tests hors ligne dans
test/<domaine>.test.mjs(contrat : déterminisme, sources, avertissements, un cas chiffré à la main),npm testvert,dist/reconstruit, étiquette, montée chezreinnover.
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é.