Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 27 additions & 24 deletions docs/revue-a-froid-4.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ <h1>Settex — après la campagne</h1>
<div class="meta">
<span><b>Date</b> 19 juillet 2026</span>
<span><b>Stack</b> .NET 10 (LTS) · C#</span>
<span><b>Tests</b> 371 · 0 échec</span>
<span><b>Tests</b> 381 · 0 échec</span>
<span><b>CI</b> Linux · Windows · extension</span>
</div>
</div>
Expand All @@ -92,8 +92,8 @@ <h2><span class="num">01</span>Verdict</h2>

<div class="score-band">
<div class="score"><div class="big">8,2<span style="font-size:1rem;color:var(--muted)">/10</span></div><div class="lbl">Note à la publication <span class="badge b-warn">−1,2</span></div></div>
<div class="score"><div class="big">371</div><div class="lbl">tests, tous verts</div></div>
<div class="score"><div class="big">0</div><div class="lbl">défaut élevé restant <span class="badge b-ok">5 corrigés</span></div></div>
<div class="score"><div class="big">381</div><div class="lbl">tests, tous verts</div></div>
<div class="score"><div class="big">4</div><div class="lbl">constats restants <span class="badge b-ok">18 traités</span></div></div>
<div class="score"><div class="big">0</div><div class="lbl">avertissement de build</div></div>
</div>

Expand All @@ -109,10 +109,13 @@ <h2><span class="num">01</span>Verdict</h2>
<div class="t">Mise à jour — depuis la publication de cette revue</div>
<p style="margin:0 0 8px">Les <strong>cinq défauts élevés sont corrigés</strong>, en trois PR, chacune validée par la CI et accompagnée de tests dont l'échec a été vérifié sur le code non corrigé. 364 → <strong>371 tests</strong>.</p>
<ul class="tight" style="margin:0">
<li><strong>H1 · H2</strong>&nbsp;— la comparaison de casse est terminée là où elle manquait&nbsp;: dictionnaire des environnements, <code>PathExists</code>, blocs imbriqués. Deux environnements ne différant que par la casse fusionnent désormais, comme le fait déjà le modèle de .NET.</li>
<li><strong>H4 · H5</strong>&nbsp;— les deux heuristiques sont remplacées par une seule règle tirée du comportement réel du provider&nbsp;: comparer les jeux de clés aplaties. Elle couvre les index de queue, les champs omis, les tableaux imbriqués et l'élément objet remplacé par un primitif.</li>
<li><strong>H3</strong>&nbsp;— un diagnostic n'est plus jamais écarté. Le compromis est assumé&nbsp;: la duplication revient, et c'est préférable à une disparition.</li>
<li><strong>Les 5 défauts élevés</strong> — casse des environnements et de <code>:=</code>, diagnostic de dérive perdu, deux fuites de superposition. <span class="badge b-ok">fait</span></li>
<li><strong>6 des 7 constats moyens</strong> — blocs imbriqués homonymes, blocs vides, références dans les boucles, segment survolé, sortie d'exemple périmée, durcissement du workflow de déploiement. <span class="badge b-ok">fait</span></li>
<li><strong>5 des 9 mineurs</strong> — fins de ligne CR, position des erreurs d'include, <code>didClose</code>, annulation de CI sur <code>main</code>, promesse flottante de l'extension. <span class="badge b-ok">fait</span></li>
<li><strong>Restent&nbsp;: M5 et quatre mineurs</strong>, tous des arbitrages plutôt que des oublis — voir ci-dessous.</li>
</ul>

<p style="margin:12px 0 0"><strong>Ce qui n'a délibérément pas été corrigé.</strong> <strong>M5</strong> (un fichier racine sans <code>settings</code> est propre dans l'éditeur et échoue au build) n'a pas de correctif gratuit&nbsp;: rien ne distingue l'intention «&nbsp;racine&nbsp;» de l'intention «&nbsp;fragment&nbsp;». Les quatre mineurs restants — tableaux frères ne différant que par la casse, dépendance à l'ordre d'insertion de la recherche insensible à la casse, complétion sans conscience de portée, deux URI pour un même fichier — demandent chacun soit une nouvelle règle de langage, soit une refonte, pas un correctif&nbsp;: les traiter à la va-vite reviendrait à échanger un défaut connu contre un défaut inconnu.</p>
</div>

<h2><span class="num">02</span>Vérité terrain</h2>
Expand Down Expand Up @@ -194,52 +197,52 @@ <h3><s>H5 — Un élément objet écrasé par un primitif est réputé «&nbsp;r

<h2><span class="num">04</span>Défauts moyens</h2>

<div class="finding med">
<h3>M1 — Deux blocs imbriqués de même nom s'écrasent au lieu de fusionner <span class="tag">reproduit</span></h3>
<div class="finding" style="border-left-color:var(--ok)">
<h3><s>M1 — Deux blocs imbriqués de même nom s'écrasent au lieu de fusionner</s> <span class="badge b-ok">corrigé</span></h3>
<p><code>settings { Db { Host = "h" } Db { Port = 5 } }</code> émet <code>{ "Db": { "Port": 5 } }</code> — <code>Host</code> est perdu sans diagnostic, alors que le modèle documenté pour les blocs <code>settings</code> multiples est la fusion profonde. Pré-existant, mais sur la ligne même que la campagne a réécrite.</p>
</div>

<div class="finding med">
<h3>M2 — Le saut des blocs vides repose sur une justification fausse <span class="tag">reproduit</span></h3>
<div class="finding" style="border-left-color:var(--ok)">
<h3><s>M2 — Le saut des blocs vides repose sur une justification fausse</s> <span class="badge b-ok">corrigé</span></h3>
<p>Le commentaire affirme qu'un objet vide ne produit aucune clé à l'exécution. Le relecteur a nourri <code>{ "A": {}, "B": [] }</code> à un vrai <code>ConfigurationBuilder</code>&nbsp;: <code>A</code> et <code>B</code> ressortent comme des clés réelles. La décision reste bonne pour le conflit qu'elle corrigeait, mais elle supprime aussi les blocs <em>explicitement</em> vides, ce que le raisonnement ne couvrait pas.</p>
</div>

<div class="finding med">
<h3>M3 — «&nbsp;Rechercher les références&nbsp;» ignore tout ce qui est dans une boucle <span class="tag">reproduit</span></h3>
<div class="finding" style="border-left-color:var(--ok)">
<h3><s>M3 — «&nbsp;Rechercher les références&nbsp;» ignore tout ce qui est dans une boucle</s> <span class="badge b-ok">corrigé</span></h3>
<p><code>ForNode</code> implémente <code>IArrayElement</code> mais pas <code>IExpression</code>, et le collecteur filtre sur <code>IExpression</code>&nbsp;: ni le corps ni la collection ne sont parcourus. Une variable utilisée uniquement dans une boucle renvoie <strong>zéro</strong> référence. La résolution de portée, elle, gère correctement les boucles — c'est le collecteur seul.</p>
</div>

<div class="finding med">
<h3>M4 — Le survol d'un segment de chemin répété résout le mauvais objet <span class="tag">reproduit</span></h3>
<div class="finding" style="border-left-color:var(--ok)">
<h3><s>M4 — Le survol d'un segment de chemin répété résout le mauvais objet</s> <span class="badge b-ok">corrigé</span></h3>
<p><code>IndexOf(word)</code> prend la <em>première</em> occurrence. Sur <code>settings { A { B { A = 1 } } }</code>, survoler le <code>A</code> le plus interne affiche l'overlay de <code>A</code> au lieu de la valeur de <code>A.B.A</code>. L'ajout du survol d'en-tête de bloc, qui produit des chemins multi-segments, élargit le cas.</p>
</div>

<div class="finding med">
<h3>M5 — Un fichier racine sans <code>settings</code> est propre dans l'éditeur et échoue au build</h3>
<h3>M5 — Un fichier racine sans <code>settings</code> est propre dans l'éditeur et échoue au build <span class="badge b-warn">assumé</span></h3>
<p>La relaxation nécessaire aux fragments masque aussi l'erreur pour un fichier destiné à être une racine. Rien ne distingue les deux intentions, donc il n'y a pas de correctif gratuit — mais la divergence éditeur/compilateur est réelle et n'est documentée nulle part.</p>
</div>

<div class="finding med">
<h3>M6 — Sorties générées commitées et périmées dans le projet d'exemple <span class="tag">reproduit</span></h3>
<div class="finding" style="border-left-color:var(--ok)">
<h3><s>M6 — Sorties générées commitées et périmées dans le projet d'exemple</s> <span class="badge b-ok">corrigé</span></h3>
<p><code>tests/IntegrationTests/SampleProject/</code> contient six <code>appsettings*.json</code> commités dont le contenu est <strong>entièrement fusionné</strong>, soit ce que le compilateur émettait avant le mode delta. Recompilation à l'appui, ils diffèrent de ce que l'outil produit aujourd'hui. Le répertoire n'est de plus <strong>pas dans la solution</strong>, donc ni construit ni vérifié par la CI. C'est la classe de défaut nettoyée à la racine du dépôt — la campagne n'avait regardé que la racine.</p>
</div>

<div class="finding med">
<h3>M7 — Le workflow de déploiement n'a pas de bloc <code>permissions</code> et casse sur les PR de fork</h3>
<div class="finding" style="border-left-color:var(--ok)">
<h3><s>M7 — Le workflow de déploiement n'a pas de bloc <code>permissions</code> et casse sur les PR de fork</s> <span class="badge b-ok">corrigé</span></h3>
<p>C'est pourtant lui qui détient un secret de déploiement, alors que <code>ci.yml</code> restreint correctement à <code>contents: read</code>. Il se déclenche par ailleurs sur <code>pull_request</code> et lit un secret vide pour un fork, ce qui fait échouer l'étape de déploiement.</p>
</div>

<h2><span class="num">05</span>Défauts mineurs</h2>
<ul class="tight">
<li><strong>Fins de ligne <code>CR</code> seules&nbsp;: tous les diagnostics annoncent la ligne 1.</strong> <code>ScanNewline</code> gère le <code>\r</code> nu, mais <code>Advance()</code> n'incrémente la ligne que sur <code>\n</code>.</li>
<li><strong>Les erreurs d'include introuvable ou illisible n'ont pas de position</strong> — ancrées en 0:0, alors que <code>IncludeNode</code> vient justement de recevoir une vraie étendue.</li>
<li><s><strong>Fins de ligne <code>CR</code> seules&nbsp;: tous les diagnostics annoncent la ligne 1.</strong> <code>ScanNewline</code> gère le <code>\r</code> nu, mais <code>Advance()</code> n'incrémente la ligne que sur <code>\n</code>.</s> <span class="badge b-ok">corrigé</span></li>
<li><s><strong>Les erreurs d'include introuvable ou illisible n'ont pas de position</strong> — ancrées en 0:0, alors que <code>IncludeNode</code> vient justement de recevoir une vraie étendue.</s> <span class="badge b-ok">corrigé</span></li>
<li><strong>Des tableaux frères ne différant que par la casse s'effondrent</strong> dans l'analyseur&nbsp;: le dernier écrase le premier dans la table, ce qui masque un raccourcissement réel.</li>
<li><strong><code>TryGetPropertyIgnoreCase</code> dépend de l'ordre d'insertion</strong> quand deux clés frères ne diffèrent que par la casse.</li>
<li><strong>La complétion n'offre que les <code>let</code> de premier niveau</strong> — ni variables d'environnement, ni itérateur de boucle, sans aucune conscience de la position.</li>
<li><strong><code>didClose</code> peut laisser des soulignements périmés</strong>&nbsp;: l'effacement des diagnostics vient après une boucle dont une exception serait avalée par la garde.</li>
<li><s><strong><code>didClose</code> peut laisser des soulignements périmés</strong>&nbsp;: l'effacement des diagnostics vient après une boucle dont une exception serait avalée par la garde.</s> <span class="badge b-ok">corrigé</span></li>
<li><strong>Deux URI ouverts pour le même fichier</strong> rendent la résolution d'includes non déterministe (dépendante de l'ordre d'énumération).</li>
<li><strong><code>cancel-in-progress</code> annule la CI d'un commit déjà fusionné</strong> quand la fusion suivante arrive.</li>
<li><strong><code>client.start()</code> est une promesse flottante</strong> dans l'extension, et ni le client ni l'observateur ne sont ajoutés à <code>context.subscriptions</code>.</li>
<li><s><strong><code>cancel-in-progress</code> annule la CI d'un commit déjà fusionné</strong> quand la fusion suivante arrive.</s> <span class="badge b-ok">corrigé</span></li>
<li><s><strong><code>client.start()</code> est une promesse flottante</strong> dans l'extension, et ni le client ni l'observateur ne sont ajoutés à <code>context.subscriptions</code>.</s> <span class="badge b-ok">corrigé</span></li>
</ul>

<h2><span class="num">06</span>Ce qui a été attaqué et a tenu</h2>
Expand Down
Loading