test: pin the surviving marked-t keys and document the known test limits (#437) #473
No reviewers
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#473
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-437-test-pins"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Resolves #437
Generated autonomously by /autopilot run of 2026-10-18
Résumé
Maillon 6 sur 8 de la pile
planned-2026-10-16-lot-v018, basé surissue-393-category-hierarchy(PR #472). Restes non bloquants des revues de la pile #433 à #436 : relecture des cinq commits de suivi appliqués sans relecture, épingles manquantes, limites documentées. Aucun changement de comportement : des tests, des commentaires et de la documentation (un commentaire dedb.tscompris), aucune entrée de CHANGELOG, aucune clé i18n.Partie 1 — Relecture des cinq commits de suivi
Chaque diff lu contre son message et contre les revues 23505 (#433), 23495 (#434), 23499 (#435), 23511 (#436) et les suivis 23535, 23550. Les mutations du relecteur, rejouées ici sur la suite complète (R1 à R13, tableau plus bas), sont toutes rouges.
74fae14—fix(db): follow-ups of the review of PR #433: relu, rien à signaler. Le diff règle S1, S2, S3, S4 et S5 de la revue 23505 comme le dit son message :close()d'un handle degetDb()passe par une sectionconnection closeet vérifie sa génération ;closeUnlockedvide l'état et incrémente la génération avantclose(), et un échec part au Journal parlogWarn(withoutFolders(…))sans rejeter ; l'alerte de blocage parle de cause possible ; le contrôle de génération du handle de transaction est commenté comme une défense inatteignable. Vérifié en plus : les deux appelants decloseDb()(switchProfileetdeleteProfiledeProfileContext) enchaînentconnectToProfile, qui ouvre maintenant le profil suivant même si l'ancien pool refuse de se fermer ;logWarnne peut pas lever (sessionStoragesoustry) ; le test « behind the queue » place bien la vérification entre deux opérations (sa réactionthenest enregistrée après celle de la file).a1c31a1—test(harness): follow-ups of the review of PR #434: relu, rien à signaler. Le test « a route change during the 150 ms wait… » épingle les dépendances du suiveur (M1 de la revue 23495, rejouée en R5 : rouge) ; le test de longueur du tableau de dépendances épingle la branche dedepsChanged(M8, rejouée en R6 : rouge). La phrase « NOT SIMULATED » est exacte : ledispatchest créé une fois (writer,??=) avec le reducer du premier rendu. « Un reducer défini au niveau du module, seul cas utilisé » reste vrai sur la base : les reducers des hooks passés au harnais (useOnboardingChecklist,useCategories,useAdjustments,useBudget) sont tous au niveau du module.ac3a981—test(i18n): follow-ups of the review of PR #435: relu, rien à signaler.renderCategoryLabel.test.tspassemarkedTet asserte la forme marquée ; la garde reconnaîtt = (,t = vi.fn(ett: vi.fn(, ancrés sur une frontière de mot (t === (etconst at = (restent propres), et exige un appeli18nMock(hors commentaires. Les faux positifs possibles (un//dans une chaîne coupe la ligne ;const t = (await …)serait refusé) rougissent la garde, ils ne la font jamais passer à tort.86eff9b—fix(profiles): follow-ups of the review of PR #436: code conforme à son message ; trois défauts de documentation, corrigés ici sans toucher au code. R10 à R12 rouges (R12, l'ancienne règle « un blanc termine les dossiers », fait rougir 18 tests).withoutFoldersdisait « a closing parenthesis », alors que le code ne s'arrête qu'à une parenthèse fermante non suivie d'un séparateur (comme le disent le message du commit et l'ADR). Corrigé, avec un renvoi à l'ADR 0021.-». Faux pour un morceau qui porte deux séparateurs ou plus, réduit à son dernier segment (sonde :dossier/sous/x.dbdonnex.db) ; seuls les mots d'un dossier qui contient un blanc restent (dossier/sous dossier/x.dbdonnedossier-sous dossier-x.db). Phrase précisée.C:\Users\Jean (Work) Smith\AppData\x.dbdonneJean (Work) x.db;C:\Users\jean\My;Docs\x.dbdonneMy;Docs-x.db; une apostrophe inverse dans le nom fait de même). Écrite comme seconde limite dans l'ADR 0021 § 7. Pas de correctif de code : séparer(see /x/y.db) and…deJean (Work) Smith\serait une autre heuristique, et l'issue exclut tout changement de comportement. À Max de dire s'il veut une issue de suivi.L'arrêt
\rn'avait pas de test propre (déjà admis par 23535) : épinglé en partie 2.c17bf5d—fix(balance): translate the best-effort badge of the price fetch button: relu, rien à signaler. Le badge passe part("balance.priceFetching.bestEffortBadge")(« non garanti », décision de Max du 2026-10-16), clé présente dans les deux langues, entrée Corrigé / Fixed dans les deux CHANGELOG (publiée dans la v0.17.2). R13 (littéral remis) : rouge.Partie 2 — Épingles
Clés lues sur la base
8a9d990(#369 et #429 ont touchéTransactionTable.tsx) ; chemins corrigés par le plan, pastransactions.table.*.\rsrc/services/db.test.ts["\r"]ajouté à l'it.each« withoutFolders ends the folders at %j »transactions.transferIcon.ariaLabelTransactionTable.render.test.tsxaria-label="t(transactions.transferIcon.ariaLabel)", une seule fois, sur la ligne liée à un transfert (le helpermarkupprendlinkedTransfersByTxId)transactions.notes.placeholderTransactionTable.render.test.tsxtitle="t(transactions.notes.placeholder)"sur le bouton de notes de chaque ligne (toujours rendu, choix du plan)TransactionTable.wiring.test.tstextarea, dont leplaceholdervautt(transactions.notes.placeholder)license.keyPlaceholderLicenseKeyForm.render.test.tsxplaceholder="t(license.keyPlaceholder)"license.activateLicenseKeyForm.render.test.tsx<button type="submit" …>t(license.activate)</button>balance.priceFetching.consent.acceptPriceFetchControl.test.tsxshowConsentModal) ;>t(balance.priceFetching.consent.accept)<, plus le titre, le texte et « Refuser » de la même fenêtredashboard.kpiSectionTitleDashboardPage.render.test.tsx>t(dashboard.kpiSectionTitle)<PriceFetchControlse prête au préréglage : aucune clé déclarée non épinglable.Partie 3 — Limites documentées
slotdefakeReact,src/test/hookHarness.ts) à chaque préréglage :markup()dePriceFetchConsentToggle.test.tsx,mountWithdeuseOnboardingChecklist.wiring.test.ts(qui couvre aussi ses deux écritures directes deharness.slots[0]), le nouveaumarkup()dePriceFetchControl.test.tsx, et le premier préréglage deSystemsSettingsPage.test.tsx(ajouté par #372 dans cette pile).docs/architecture.md, fin de la section Tests : « Limites connues (#437) ». Les emplacements préréglés sont écrits en entier (nulle part avant) ;withoutFolderset la mesure du rattrapage renvoient à l'ADR 0021 (§ 7, et le point « Le délai de démarrage couvre le rattrapage du profil actif »), qui les portaient déjà : 306 ms, SSD NVMe et risque d'un disque lent ou d'un antivirus ne sont pas recopiés. Ajouté seulement ce que l'ADR ne dit pas : le test#[ignore]ne tourne pas en CI et n'asserte rien.withoutFolders(défauts 2 et 3 de la partie 1).Fichiers
src/services/db.test.ts\rsrc/services/db.tswithoutFoldersseulementsrc/components/transactions/TransactionTable.render.test.tsxlinkedTransfersByTxIddu helpersrc/components/transactions/TransactionTable.wiring.test.tssrc/components/settings/LicenseKeyForm.render.test.tsxtechoes its key » corrigésrc/components/balance/PriceFetchControl.test.tsxvi.mock("react")), helpermarkup, 1 test ; en-tête périmé corrigésrc/pages/DashboardPage.render.test.tsxsrc/components/settings/PriceFetchConsentToggle.test.tsxsrc/hooks/useOnboardingChecklist.wiring.test.tssrc/pages/settings/SystemsSettingsPage.test.tsxdocs/architecture.mddocs/adr/0021-migrations-profils-secondaires.mdDécisions
13 décisions : 7 HIGH, 6 MEDIUM, 0 LOW (détail dans le journal de décisions du run).
reactpar le harnais va dansPriceFetchControl.test.tsx, le fichier que nomme l'issue, et le rendu existant passe par le même helpermarkup()(harness.render), commePriceFetchConsentToggle.test.tsx: sous un mock de fichier, un rendu JSX par react-dom/server appellerait les hooks du harnais sans remise à zéro du curseur. Écartés : un fichier de test à part ; garder le rendu JSX avec un simpleharness.clear().titledu bouton ; le second appel (placeholderde latextarea) l'est aussi, dansTransactionTable.wiring.test.ts(créé par #369 après le plan), par un clic dans l'arbre rendu, sans emplacement préréglé. La revue 23499 ne dit pas lequel des deux appels elle avait muté.SystemsSettingsPage.test.tsx(même décalage silencieux) ;OnboardingStepCard.test.tsxne fait que lire l'emplacement 0 et dit déjà « its first hook » : cité dansarchitecture.md, pas commenté.architecture.md: section ajoutée en fin de « Tests », renvois à l'ADR 0021 plutôt que recopie.86eff9b: défauts de documentation corrigés, la seconde limite écrite, aucun changement du code ni test qui fige la fuite.v0.17.2) ; chemins des clés lus sur la base ; verdicts de la partie 1 ; en-têtes périmés deLicenseKeyForm.render.test.tsxet (auto-revue) dePriceFetchControl.test.tsxcorrigés ; pas de CHANGELOG ; niveau normal ; formulation de la seconde limite généralisée à tout arrêt dans un nom de dossier (sondeMy;Docs).Preuves
Passe de mutations par script à table, une mutation à la fois, suite complète (152 fichiers) à chaque fois, restauration par
git checkout --et arbre vérifié propre après chacune ; jouée après le commit des tests.Épingles de cette PR (rouges attendues : le test du composant)
src/services/db.ts\rretiré dePATH_STOPdb.test.ts)TransactionTable.tsxaria-labelde l'icône de transfert sanstTransactionTable.render.test.tsx)TransactionTable.tsxtitledu bouton de notes sanstTransactionTable.tsxplaceholderde latextareade notes sanstTransactionTable.wiring.test.ts)LicenseKeyForm.tsxplaceholderdu champ sanstLicenseKeyForm.render.test.tsx)LicenseKeyForm.tsxtLicenseKeyForm.render.test.tsx)PriceFetchControl.tsxconsent.acceptsanstPriceFetchControl.test.tsx)PriceFetchControl.tsxconsent.titlesanstPriceFetchControl.tsxconsent.bodysanstPriceFetchControl.tsxconsent.declinesanstDashboardPage.tsxdashboard.kpiSectionTitlesanstDashboardPage.render.test.tsx)PriceFetchControl.tsxuseStateajouté avantshowConsentModal(décalage des emplacements)Mutations rejouées des cinq commits relus
74fae14close()d'un handle degetDb()sans contrôle de génération74fae14closeUnlockedrelance l'échec duclose()74fae14lockHolderjamais remis ànull74fae14close()écrit sanswithoutFoldersa1c31a1pathnamedans les dépendances du suiveur (M1 de 23495)a1c31a1depsChangedretirée (M8 de 23495)ac3a981t: (ac3a981i18nMocksuffit (commentaires compris)ac3a981renderCategoryLabelsanst86eff9b)n'arrête jamais un chemin86eff9b86eff9bfbecfff)c17bf5dbest-effortComptes
npm run buildvert (tsc+ vite).src/zz_tmp_probe.test.ts, unexpectrouge, supprimée).cargo test.Vérifications manuelles dues (prochaine release)
Aucune : la PR ne change ni comportement ni texte visible.
Pour le relecteur
test:), les commentaires et la documentation (docs:), puis une correction d'auto-revue (docs:, en-tête dePriceFetchControl.test.tsxqui disait encore tout rendu React contourné).license.activateest aussi appelée par le bouton « Activer » de la section Machines (LicenseCard.tsx) : déjà épinglée sous forme marquée (sonde :tretiré là, 2 tests rouges dansLicenseCard.render.test.tsx).PriceFetchControl.test.tsxest maintenant entièrement sous le harnais (mock dereactau niveau du fichier) ; les describes qui ne rendent rien n'en sont pas affectés, et le test de rendu existant garde ses six assertions telles quelles.architecture.mdétait déjà incomplète avant cette PR (TransactionTable.wiring,AdjustmentForm.wiring,LinkTransfersModal.wiring,HierarchyCheckModal.wiring,useAdjustments,useCategories,ChangelogContent,SystemsSettingsPage,ProfileFormModal.deleten'y figurent pas) ; non mise à jour ici, hors périmètre ;PriceFetchControl.test.tsxs'y ajoute.withoutFolders(défaut 3 de la partie 1) : documentée, pas corrigée ; une issue de suivi est à décider.🤖 Generated with Claude Code
Niveau : normal
Verdict : APPROVE
Auto-revue de l'auteur (worker /autopilot), pas une revue indépendante. Checklist de
/pr-reviewappliquée au diff complet de la PR contre sa baseissue-393-category-hierarchy, à la profondeur du niveau normal.Résumé. Tests, commentaires et documentation seulement : l'arrêt
\ret les six clés survivantes de la revue 23499 sont épinglés sous forme marquée (plus le second appel de la clé des notes et les trois autres textes de la fenêtre de consentement), la dépendance à l'ordre des hooks est commentée à chaque préréglage d'emplacement, et les limites connues sont écrites sans recopier l'ADR 0021. Les cinq commits de suivi sont relus : rien à signaler sur quatre ; sur86eff9b, trois défauts de documentation corrigés ici, sans toucher au code.Niveau (Step 0bis,
REVIEW.mddemain)Fichier par fichier : les douze fichiers sont normaux. Aucune ligne du tableau Haut n'est remplie : les tests sous
src/**n'ajoutent aucun appel réseau et ne retirent ni ne contournent aucun consentement (PriceFetchControl.tsxetPriceFetchConsentToggle.tsxne sont touchés que par leurs tests, qui ouvrent la fenêtre dans un rendu de test) ;src/services/db.ts(commentaire seul),docs/architecture.mdetdocs/adr/**restent au moins normaux ; aucun fichier ajouté, renommé ou supprimé.Ce qui a été exécuté
expectrouge fait sortir vitest en rc=1 ; fichier supprimé.npm run buildvert ;npm test: 152 fichiers, 2465 tests verts, sur la têtedad81fa.tretiré du bouton « Activer » des Machines (LicenseCard.tsx, autre appel delicense.activate) : 2 rouges dansLicenseCard.render.test.tsx, cet appel était déjà épinglé.zz_tmp_*laissé.Checklist
Jean Dupont,marie claire,Jean (Work) Smith) ; aucun.env.PriceFetchControl.test.tsxpasse entier sous le harnais, et le test de rendu existant garde ses six assertions..onlyni.skip; aucune régression (suite verte).test:,docs:) ; aucune chaîne visible ; mot-clé de fermeture en première ligne du corps et dans le dernier commit, nulle part ailleurs ; la timeline de l'issue porte un seulpull_refencloses, celui de cette PR.REVIEW.md: « i18n et documentation » (rien de visible, donc pas de CHANGELOG ;architecture.mdet l'ADR 0021 à jour). « Vie privée » : la règle « un message du Journal nomme un fichier, jamais son dossier » a une exception préexistante, que la PR documente sans changer le code (suggestion 1).Constat corrigé
src/components/balance/PriceFetchControl.test.tsx:1-6: l'en-tête disait encore que tout rendu React du fichier était contourné, alors que ses tests « displayed texts » rendent le contrôle, hooks fournis par le harnais. Corrigé dansdad81fa, avec une précision de formulation dansdocs/architecture.md(préréglages « commentés dans son fichier »).Corrigé aussi dans le corps de la PR avant ce verdict : la ligne M5 disait que
LicenseCard.render.test.tsxlaissait passer l'oubli par une assertion en sous-chaîne ; ses assertionslicense.activatevisent le bouton « Activer » des Machines, déjà épinglé.Suggestions (non bloquantes)
withoutFolders(défaut 3 de la partie 1, maintenant dans l'ADR 0021 § 7) : un nom de dossier qui contient l'un des arrêts laisse ce nom, ou son début, dans la ligne du Journal (Jean (Work) x.db). Cas rare, et le côté Rust remplace déjà le dossier des profils par<profile folder>; le correctif changerait le comportement, ce que l'issue exclut. À Max de décider d'une issue de suivi.docs/architecture.mdétait déjà incomplète avant cette PR (neuf fichiers de test plus récents n'y figurent pas,PriceFetchControl.test.tsxs'y ajoute) : à rafraîchir avec un autre suivi de documentation.CI lue par l'orchestrateur du run
/autopilotdu 2026-10-18 :check-frontendvert sur la têtedad81fa(run 584).db.test.ts(60),PriceFetchControl.test.tsx(19),TransactionTable.render.test.tsx(8),TransactionTable.wiring.test.ts(6),LicenseKeyForm.render.test.tsx(5),DashboardPage.render.test.tsx(7),PriceFetchConsentToggle.test.tsx(12) etuseOnboardingChecklist.wiring.test.ts(18).check-rustne s'applique pas à ce maillon (aucun chemin Rust touché).86eff9b: un nom de dossier qui contient un caractère d'arrêt (), accent grave…) laisse ce nom, ou son début, dans la ligne du Journal (C:\Users\Jean (Work) Smith\AppData\x.dbdonneJean (Work) x.db). Le cas est documenté comme limite dans l'ADR 0021 §7 et n'est pas corrigé ici, puisque l'issue exclut tout changement de comportement.Niveau : normal
Verdict : APPROVE
Résumé. Les six clés survivantes de la revue 23499 et l'arrêt
\rsont épinglés sous la forme marquée : chaque mutation «tretiré » que j'ai rejouée rougit le test du composant sur la têtedad81faet restait verte sur la base8a9d990. Les faits ajoutés à l'ADR 0021, àarchitecture.mdet aux commentaires tiennent à la sonde, sauf une phrase sur le test#[ignore](suggestion 1). Aucun changement de comportement ; les suggestions relèvent d'issues de suivi, pas d'un tour de plus.Niveau. Aucun fichier n'entre dans le tableau Haut : des tests,
docs/adr/**etdocs/architecture.md(au moins normaux), un commentaire seul danssrc/services/db.ts(normal). La ligne « code livré » ne s'applique pas :PriceFetchControl.test.tsxetPriceFetchConsentToggle.test.tsxne changent que du test et des commentaires, sans appel réseau ni consentement touché.Rejoué (copie hors dépôt)
npm ci,npm run build(tsc + vite) vert ;vitest run: 152 fichiers, 2465 tests verts (2458 sur la base, soit +7) ; sonde rc=1.check-frontendrun 584 surdad81fa, journal lu : build, 152 fichiers, 2465 tests.\rretiré dePATH_STOPdb.test.ts)aria-labelde l'icône : clé brute, sansttitledu bouton de notes : clé brutetitledu bouton de notes sur la 1re ligne seulementplaceholderde latextarea: autre cléplaceholderdu champ de clé écrit en durconsent.accept: clé bruteuseEffectajouté avantshowConsentModal(décalage des emplacements)bestEffortNoticebrut (test existant, passé sous le harnais)transferIcon.tooltip) : clé brutecommon.canceldeLicenseKeyForm: clé bruteonAccepthandleClickne regarde plus le consentement (if (false))!isPremium)hasConsent()rend toujourstrueUne première version de X2 plantait sans table de liens (13 rouges sans rapport avec l'épingle) : remplacée par X2b.
withoutFolderssur les exemples ajoutés :dossier/sous/x.db→x.db,dossier/sous dossier/x.db→dossier-sous dossier-x.db,C:\Users\Jean (Work) Smith\AppData\x.db→Jean (Work) x.db,C:\Users\jean\My;Docs\x.db→My;Docs-x.db. Le commentaire corrigé dedb.tsdécrit bien la ligne 371 (parenthèse fermante non suivie d'un séparateur).architecture.md: les six hooks couverts prennent chacun un emplacement (slotdefakeReact) ; la liste des préréglages est complète (slots[danssrc/: ces cinq fichiers, rien d'autre ;mountWithet les écritures des l. 360 et 384 ; deux préréglages dansSystemsSettingsPage.test.tsx) ; la section et le point cités de l'ADR 0021 existent. Les quatre commentaires d'ordre des hooks correspondent aux composants (showConsentModal;hasConsent,showConfirm,loading;version; leuseReduceren premier).fr.jsoneten.json.closeDb()dansProfileContext,closeUnlocked, motifs de la garde i18n : conformes au corps de la PR.pull_refenclosessur #437, celui de cette PR.Suggestions (non bloquantes)
architecture.md, « Mesure du rattrapage » : « n'asserte rien » est inexact.a_large_profile_catch_up_durationasserte que le rattrapage aboutit (catch_up_erroràNoneet plancher 6,profile_db.rs:1755-1756) ; il n'asserte rien sur la durée. Proposé : « n'asserte rien sur la durée, qu'il imprime après avoir vérifié que le rattrapage aboutit ». Le commentaire Rust (« Prints, never asserts », l. 1706) porte la même imprécision. Phrase inchangée au sommet de la pile (#475).TransactionTable.render.test.tsxaffiche l'infobulle de l'icône sans l'asserter (X4), ettransactions-transfer-icon.test.tsne lit que la source, donc une clé brute passe. Une ligne dans le même test l'épingle, avec la clé de direction :expect(bodyRows(html)[1]).toContain('title="t(transactions.transferIcon.tooltip): CELI (t(balance.transfers.direction.in))"')(balisage relevé par sonde). Même cas pourcommon.cancel, rendu par le nouveau test deLicenseKeyForm(X11). Le test des notes ne dit pas quelle ligne se déplie (X8) : lesFragmentportentkey={row.id}, chercher latextareasous celui de la ligne 2 le dirait.PriceFetchControl(zone Vie privée) : aucun test n'exerce le parcours de consentement ni la garde Premium (X12 et Y1 à Y4 restent verts sur la suite complète). Les six describes autres que « displayed texts » appellent les mocks et recalculent les conditions, sans appeler le composant ; l'en-tête réécrit pardad81fadit encore qu'ils « cover the component's internal logic ». Ce consentement n'est vérifié que côté front,fetch_pricene le revérifie pas (REVIEW.md). Le fichier étant maintenant sous le harnais, une issue de suivi peut testerhandleClick, « Accepter » et « Annuler » par l'arbre rendu (appeler leonClickdu bouton, attendre, rendre de nouveau, lire la fenêtre etfetchPrice), avec ces cinq mutations pour critère, et corriger l'en-tête.withoutFolders, pour la décision de Max : une issue de suivi en priorité basse.withoutFoldersest la seconde barrière derrièrescrub(Rust), qui remplace déjà le dossier des profils par<profile folder>; et un nom de compte local Windows ne peut contenir ni;, ni|, ni,, ni:. Le cas réaliste est un nom de compte avec des parenthèses suivies d'un autre mot, dans un chemin quescrubn'a pas remplacé.architecture.md) n'inclut pasPriceFetchControl.test.tsx; écart signalé dans le corps de la PR, à joindre au suivi.Actions faites
/tmp/pr473-review(npm ci), supprimé en fin de revue avec les fichiers/tmp/pr473-*.status:review→status:approved.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.