The audit must say how much of the engine its tests really check. Of 2576 mutants, 2171 are killed, 207 time out, 61 are declared equivalent with a reason a reviewer can check, and 137 survive, listed by file, operator and line; the ranking, indicators and ceiling modules have none left. New tests in classement, indicateurs and plafond kill the survivors found there, each red under its mutant. Checked: 3677 node and 101 long tests green from the index alone. --- FR --- [ADD] audit : premier audit par mutation du moteur, survivants tués L'audit doit dire combien du moteur ses épreuves vérifient vraiment. Sur 2576 mutants, 2171 sont tués, 207 dépassent leur délai, 61 sont déclarés équivalents avec une raison qu'un relecteur vérifie, et 137 survivent, listés par fichier, opérateur et ligne ; le classement, les indicateurs et le plafond n'en ont plus. De nouvelles épreuves de classement, indicateurs et plafond tuent les survivants trouvés là, chacune rouge sous son mutant. Vérifié : 3677 node et 101 longues vertes depuis l'index seul. Assisted-by: Claude Opus 5.5
246 lines
17 KiB
JSON
246 lines
17 KiB
JSON
[
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:nombre-plus-un:00c7051f9d2508f1:0",
|
||
"raison": "indicateurs.js, parcourirTours, visites[t] += 2 au lieu de 1 : visites[t] ne se lit que par visites[t] > 0 et se remet à 0 après chaque personne ; un pas de 2 garde le signe, aucune sortie ne change."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:nombre-plus-un:7501d61d37d5e2f8:0",
|
||
"raison": "indicateurs.js, parcourirTours, reserveeAvant[t] = 2 au lieu de 1 : la marque ne se lit que par reserveeAvant[t] === 0."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:frontiere:8d0d1504ba708607:1",
|
||
"raison": "indicateurs.js, parcourirTours, remise à zéro jusqu'à r <= R : le tour de trop lit la première case de la personne suivante, dont la table vaut 0 dans visites et reserveeAvant sauf si la personne courante l'a visitée, auquel cas la boucle la remet à 0 de toute façon ; pour la dernière personne la case est undefined, et une écriture à l'index undefined pose une propriété hors des éléments du tableau typé, que rien ne lit."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:si-faux:032af4d6881bbbc2:1",
|
||
"raison": "indicateurs.js, parcourirTours, remise à zéro sans le continue des cases RESERVE : la case −1 écrit visites[−1] et reserveeAvant[−1] ; un index hors des éléments d'un tableau typé n'écrit rien."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:corps-si:0bf37874b7af9907:1",
|
||
"raison": "indicateurs.js, parcourirTours, if (t === RESERVE) {} : même effet que le mutant si-faux du même if — visites[−1] et reserveeAvant[−1] ; un index hors des éléments d'un tableau typé n'écrit rien."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:frontiere:540d595717113ffa:0",
|
||
"raison": "indicateurs.js, parcourirTours, i <= liste.length : le tour de trop lit a = undefined ; revenu[NaN] et fixe[NaN] sont undefined, rien n'est poussé, et la boucle intérieure part de j = length + 1, au-delà de la liste."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:frontiere:cde969d8987ccd53:0",
|
||
"raison": "indicateurs.js, parcourirTours, j <= liste.length : le tour de trop lit b = undefined ; k = rangPaire(N, a, undefined) vaut NaN, parPaire[NaN] et libre[NaN] n'écrivent rien sur un tableau typé, groupe[undefined] n'égale aucun groupe et parPaire[NaN] >= 2 est faux : ni collègue ni revue n'est poussé."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:nombre-plus-un:227d5e978a2c6f6e:0",
|
||
"raison": "indicateurs.js, lirePaires, vu[p * G + g] = 2 au lieu de 1 : la marque ne se lit que par === 0."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:frontiere:344134eea29f143b:0",
|
||
"raison": "indicateurs.js, lirePaires, a <= N : pour a = N, la boucle intérieure (b de N + 1 à N − 1) ne tourne pas, et k n'avance pas."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:frontiere:d9e6e8ece30ea311:0",
|
||
"raison": "indicateurs.js, lirePaires, n >= maxRencontresPaire : à égalité, l'affectation écrit la valeur déjà retenue."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:arithmetique:4883685ba05bd48f:1",
|
||
"raison": "indicateurs.js, lireTours, nombrePaires = N(N + 1)/2 : ne dimensionne que collegueVu et revueVue, indexés par rangPaire, toujours < N(N − 1)/2 ; un tableau plus long garde les mêmes cases utiles, les autres ne se lisent jamais."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:nombre-zero:4883685ba05bd48f:1",
|
||
"raison": "indicateurs.js, lireTours, nombrePaires = N·N/2 : même raison que N(N + 1)/2 — une longueur au moins égale (tronquée à l'entier par le constructeur du tableau typé) pour des index rangPaire < N(N − 1)/2."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:arithmetique:9befd8786dbb9e8f:1",
|
||
"raison": "indicateurs.js, lireTours, nombrePaires = 2N(N − 1) : longueur au moins égale à N(N − 1)/2, mêmes cases utiles, les autres jamais lues."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:nombre-plus-un:3ab1dfff408dce14:0",
|
||
"raison": "indicateurs.js, lireTours, collegueVu[k] = 2 au lieu de 1 : la marque ne se lit que par === 0."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:nombre-plus-un:b13533cdd354d276:0",
|
||
"raison": "indicateurs.js, lireTours, revueVue[k] = 2 au lieu de 1 : la marque ne se lit que par === 0."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:frontiere:c87986ba8e01803b:0",
|
||
"raison": "indicateurs.js, ajouter, valeur <= min : à égalité, le minimum retenu est la même valeur."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:frontiere:6f32f41253f60a4b:2",
|
||
"raison": "indicateurs.js, mesurer, p <= N au compte des effectifs : groupe[N] est undefined, différent de SANS_GROUPE ; effectifs[undefined] += 1 pose une propriété « undefined » sur un tableau ordinaire, et parGroupe ne lit que les index 0 à G − 1."
|
||
},
|
||
{
|
||
"cle": "src/moteur/indicateurs.js:si-vrai:fcd03735b3f47217:0",
|
||
"raison": "indicateurs.js, mesurer, if (true) au compte des effectifs : une personne sans appartenance incrémente effectifs[SANS_GROUPE], soit effectifs[−1], propriété hors des index d'un tableau ordinaire ; parGroupe ne lit que les index 0 à G − 1."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:arithmetique:4ff9d4aad2110e83:0",
|
||
"raison": "plafond.js, borne, min(N + 1, …) : le terme Σ a_t + min(n_p, S) ne dépasse jamais N − 1. Les ancrés des tables distinctes, p exclu, sont au plus k − 1 pour un ancré et k sinon ; n_p vaut n pour un ancré et n − 1 sinon ; la somme vaut au plus k + n − 1 = N − 1 (n = N − k, configuration.js). Le min extérieur ne mord jamais, que sa borne soit N − 1 ou plus."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-zero:4ff9d4aad2110e83:0",
|
||
"raison": "plafond.js, borne, min(N − 0, …) : même raison que min(N + 1, …) — le terme intérieur vaut au plus N − 1."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:1bad6b8cf97131fc:0",
|
||
"raison": "plafond.js, ancrageDe, −2 au lieu de −1 pour un non-ancré : l'ancrage ne sert qu'à t === ancrage, où t est un index de table ≥ 0, et à la clé de signature, où −2 remplace −1 pour tous les non-ancrés à la fois : aucune comparaison ni aucun regroupement ne change."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:frontiere:66f4a0fe878c0caf:0",
|
||
"raison": "plafond.js, tablesAdmissibles, t <= T : ancresParTable[T] et capacite[T] sont undefined, undefined < undefined est faux, rien ne s'ajoute."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:frontiere:6f32f41253f60a4b:0",
|
||
"raison": "plafond.js, plafondsRealises, p <= N : la case N × R + r est hors du plan (undefined, différent de RESERVE) ; occupation[NaN] += 1 n'écrit rien sur un Int32Array."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:si-vrai:f99905fb09a97ec2:0",
|
||
"raison": "plafond.js, plafondsRealises, if (true) : une case RESERVE (−1) écrit occupation[−R + r], index négatif puisque r < R ; un index hors des éléments d'un tableau typé n'écrit rien."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:si-vrai:4e2d29d60a734ece:0",
|
||
"raison": "plafond.js, signature, chaque case poussée, LIBRE comprise : le nombre de cases LIBRE vaut R moins le nombre de tours fixés, que le multiensemble des tables fixées donne déjà ; deux clés sont égales sous le mutant si et seulement si elles le sont sans lui."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:arithmetique:1e3e1be34f22da4b:0",
|
||
"raison": "plafond.js, signature, tri par x + y : le tri ne sert qu'à rendre la clé indépendante de l'ordre des tours. Un ordre faux peut séparer deux rangées de même multiensemble en deux clés, jamais réunir deux multiensembles distincts — la clé garde ses éléments — : la valeur mémoïsée reste exacte, seul le partage se perd."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:d0a020f0a45907d8:0",
|
||
"raison": "plafond.js, maximiser, vMax part de 1 : vMax ne sert qu'à W, qui grandit ou reste. Tout W' ≥ W rend le même plafond : sans écrêtage (W' ≥ f·vMax) la programmation dynamique est exacte, et un écrêtage à W' ≥ cap ne fond que des états où min(n_p, sieges0 + w) vaut déjà n_p."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:min-max:921cce52c896cad6:0",
|
||
"raison": "plafond.js, maximiser, W = max(cap, f·vMax) : W grandit ou reste ; même raison que vMax partant de 1 — tout W' ≥ W rend le même plafond."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:6aaa76d38a359d8b:0",
|
||
"raison": "plafond.js, maximiser, cap = max(1, n_p − sieges0) : W grandit ou reste ; tout W' ≥ W rend le même plafond (voir vMax partant de 1)."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:arithmetique:bf9f37f58ec637aa:0",
|
||
"raison": "plafond.js, maximiser, cap = max(0, n_p + sieges0) : sieges0 ≥ 0 (v ≥ 0 pour toute table qu'un plan valide fixe), donc W grandit ou reste ; tout W' ≥ W rend le même plafond (voir vMax partant de 1)."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:0bde1efec9ee24ca:0",
|
||
"raison": "plafond.js, maximiser, largeur = W + 2 : une colonne de plus par rangée, jamais écrite (cible ≤ W) ni lue (w ≤ W) ; chaque état garde une case distincte."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:6a44835bbd054679:0",
|
||
"raison": "plafond.js, maximiser, (f + 2) × largeur cases : une rangée de plus en fin de tableau, jamais lue ni écrite (s + m ≤ f)."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:1bad6b8cf97131fc:1",
|
||
"raison": "plafond.js, maximiser, fill(−2) : le marqueur d'état inatteignable ne se lit que par < 0 et >= 0, et tout atteint + gain ≥ 0 le dépasse ; −2 se comporte comme −1."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:frontiere:ebba58ec39728177:0",
|
||
"raison": "plafond.js, maximiser, s <= f : à s = f, la boucle sur m (s + m ≤ f) ne tourne pas."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:frontiere:f0a78f7a10078a9f:0",
|
||
"raison": "plafond.js, maximiser, atteint + gain >= suivant[cible] : à égalité, l'affectation écrit la valeur déjà présente."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:1bad6b8cf97131fc:2",
|
||
"raison": "plafond.js, maximiser, plafond part de −2 : l'état (f, W) est toujours atteint — la table de plus grand v prise f fois — avec une somme d'ancrés ≥ 0, et sa borne vaut au moins 0 ; le maximum ne dépend pas de la valeur initiale, pourvu qu'elle ne dépasse pas 0."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-zero:1bad6b8cf97131fc:2",
|
||
"raison": "plafond.js, maximiser, plafond part de −0 : même raison que −2 — un état atteint donne une borne x ≥ 0, et Math.max(−0, x) = x."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:si-vrai:717790d7ce1ce378:0",
|
||
"raison": "plafond.js, maximiser, if (true) sur ajout >= 0 : un état inatteignable porte −1, soit ancres0 − 1, à un w ≤ W ; l'état (f, W) est atteint avec une somme ≥ 0, et la borne, croissante en ses deux termes, y vaut au moins autant : un état inatteignable ne l'emporte jamais."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:frontiere:8d0d1504ba708607:4",
|
||
"raison": "plafond.js, enumerer, r <= R : itineraire[R] est undefined, qui n'égale pas LIBRE ; aucun tour libre ne s'ajoute."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:1bad6b8cf97131fc:3",
|
||
"raison": "plafond.js, enumerer, plafond part de −2 : au moins un itinéraire s'évalue (f > 0 et A > 0), et son plafond est ≥ 0 ; la valeur initiale ne l'emporte jamais."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-zero:1bad6b8cf97131fc:3",
|
||
"raison": "plafond.js, enumerer, plafond part de −0 : au moins un itinéraire s'évalue, de plafond x ≥ 0, et Math.max(−0, x) = x."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:frontiere:8f48d3d06744671e:0",
|
||
"raison": "plafond.js, enumerer, i <= f : libres[f] est undefined ; itineraire[undefined] = … pose une propriété hors des index de l'Int32Array, que plafondItineraire ne lit pas (il lit length et les index 0 à R − 1)."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-zero:3cdd668f03bae9c9:0",
|
||
"raison": "plafond.js, enumerer, j = i + 0 : le premier tour écrit choix[i] = choix[i], sans effet ; les tours suivants sont ceux du code."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:frontiere:2ad7eaa66ad4393a:0",
|
||
"raison": "plafond.js, enumerer, j <= f : choix[f] est hors d'un Int32Array de f cases ; un index hors des éléments d'un tableau typé n'écrit rien."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:arithmetique:c621ca71e6b7f974:6",
|
||
"raison": "plafond.js, plafondsAPrioriParEnumeration, clé subarray(p / R, …) : l'index de début se tronque, et la clé devient une tranche qui finit par la rangée de p. Pour R ≥ 2 sa longueur, (p + 1)R − ⌊p/R⌋, croît strictement avec p : aucune clé n'est partagée, chaque plafond se calcule et reste exact ; pour R = 1, la tranche est la rangée même."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:nombre-plus-un:722cded1530bd637:1",
|
||
"raison": "plafond.js, plafondsAPrioriParEnumeration, clé subarray(pR, (p + 2)R) : la clé ajoute la rangée suivante (rien pour la dernière personne, dont la clé a R cases contre 2R) ; deux clés égales ont même longueur et même début, donc même rangée : le regroupement se fait plus fin, jamais plus large."
|
||
},
|
||
{
|
||
"cle": "src/moteur/plafond.js:si-vrai:b5e28aed44dacc4e:1",
|
||
"raison": "plafond.js, plafondsAPrioriParEnumeration, if (true) : le plafond se recalcule pour chaque personne au lieu d'être repris de sa rangée ; même valeur, seule la mémoïsation de l'oracle se perd, et l'oracle n'a pas de budget de temps."
|
||
},
|
||
{
|
||
"cle": "src/moteur/classement.js:frontiere:d2e0232a8a610afd:0",
|
||
"raison": "classement.js, plusGrand, valeur >= plus : à égalité, l'affectation écrit la valeur déjà retenue."
|
||
},
|
||
{
|
||
"cle": "src/moteur/classement.js:frontiere:6d8294f499162f5c:0",
|
||
"raison": "classement.js, comparerCles, i <= a.length : a[length] et b[length] sont tous deux undefined, donc égaux ; la boucle finit et rend 0, comme sans le tour de trop."
|
||
},
|
||
{
|
||
"cle": "src/moteur/classement.js:frontiere:d5d8d6548f2d9d52:0",
|
||
"raison": "classement.js, comparerCles, a[i] <= b[i] sous a[i] !== b[i] : pour deux nombres différents, <= et < coïncident. Une clé ne mêle jamais null et nombre : le premier critère vaut null pour une liste d'écarts vide, et toutes les entrées ont des listes de même longueur (exigerMemeTaille), toutes vides ou aucune."
|
||
},
|
||
{
|
||
"cle": "src/moteur/classement.js:nombre-plus-un:1bad6b8cf97131fc:0",
|
||
"raison": "classement.js, comparerCles, −2 au lieu de −1 : le résultat ne se lit que par son signe, dans sort et dans le || du départage par identifiant."
|
||
},
|
||
{
|
||
"cle": "src/moteur/classement.js:nombre-plus-un:394f51f11873175b:0",
|
||
"raison": "classement.js, comparerCles, 2 au lieu de 1 : le résultat ne se lit que par son signe, dans sort et dans le || du départage par identifiant."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:frontiere:616dbb8c2f18776c:0",
|
||
"raison": "manque.js, plusGrand, valeur >= cumul : à égalité, le cumul retenu est la même valeur."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:arithmetique:ebfa5f19c5ac6881:0",
|
||
"raison": "manque.js, profilManque, départage a.id + b.id : à manque et plafond réalisé égaux, le comparateur rend un nombre positif. Le tri de V8 ne lit que « < 0 » et est stable : un positif s'y lit comme 0, et l'ordre reçu reste, celui de instance.ids, que normaliser trie par identifiant croissant et sans doublon — l'ordre de a.id − b.id. Une liste reçue dans un autre ordre ne peut pas se construire : profilManque parcourt instance.ids."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:frontiere:a42a37da6acfc1b0:0",
|
||
"raison": "manque.js, comparerProfils, difference <= 0 : la ligne ne s'atteint que pour difference !== 0, où <= 0 et < 0 coïncident."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:nombre-plus-un:a42a37da6acfc1b0:0",
|
||
"raison": "manque.js, comparerProfils, difference < 1 : un manque est un entier (plafond réalisé − rencontres, deux comptes), et la ligne ne s'atteint que pour difference !== 0 : < 1 et < 0 coïncident."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:nombre-plus-un:1bad6b8cf97131fc:0",
|
||
"raison": "manque.js, comparerProfils, signeRang = −2 au lieu de −1 : signeRang ne se lit que par < 0 et par comparaison à signe, qui reçoit les mêmes valeurs ; signe ne se rend pas."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:nombre-plus-un:499febce3e9d753b:0",
|
||
"raison": "manque.js, comparerProfils, signeRang = 2 au lieu de 1 : signeRang ne se lit que par < 0 et par comparaison à signe, qui reçoit les mêmes valeurs ; signe ne se rend pas."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:frontiere:09493d576cddf072:0",
|
||
"raison": "manque.js, comparerProfils, signeRang <= 0 : signeRang vaut −1 ou 1, jamais 0."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:nombre-plus-un:09493d576cddf072:0",
|
||
"raison": "manque.js, comparerProfils, signeRang < 1 : signeRang vaut −1 ou 1 ; < 1 et < 0 coïncident."
|
||
},
|
||
{
|
||
"cle": "src/moteur/manque.js:si-vrai:3f2ec15cfbc2d410:0",
|
||
"raison": "manque.js, comparerProfils, bascule posée à chaque changement : rangBascule ne la rend que pour changements === 1, où la première et la dernière affectation sont la même."
|
||
}
|
||
]
|