La deduction de profil ne voyait pas les applications, donc jamais un depot nest #103

Merged
nicolas-fryder merged 2 commits from nicolas-fryder/dev into main 2026-10-01 14:25:20 +00:00 AGit

Corrige #99. profilDe lisait le manifeste de la racine ; dans un profil nest ni @nestjs/core ni next n'y sont. Depot porte dependancesPartout, et la recherche de route handlers couvre les applications. migrate plan annonce son profil et dit quand il est indetermine. Quatre tests en workspace, eprouves en reinjectant le defaut.

Corrige #99. profilDe lisait le manifeste de la racine ; dans un profil nest ni @nestjs/core ni next n'y sont. Depot porte dependancesPartout, et la recherche de route handlers couvre les applications. migrate plan annonce son profil et dit quand il est indetermine. Quatre tests en workspace, eprouves en reinjectant le defaut.
`profilDe` lisait le `package.json` de la **racine**. Dans un profil `nest`, rien
de ce qu'il cherche n'y est : `@nestjs/core` vit dans `apps/api`, `next` dans
`apps/web`. Tout dépôt `nest` existant rendait donc `profile: null` — c'est-à-dire
exactement le cas que `eqs migrate` existe pour servir (#99).

## Pourquoi ça a tenu si longtemps

Trois chemins qui marchent masquaient le quatrième :

    le gabarit, eqs-demo   ils DÉCLARENT eqs.profile, qui court-circuite tout
    ATLAS                  next-fullstack mono-application : son next EST à la racine
    un dépôt rétrofitté    @eqs/platform-* installé, les deux premières lignes suffisent

Restait le seul cas qui compte pour une migration : un dépôt `nest` existant, qui
ne déclare rien et n'a aucun paquet du socle.

## L'ironie, et elle rend le correctif évident

`lireDepot`, vingt lignes plus haut dans le même fichier, parcourt déjà les
applications du workspace — avec un commentaire qui dénonce « un `null` de
complaisance là où il y avait une mesure à faire ». La leçon était tirée, écrite,
et appliquée aux seuls `@eqs/*`, parce que la boucle filtre sur
`startsWith('@eqs/')`. Deux fonctions plus loin, `profilDe` refaisait exactement
ce `null`.

C'est le miroir de #83 : là, `knipSatellite()` déduisait de `apps/*` et ne voyait
pas une application à la racine ; ici, `profilDe` déduit de la racine et ne voit
pas les applications. Même classe, sens inverse.

## Le correctif

`Depot` porte `dependancesPartout` : l'union des dépendances de tous les
emplacements, sans le filtre `@eqs/`. `profilDe` s'en sert. Et la recherche des
route handlers couvre aussi les applications — un `next-fullstack` posé dans
`apps/web` n'a rien sous `app/` à la racine.

L'ordre des tests reste porteur de sens, et un test neuf le fixe : un profil
`nest` a AUSSI un `next`, dans son `apps/web` en profil `front`. NestJS vu
quelque part l'emporte sur un `next` vu ailleurs ; l'inverse serait faux.

## Mesuré sur la forme réelle de `nuage`, déclaration retirée

    racine declare un framework ?  []
    profile = "nest"

Reproduit dans un bac à part, en recopiant ses trois manifestes sans
`eqs.profile` — le dépôt lui-même n'a pas été touché.

## `migrate plan` dit son profil, et dit quand il ne sait pas

    profil : INDÉTERMINÉ — la liste ci-dessous n'est donc pas filtrée.
      Aucun framework reconnu dans le dépôt ni dans ses applications.
      Déclarer `eqs.profile` dans le manifeste, ou forcer avec --profile.

Sans cette ligne, un lecteur ne pouvait pas savoir que la liste n'était pas
filtrée : elle a exactement la même forme dans les deux cas. C'est le versant
« non déduit » de ce que #79 demande pour le versant « mal filtré ». `--json`
porte aussi `profil`.

## Les tests portent sur des workspaces, et c'est le point

Les trois tests existants de `profilDe` étaient **tous** mono-application, le
framework à la racine. C'est précisément pour cela que le défaut avait survécu :
la suite couvrait la forme qui marche.

Quatre cas neufs, tous en workspace. Éprouvés en réinjectant les deux moitiés du
défaut — la lecture de la racine seule et la recherche de routes depuis la racine
seule :

    × classe un workspace nest par le framework de apps/api, pas par la racine (#99)
    × préfère nest à front quand les deux frameworks sont dans le workspace
    × trouve les route handlers dans une application, pas seulement à la racine

Le quatrième, « rend null quand aucun framework n'est déclaré », passe dans les
deux cas — ce qui est juste, et c'est pour ça qu'il ne figure pas ci-dessus.

Closes #99

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`telemetry` et `http` sortaient `✓ … 0ms` au premier passage de `runConformance`
sur un satellite, sans avoir joué une seule règle : leur contexte n'était pas
fourni (#108).

## Le piège était refermé, mais pas là où on lit

Le compte d'ensemble dit exactement pourquoi il existe — « journal vide = harnais
muet, et pas suite vide ; prendre le silence pour un succès est exactement le
piège qu'on referme ici ». Il a raison, et il ne referme rien au bon endroit : il
vient en dernier, il est seul, son message est long, et **ce qu'on lit d'abord
c'est la ligne du paquet**.

Six ✓ laissaient conclure que six paquets étaient éprouvés. J'aurais conclu
pareil.

## `executerEtCompter`, et une seule définition de « jouée »

`@eqs/testing` exporte la couverture du groupe en plus de ses problèmes. Deux
choses tiennent ce correctif debout :

- `jouees` réutilise `reglesJouees`. **Une seconde définition de « jouée » serait
  pire que pas de compte du tout** — un contrôle empêché n'en fait compter aucune,
  ici comme dans le compte d'ensemble ;
- le compte porte sur le GROUPE, par une tranche du journal. Le journal est
  global : une lecture naïve ferait hériter le second groupe des règles du
  premier, et aucun groupe ne serait jamais à 0/n. C'est le défaut que le
  troisième test neuf attrape, et je l'ai éprouvé en le réinjectant.

## Le titre ne peut pas porter le compte, le statut peut

Le titre d'un `it` est figé avant l'exécution. Le ticket proposait
`✓ telemetry — 0/7 règles jouées`, et ce n'est pas atteignable tel quel.

Il proposait aussi la bonne réponse, dans sa phrase suivante : « un paquet à 0/n
pourrait se déclarer `skip` plutôt que `pass` — un test sauté se voit, un test
vert ne se revoit jamais. » C'est ce qui est fait.

Mesuré avant de m'y fier, parce que `ctx.skip()` appelé APRÈS des assertions
réussies n'avait rien d'évident :

    ↓ saute après une assertion réussie 1ms [0/7 règle(s) jouée(s) — contexte absent]
    ✓ ne saute pas quand la condition ne se présente pas 0ms
    Tests  1 passed | 1 skipped (2)

La note s'affiche entre crochets et l'exécution s'arrête là — le `throw` placé
juste après n'a jamais été atteint. Le fichier de preuve a été retiré ; ce qui
reste est le test de la vraie API.

Ce n'est pas un échec : un contexte absent est une déclaration, pas un défaut, et
en strict les non exécutables font déjà rougir au-dessus. Un groupe
partiellement joué le dit en avertissement.

## La seconde moitié du ticket repose sur une prémisse fausse

#108 signalait trois règles « jouées mais non notées » — `testing.check-budget`,
`testing.base-detruite`, `testing.fichier-orphelin` — et en concluait qu'elles
tournaient sans passer par `executerEtNoter`, ou sous un autre nom.

Vérifié dans les trois : elles passent bien par le bon chemin, **et elles rendent
`nonExecutable`** quand leur contexte manque — `ctx.check` absent pour la
première, une base jetable en cours d'utilisation pour la deuxième (documenté :
« le contrôle a un sens APRÈS, quand plus rien ne devrait rester »),
`globsTests` absent pour la troisième.

Elles sont donc **correctement** comptées comme non jouées. Ce qui trompait,
c'est que leur test était vert — parce qu'un non exécutable n'a jamais fait
rougir personne. C'est exactement l'asymétrie que ce commit corrige, et il n'y a
pas de second défaut.

Il n'y a donc rien à dispenser pour ces trois-là : il y a un contexte à fournir,
et le harnais le dira maintenant au lieu d'afficher un ✓.

Closes #108

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Infrastructure/eqs-platform!103
No description provided.