docs(onboarding): user guide, architecture and QA checklist for the guided getting-started path #407

Merged
maximus merged 11 commits from issue-401-onboarding-guide-qa into main 2026-10-09 01:11:03 +00:00
Owner

Resolves #401

Generated autonomously by /autopilot run of 2026-10-08

PR empilée sur #406 (elle-même sur #405, #404, #403 puis #402) : elle ne montre que son propre diff.

Ce qui change pour l'utilisateur

  • Le guide d'utilisation (Paramètres → Utilisateurs) gagne, dans « Premiers pas », la sous-section « Le parcours de démarrage ». C'est la section qu'ouvre « Ouvrir le guide » à la fin du parcours. Elle décrit, en français et en anglais :
    • le bandeau et sa liste (« Voir la liste », « Fermer la liste ») ;
    • les cartes d'étape des pages Import, Transactions et Budget, leur contour (trois pulsations, aucune sous mouvement réduit) et le focus à l'arrivée par « Étape suivante » ;
    • « Fait. » puis l'étape suivante, et l'import qui n'ajoute rien ;
    • « Passer cette étape » et « Reprendre » ;
    • le message de fin, « Masquer » et le réaffichage depuis Paramètres → Utilisateurs ;
    • les profils déjà actifs, masqués d'office (règle D9), et la fin à 5/5 en édition Gratuite.
  • Les sections Tableau de bord et Paramètres du guide ne parlent plus de la barre compacte retirée par #397. La section Profils dit que le parcours est propre à chaque profil.
  • docs/guide-utilisateur.md porte le même texte. Rien d'autre ne change dans l'application : seul le contenu du guide intégré est nouveau.

Technique

  • src/i18n/locales/fr.json et en.json :

    • docs.gettingStarted.subsections : une entrée, id getting-started-path, neuf points et une note ;
    • une fonction de plus dans docs.gettingStarted.features, une astuce dans docs.profiles.tips ;
    • une fonction et deux étapes réécrites dans docs.dashboard, une fonction et une étape dans docs.settings.

    C'est la forme de docs.import.subsections, que DocsSubsections lit déjà : aucun code d'affichage ne change.

  • src/components/settings/DocsContent.locales.test.ts (nouveau, 6 tests) lit les vrais fichiers de langue, ce que ne faisait aucun test : DocsSubsections.test.tsx tourne sur une fixture et DocsContent n'a pas de test. DocsContent.tsx exporte SECTIONS pour lui.

  • docs/architecture.md : la section « Onboarding — états vides et parcours de démarrage » est réécrite, avec une sous-section « Parcours guidé » :

    • le fournisseur et useOnboarding() ;
    • le canal dataEvents et l'ADR 0022 ;
    • la table des préférences onboarding_checklist_hidden, onboarding_skipped_<clé> et onboarding_guided_initialized, et la règle D9 ;
    • les modèles purs d'onboardingPath.ts, le bandeau, le verrou de carte et CARD_PAGES, les cartes d'étape ;
    • la mise en évidence par props et CSS.

    Lignes rendues fausses par la pile et corrigées : le compte de utils/ (14 → 16) et la ligne user_preferences.

  • docs/qa-onboarding.html : cinq groupes, 41 cas, clé de stockage v2 (voir Décisions).

  • CHANGELOG.md et CHANGELOG.fr.md : entrées de #396 à #400 réorganisées (voir Décisions), et une entrée #401.

  • STATE.md : une puce dans « Blockers actifs ».

  • Aucun changement Rust, aucune migration.

Preuves

  • npm run build vert (tsc + vite).
  • npx vitest run : 1885 → 1891 tests verts (108 → 109 fichiers).
  • CI check-frontend, lue dans les logs : run 505 vert sur d6f42db, puis run 506 vert sur la tête 5c18fdd (build, 109 fichiers, 1891 tests).
  • Passe de mutations sur l'arbre commité, une mutation à la fois : git diff non vide vérifié, suite complète lancée, fichier restauré par git checkout, arbre propre après chacune. Faite sur d6f42db, puis refaite sur la tête 5c18fdd après l'auto-revue, avec les mêmes résultats.
# Mutation Rouges (suite complète)
M1 fr.json : steps retiré de la sous-section du parcours (une clé que lit DocsSubsections) 3/1891
M2 en.json : docs.dashboard.steps devient une chaîne 2/1891
M3 en.json : dernier point de docs.settings.steps retiré (FR et EN désynchronisés) 1/1891
M4 fr.json : la sous-section reprend l'ancre import-export 3/1891

4/4 rouges, toutes dans DocsContent.locales.test.ts : aucun autre test ne lit ces clés, et les quatre mutations seraient restées vertes sans lui.

  • Greps : plus aucune « barre compacte » ni « compact bar » dans le guide, dans les clés docs.* des deux langues et dans architecture.md. Le seul « compact » restant décrit le panneau du hub Rapports (docs.reports).
  • Les 65 libellés d'interface cités entre guillemets par le guide, la liste QA et le CHANGELOG existent dans la langue correspondante. La seule clé onboarding.* citée (onboarding.state.*, dans architecture.md) existe dans les deux.
  • Le script de la liste QA tourne dans node avec un faux DOM : 5 groupes, 41 cas, identifiants uniques, rapport de 54 lignes.

Décisions

Huit décisions, toutes dans le journal du run. Les principales :

  • [MEDIUM] Le parcours est décrit dans une sous-section de « Premiers pas », la section qu'ouvre « Ouvrir le guide », sous la forme que DocsSubsections lit déjà. Écartés : six astuces mêlées à la langue et au thème ; la section Tableau de bord, où le parcours ne vit plus ; une section de premier niveau, qui demanderait du code.
  • [MEDIUM] Un test qui lit les vraies clés docs.* : les tests du guide intégré tournent sur des fixtures, et la passe de mutations n'aurait rien prouvé. Écarté : livrer une passe verte en le signalant.
  • [MEDIUM] CHANGELOG : une entrée commune pour ce que fait toute carte (« Étape n sur N », contour, « Fait. », focus, « Passer » et « Reprendre »), puis une entrée par page. L'entrée de #396 couvre le bandeau et sa liste ; celles de #397 ajoutent l'état « passée » et « faites ou passées ». Les entrées de #390 sont intactes. Écartés : focus et « Passer » écrits pour la page Import seulement ; le commun répété dans chaque entrée.
  • [MEDIUM] Liste QA : trois cas de la phase 1 retirés car rendus faux par le bandeau (liste compacte à 4/6, 5/6 puis 6/6 sur le tableau de bord), « Masquer sur un second profil » mis à jour. Clé de stockage v2, pour ne pas mêler les réponses de l'ancienne liste. La page renvoie à git show v0.17.0:docs/qa-onboarding.html pour la vérification de la v0.17.0, encore due.
  • [MEDIUM] Un constat signalé et non corrigé, détaillé dans « Pour relire ».
  • [HIGH] architecture.md : seuls les comptes rendus faux par la pile sont corrigés ; les dérives antérieures (pages, sous-dossiers de composants) restent.

Pour relire

  • Constat hors périmètre : un import qui n'ajoute aucune transaction coche quand même « Importer un premier fichier ».
    • executeImport écrit la ligne imported_files en completed avant d'insérer, et ne la repasse en error que si l'insertion lève.
    • Un fichier sans ligne valide, ou de doublons seuls, laisse donc une ligne completed à 0 ligne, que compte COUNTERS_SQL.
    • La carte dit bien, sur le rapport, que l'import n'a rien ajouté ; mais après « Terminé », elle annonce « Fait. » (importCardModel, assistant au repos).
    • C'est le compteur de la phase 1. Le cas est consigné « à juger » dans la liste QA ; aucune issue ouverte.
  • L'auto-revue a ajouté 5c18fdd : le guide et l'entrée #398 disaient que la carte n'annonce jamais « Fait. » pour un import qui n'ajoute rien, alors qu'elle ne le retient que sur le rapport ; le test des clés ne dépend plus de l'ordre des sections dans les fichiers.
  • Ordre de lecture conseillé : DocsContent.locales.test.ts, puis la sous-section dans fr.json et en.json (texte identique au guide .md), puis la sous-section « Parcours guidé » d'architecture.md.
  • La liste QA est à faire sur un build de release, d'abord sous Linux avec Orca, puis sous Windows avec NVDA. Elle reprend les vérifications à la main laissées par les PR #402 à #406 :
    • règle D9 sur un profil réel, et une étape cochée page ouverte ;
    • bandeau sur chaque page mais pas sur le tableau de bord vide, « Voir la liste », « Masquer » depuis Paramètres → Utilisateurs, message de fin ;
    • contour et pulsation dans WebKitGTK et WebView2, focus sur le titre, annonces de NVDA et d'Orca, micro-flash d'ImportFolderConfig ;
    • entrée guidée et repli sur toutes les transactions, lien guidé suivi depuis /transactions ;
    • « Tout déplier » puis la cellule, Entrée et Tab, grille déjà dépliée, cellule hors de vue, 0 $, édition Gratuite à 5/5.
  • CI : ce diff touche fr.json, en.json et un test, donc check-frontend tourne.

🤖 Generated with Claude Code

Resolves #401 Generated autonomously by /autopilot run of 2026-10-08 > PR empilée sur #406 (elle-même sur #405, #404, #403 puis #402) : elle ne montre que son propre diff. ## Ce qui change pour l'utilisateur - Le guide d'utilisation (Paramètres → Utilisateurs) gagne, dans « Premiers pas », la sous-section « Le parcours de démarrage ». C'est la section qu'ouvre « Ouvrir le guide » à la fin du parcours. Elle décrit, en français et en anglais : - le bandeau et sa liste (« Voir la liste », « Fermer la liste ») ; - les cartes d'étape des pages Import, Transactions et Budget, leur contour (trois pulsations, aucune sous mouvement réduit) et le focus à l'arrivée par « Étape suivante » ; - « Fait. » puis l'étape suivante, et l'import qui n'ajoute rien ; - « Passer cette étape » et « Reprendre » ; - le message de fin, « Masquer » et le réaffichage depuis Paramètres → Utilisateurs ; - les profils déjà actifs, masqués d'office (règle D9), et la fin à 5/5 en édition Gratuite. - Les sections Tableau de bord et Paramètres du guide ne parlent plus de la barre compacte retirée par #397. La section Profils dit que le parcours est propre à chaque profil. - `docs/guide-utilisateur.md` porte le même texte. Rien d'autre ne change dans l'application : seul le contenu du guide intégré est nouveau. ## Technique - `src/i18n/locales/fr.json` et `en.json` : - `docs.gettingStarted.subsections` : une entrée, id `getting-started-path`, neuf points et une note ; - une fonction de plus dans `docs.gettingStarted.features`, une astuce dans `docs.profiles.tips` ; - une fonction et deux étapes réécrites dans `docs.dashboard`, une fonction et une étape dans `docs.settings`. C'est la forme de `docs.import.subsections`, que `DocsSubsections` lit déjà : aucun code d'affichage ne change. - `src/components/settings/DocsContent.locales.test.ts` (nouveau, 6 tests) lit les vrais fichiers de langue, ce que ne faisait aucun test : `DocsSubsections.test.tsx` tourne sur une fixture et `DocsContent` n'a pas de test. `DocsContent.tsx` exporte `SECTIONS` pour lui. - `docs/architecture.md` : la section « Onboarding — états vides et parcours de démarrage » est réécrite, avec une sous-section « Parcours guidé » : - le fournisseur et `useOnboarding()` ; - le canal `dataEvents` et l'ADR 0022 ; - la table des préférences `onboarding_checklist_hidden`, `onboarding_skipped_<clé>` et `onboarding_guided_initialized`, et la règle D9 ; - les modèles purs d'`onboardingPath.ts`, le bandeau, le verrou de carte et `CARD_PAGES`, les cartes d'étape ; - la mise en évidence par props et CSS. Lignes rendues fausses par la pile et corrigées : le compte de `utils/` (14 → 16) et la ligne `user_preferences`. - `docs/qa-onboarding.html` : cinq groupes, 41 cas, clé de stockage `v2` (voir Décisions). - `CHANGELOG.md` et `CHANGELOG.fr.md` : entrées de #396 à #400 réorganisées (voir Décisions), et une entrée #401. - `STATE.md` : une puce dans « Blockers actifs ». - Aucun changement Rust, aucune migration. ## Preuves - `npm run build` vert (tsc + vite). - `npx vitest run` : 1885 → **1891** tests verts (108 → 109 fichiers). - CI `check-frontend`, lue dans les logs : run 505 vert sur `d6f42db`, puis run 506 vert sur la tête `5c18fdd` (build, 109 fichiers, 1891 tests). - Passe de mutations sur l'arbre commité, une mutation à la fois : `git diff` non vide vérifié, suite complète lancée, fichier restauré par `git checkout`, arbre propre après chacune. Faite sur `d6f42db`, puis refaite sur la tête `5c18fdd` après l'auto-revue, avec les mêmes résultats. | # | Mutation | Rouges (suite complète) | |---|---|---| | M1 | `fr.json` : `steps` retiré de la sous-section du parcours (une clé que lit `DocsSubsections`) | 3/1891 | | M2 | `en.json` : `docs.dashboard.steps` devient une chaîne | 2/1891 | | M3 | `en.json` : dernier point de `docs.settings.steps` retiré (FR et EN désynchronisés) | 1/1891 | | M4 | `fr.json` : la sous-section reprend l'ancre `import-export` | 3/1891 | **4/4 rouges**, toutes dans `DocsContent.locales.test.ts` : aucun autre test ne lit ces clés, et les quatre mutations seraient restées vertes sans lui. - Greps : plus aucune « barre compacte » ni « compact bar » dans le guide, dans les clés `docs.*` des deux langues et dans `architecture.md`. Le seul « compact » restant décrit le panneau du hub Rapports (`docs.reports`). - Les 65 libellés d'interface cités entre guillemets par le guide, la liste QA et le CHANGELOG existent dans la langue correspondante. La seule clé `onboarding.*` citée (`onboarding.state.*`, dans `architecture.md`) existe dans les deux. - Le script de la liste QA tourne dans node avec un faux DOM : 5 groupes, 41 cas, identifiants uniques, rapport de 54 lignes. ## Décisions Huit décisions, toutes dans le journal du run. Les principales : - **[MEDIUM]** Le parcours est décrit dans une sous-section de « Premiers pas », la section qu'ouvre « Ouvrir le guide », sous la forme que `DocsSubsections` lit déjà. Écartés : six astuces mêlées à la langue et au thème ; la section Tableau de bord, où le parcours ne vit plus ; une section de premier niveau, qui demanderait du code. - **[MEDIUM]** Un test qui lit les vraies clés `docs.*` : les tests du guide intégré tournent sur des fixtures, et la passe de mutations n'aurait rien prouvé. Écarté : livrer une passe verte en le signalant. - **[MEDIUM]** CHANGELOG : une entrée commune pour ce que fait toute carte (« Étape n sur N », contour, « Fait. », focus, « Passer » et « Reprendre »), puis une entrée par page. L'entrée de #396 couvre le bandeau et sa liste ; celles de #397 ajoutent l'état « passée » et « faites ou passées ». Les entrées de #390 sont intactes. Écartés : focus et « Passer » écrits pour la page Import seulement ; le commun répété dans chaque entrée. - **[MEDIUM]** Liste QA : trois cas de la phase 1 retirés car rendus faux par le bandeau (liste compacte à 4/6, 5/6 puis 6/6 sur le tableau de bord), « Masquer sur un second profil » mis à jour. Clé de stockage `v2`, pour ne pas mêler les réponses de l'ancienne liste. La page renvoie à `git show v0.17.0:docs/qa-onboarding.html` pour la vérification de la v0.17.0, encore due. - **[MEDIUM]** Un constat signalé et non corrigé, détaillé dans « Pour relire ». - **[HIGH]** `architecture.md` : seuls les comptes rendus faux par la pile sont corrigés ; les dérives antérieures (pages, sous-dossiers de composants) restent. ## Pour relire - **Constat hors périmètre : un import qui n'ajoute aucune transaction coche quand même « Importer un premier fichier ».** - `executeImport` écrit la ligne `imported_files` en `completed` avant d'insérer, et ne la repasse en `error` que si l'insertion lève. - Un fichier sans ligne valide, ou de doublons seuls, laisse donc une ligne `completed` à 0 ligne, que compte `COUNTERS_SQL`. - La carte dit bien, sur le rapport, que l'import n'a rien ajouté ; mais après « Terminé », elle annonce « Fait. » (`importCardModel`, assistant au repos). - C'est le compteur de la phase 1. Le cas est consigné « à juger » dans la liste QA ; aucune issue ouverte. - L'auto-revue a ajouté `5c18fdd` : le guide et l'entrée #398 disaient que la carte n'annonce jamais « Fait. » pour un import qui n'ajoute rien, alors qu'elle ne le retient que sur le rapport ; le test des clés ne dépend plus de l'ordre des sections dans les fichiers. - Ordre de lecture conseillé : `DocsContent.locales.test.ts`, puis la sous-section dans `fr.json` et `en.json` (texte identique au guide `.md`), puis la sous-section « Parcours guidé » d'`architecture.md`. - La liste QA est à faire sur un build de release, d'abord sous Linux avec Orca, puis sous Windows avec NVDA. Elle reprend les vérifications à la main laissées par les PR #402 à #406 : - règle D9 sur un profil réel, et une étape cochée page ouverte ; - bandeau sur chaque page mais pas sur le tableau de bord vide, « Voir la liste », « Masquer » depuis Paramètres → Utilisateurs, message de fin ; - contour et pulsation dans WebKitGTK et WebView2, focus sur le titre, annonces de NVDA et d'Orca, micro-flash d'`ImportFolderConfig` ; - entrée guidée et repli sur toutes les transactions, lien guidé suivi depuis /transactions ; - « Tout déplier » puis la cellule, Entrée et Tab, grille déjà dépliée, cellule hors de vue, 0 $, édition Gratuite à 5/5. - CI : ce diff touche `fr.json`, `en.json` et un test, donc `check-frontend` tourne. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
maximus added 3 commits 2026-10-08 13:56:53 +00:00
The "Getting Started" section, which "Open the guide" opens at the end of
the path, gains a "The getting-started path" sub-section in both locales
and in docs/guide-utilisateur.md: the banner and its list, the step cards
and their outline, "Skip this step" and "Resume", the end of the path,
the profiles that find it hidden from the start, and how to show it again
from Settings -> Users. It uses the sub-section shape DocsSubsections
already reads for the Import section.

The Dashboard and Settings sections no longer describe the compact bar
the banner replaced, and the Profiles section says the path belongs to
each profile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DocsContent and DocsSubsections read the guide straight from fr.json and
en.json, but their tests run on fixtures: a string where an array is
expected, a sub-section without its steps or a French list longer than
its English one only showed in the app. DocsContent.locales.test.ts reads
the real files: every section DocsContent renders and no other, the
strings and string arrays it reads, sub-sections that readSubsections
keeps whole, anchors of their own, French and English item for item, and
the path's sub-section in the section "Open the guide" opens.

DocsContent exports SECTIONS for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs: architecture, QA checklist and changelog for the guided path
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m59s
d6f42dbe32
- architecture.md: the Onboarding section describes the guided path as
  delivered (provider and useOnboarding(), the data-change channel of
  ADR 0022, the three onboarding preferences, rule D9, the pure models of
  onboardingPath.ts, the banner, the card latch and CARD_PAGES, the step
  cards, the highlight by props and CSS); the utils count and the
  user_preferences row follow the stack.
- qa-onboarding.html: the phase 1 cases that still hold, without the
  compact bar ones, and four guided-path groups, including the manual
  checks the five links left for a release build (WebKitGTK and WebView2,
  Orca and NVDA, reduced motion, keyboard, Free edition, rule D9).
- CHANGELOG (EN and FR): one entry for what every step card does, one per
  page, the path hidden on active profiles covers the banner too, the
  skipped state, and the guide's new sub-section.
- STATE.md: manual checks due on the next release.

Resolves #401

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maximus added the
autopilot:pending-human
label 2026-10-08 13:56:57 +00:00
maximus added 1 commit 2026-10-08 13:59:57 +00:00
docs: say where the Import card holds back "Done." (self-review)
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 2m6s
5c18fddfc0
The guide and the changelog said the card never says "Done." for an
import that added no transaction. It holds it back on the report only:
on the Import page the card moves from one step to the next, and says
"Done." once the file is imported. The locale test no longer depends on
the order of the sections in the files, which DocsContent ignores.

Resolves #401

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

Auto-revue (worker autopilot) — verdict : APPROVE, après une correction

Revue du diff de cette PR seule (d76c387..5c18fdd, 10 fichiers) contre les critères de #401, la parité FR/EN et le code livré par #402 à #406. Cette auto-revue ne remplace pas une revue indépendante : l'issue reste en status:review, et status:approved revient à /pr-review.

Critères d'acceptation

  • Le guide (fichier et clés docs.*) décrit le parcours livré, en FR et en EN, sans barre compacte : sous-section getting-started-path (neuf points et une note), sections Tableau de bord, Profils et Paramètres mises à jour. Le seul « compact » restant dans les clés est le panneau du hub Rapports (docs.reports).
  • architecture.md décrit le fournisseur, le canal, les préférences, le verrou de carte et la mise en évidence, et renvoie à l'ADR 0022.
  • qa-onboarding.html porte les dix cas de l'issue, plus les vérifications à la main laissées par #402 à #406 (D9 sur un profil réel, coche en direct, bandeau et liste, « Masquer » depuis Paramètres → Utilisateurs, contour dans WebKitGTK et WebView2, focus, annonces d'Orca et de NVDA, micro-flash d'ImportFolderConfig, entrée guidée et repli, lien guidé suivi depuis /transactions, « Tout déplier » puis la cellule, Tab, grille déjà dépliée, cellule hors de vue, 0 $, édition Gratuite à 5/5).
  • CHANGELOG cohérent dans les deux langues : 6 entrées Ajouté, 3 Modifié et 4 Corrigé de chaque côté, entrées de #390 intactes. npm run build et npx vitest run verts (1891 tests).

Six affirmations du guide vérifiées dans le code

  1. « Le contour pulse trois fois, et pas du tout si votre système demande de réduire les animations » : styles.css, animation-iteration-count: 3, et animation: none sous prefers-reduced-motion: reduce.
  2. « La liste se replie aussi quand vous changez de page » : AppShell.tsx monte <OnboardingBannerSlot key={pathname} />, dont l'état listOpen est local.
  3. « Il n'apparaît pas sur le tableau de bord d'un profil sans transaction » : bannerMode rend none quand pathname === "/" et counters.transactions === 0.
  4. Une étape passée « compte dans la progression » : computeChecklist compte item.done || item.skipped parmi les lignes déverrouillées.
  5. Un profil déjà actif le voit « masqué d'office à sa première ouverture », un profil vide ou neuf le garde : initializeGuidedPath, drapeau absent et COUNT(*) FROM transactions > 0, puis préférence masquée et drapeau dans la même transaction.
  6. « Reprendre remet l'étape à faire et ouvre sa page » : OnboardingChecklist, Link vers item.to avec stepNavState et onClick={() => onResume(item.key)}.

Constats

  1. Corrigé dans 5c18fdd. Le guide et l'entrée #398 disaient que la carte n'annonce pas « Fait. » pour un import qui n'ajoute rien. Elle ne le retient que sur le rapport (importCardModel) : sur la page Import, la carte passe d'une étape à la suivante, et après « Terminé » l'assistant au repos, source et import cochés, donne « Fait. ». Texte précisé en FR et en EN.
  2. Corrigé dans 5c18fdd. Le premier test de DocsContent.locales.test.ts exigeait l'ordre des sections dans les fichiers de langue, que DocsContent ignore : comparaison triée.
  3. Signalé, hors périmètre. Un import sans transaction coche quand même « Importer un premier fichier » : executeImport écrit la ligne imported_files en completed avant l'insertion, et COUNTERS_SQL la compte. Consigné « à juger » dans la liste QA, aucune issue ouverte.
  4. Parité FR/EN : les clés docs.* sont désormais gardées par le nouveau test (mutation M3 rouge). Les 65 libellés d'interface cités entre guillemets existent dans la langue correspondante.
  5. Aucun secret ni donnée personnelle dans les lignes ajoutées (scan des courriels, jetons, clés de licence et chemins personnels).

Preuves sur la tête 5c18fdd

  • Mutations, une à la fois, restaurées par git checkout : 4/4 rouges (3, 2, 1 et 3 tests sur 1891), toutes dans DocsContent.locales.test.ts.
  • CI check-frontend, lue dans les logs : run 505 vert sur d6f42db, puis run 506 vert sur 5c18fdd (build, 109 fichiers, 1891 tests).
## Auto-revue (worker autopilot) — verdict : APPROVE, après une correction Revue du diff de cette PR seule (`d76c387..5c18fdd`, 10 fichiers) contre les critères de #401, la parité FR/EN et le code livré par #402 à #406. Cette auto-revue ne remplace pas une revue indépendante : l'issue reste en `status:review`, et `status:approved` revient à `/pr-review`. ### Critères d'acceptation - [x] Le guide (fichier et clés `docs.*`) décrit le parcours livré, en FR et en EN, sans barre compacte : sous-section `getting-started-path` (neuf points et une note), sections Tableau de bord, Profils et Paramètres mises à jour. Le seul « compact » restant dans les clés est le panneau du hub Rapports (`docs.reports`). - [x] `architecture.md` décrit le fournisseur, le canal, les préférences, le verrou de carte et la mise en évidence, et renvoie à l'ADR 0022. - [x] `qa-onboarding.html` porte les dix cas de l'issue, plus les vérifications à la main laissées par #402 à #406 (D9 sur un profil réel, coche en direct, bandeau et liste, « Masquer » depuis Paramètres → Utilisateurs, contour dans WebKitGTK et WebView2, focus, annonces d'Orca et de NVDA, micro-flash d'`ImportFolderConfig`, entrée guidée et repli, lien guidé suivi depuis /transactions, « Tout déplier » puis la cellule, Tab, grille déjà dépliée, cellule hors de vue, 0 $, édition Gratuite à 5/5). - [x] CHANGELOG cohérent dans les deux langues : 6 entrées Ajouté, 3 Modifié et 4 Corrigé de chaque côté, entrées de #390 intactes. `npm run build` et `npx vitest run` verts (1891 tests). ### Six affirmations du guide vérifiées dans le code 1. « Le contour pulse trois fois, et pas du tout si votre système demande de réduire les animations » : `styles.css`, `animation-iteration-count: 3`, et `animation: none` sous `prefers-reduced-motion: reduce`. 2. « La liste se replie aussi quand vous changez de page » : `AppShell.tsx` monte `<OnboardingBannerSlot key={pathname} />`, dont l'état `listOpen` est local. 3. « Il n'apparaît pas sur le tableau de bord d'un profil sans transaction » : `bannerMode` rend `none` quand `pathname === "/"` et `counters.transactions === 0`. 4. Une étape passée « compte dans la progression » : `computeChecklist` compte `item.done || item.skipped` parmi les lignes déverrouillées. 5. Un profil déjà actif le voit « masqué d'office à sa première ouverture », un profil vide ou neuf le garde : `initializeGuidedPath`, drapeau absent et `COUNT(*) FROM transactions` > 0, puis préférence masquée et drapeau dans la même transaction. 6. « Reprendre remet l'étape à faire et ouvre sa page » : `OnboardingChecklist`, `Link` vers `item.to` avec `stepNavState` et `onClick={() => onResume(item.key)}`. ### Constats 1. **Corrigé dans `5c18fdd`.** Le guide et l'entrée #398 disaient que la carte n'annonce pas « Fait. » pour un import qui n'ajoute rien. Elle ne le retient que sur le rapport (`importCardModel`) : sur la page Import, la carte passe d'une étape à la suivante, et après « Terminé » l'assistant au repos, source et import cochés, donne « Fait. ». Texte précisé en FR et en EN. 2. **Corrigé dans `5c18fdd`.** Le premier test de `DocsContent.locales.test.ts` exigeait l'ordre des sections dans les fichiers de langue, que `DocsContent` ignore : comparaison triée. 3. **Signalé, hors périmètre.** Un import sans transaction coche quand même « Importer un premier fichier » : `executeImport` écrit la ligne `imported_files` en `completed` avant l'insertion, et `COUNTERS_SQL` la compte. Consigné « à juger » dans la liste QA, aucune issue ouverte. 4. Parité FR/EN : les clés `docs.*` sont désormais gardées par le nouveau test (mutation M3 rouge). Les 65 libellés d'interface cités entre guillemets existent dans la langue correspondante. 5. Aucun secret ni donnée personnelle dans les lignes ajoutées (scan des courriels, jetons, clés de licence et chemins personnels). ### Preuves sur la tête `5c18fdd` - Mutations, une à la fois, restaurées par `git checkout` : **4/4 rouges** (3, 2, 1 et 3 tests sur 1891), toutes dans `DocsContent.locales.test.ts`. - CI `check-frontend`, lue dans les logs : run 505 vert sur `d6f42db`, puis run 506 vert sur `5c18fdd` (build, 109 fichiers, 1891 tests).
Author
Owner

Revue adversariale — verdict : APPROVE

Résumé : le guide (FR, EN et .md), architecture.md, la liste QA et le CHANGELOG décrivent fidèlement le code de la pile au tip 5c18fdd. Chaque affirmation vérifiable a été confrontée au code, et le nouveau test rougit sous les neuf mutations structurelles du relecteur. Aucun bloquant sur ce maillon. La condition de merge posée par la revue de #404 le touche : il porte cinq des textes qu'elle ferait réécrire (voir plus bas).

Exécuté

  • Copie hors dépôt (git archive 5c18fdd, npm ci) : npx vitest run 109 fichiers, 1891 tests verts ; npm run build vert (tsc + vite).
  • CI check-frontend, run 506, lue dans le journal du job : checkout de 5c18fdd, build, 109 fichiers et 1891 tests, « Job succeeded ».
  • Script de la liste QA rejoué dans node avec un faux DOM : 5 groupes, 41 cas, identifiants uniques, rapport de 54 lignes, état rangé sous simpl-resultat.qa-onboarding.v2.
  • Libellés : 72 citations « … » (FR) et 18 "…" (EN) extraites des lignes ajoutées, cherchées dans les valeurs des fichiers de langue hors docs.*. Toutes se retrouvent dans l'interface, sauf des noms de sections (guide, architecture, liste QA), le bouton de la page QA, des noms du dossier d'exemple, une citation abrégée par « … » et la ligne de Journal de D9, présente mot pour mot à onboardingService.ts:161.
  • « Paramètres → Système → Envoyer un feedback », qui remplace « Systèmes → Rétroaction » dans la liste QA : conforme à settings.systems.title et à feedback.button.

Mutations du relecteur

Distinctes des M1 à M4 de l'auteur, appliquées une à la fois. Après chacune, les fichiers sont restaurés et comparés à l'octet avec 5c18fdd.

# Mutation Rouges
R1 en.json : sous-section du parcours retirée en entier, FR la garde 2 ; sur la suite complète, ce fichier est le seul à les voir
R2 fr.json : note de la sous-section vide 1
R3 GETTING_STARTED_GUIDE pointé sur #profiles 1, plus 1 dans OnboardingBanner.render.test.tsx
R5 SECTIONS sans editions 1
R6 status ajouté à la seule sous-section FR 1
R7 un point de la sous-section devient un nombre, que readSubsections garde 1
R8 docs.tipsHeader retiré de en.json 1
R9 deux sous-sections d'Import avec le même id en EN 2
R11 docs.dashboard.tips vide en EN 2
R10 point 7 de la sous-section FR réécrit faux 0, attendu

R10 borne ce que prouve le test : il garde la forme, pas le sens. La justesse du texte repose sur la relecture, d'où la confrontation au code qui suit.

Vérifié contre le code du tip

  • Bandeau : bannerMode (none sur le tableau de bord vide, card sur la page du verrou, complete quand tout est fait ou passé et budgetReady) ; key={pathname} sur le slot dans AppShell, d'où la liste repliée à chaque page ; « Masquer » dans le bandeau et dans la liste dépliée.
  • Carte : cardStep, cardNext et StepCard (zone role="status", « Passer » tant que l'étape n'est pas faite, fin avec « Ouvrir le guide » et « Fermer ») ; focus gardé sur location.key ; « Reprendre » est un lien vers la page de l'étape qui appelle resume.
  • Import : importCardModel dit « Fait. » sur le rapport seulement si importedCount > 0, puis au repos dès que source et import sont cochés. C'est ce que disent le point 5 du guide et l'entrée #398 depuis 5c18fdd.
  • Transactions et Budget : GUIDED_ENTRY_FILTERS (dateFrom: null, non catégorisées) et « Tout » actif dans TransactionFilterBar ; budgetOnboardingTarget (première feuille visible, sinon « Tout déplier »).
  • D9, préférences, canal, contour : initializeGuidedPath, getOnboardingSnapshot, followDataChanges à 150 ms ; contour de 3 px décalé de 2 px, pulsation de 1,2 s jouée trois fois, retirée sous prefers-reduced-motion.
  • Comptes d'architecture.md : 16 modules dans utils/ au tip (15 .ts et chartPatterns.tsx), 26 services, 29 hooks.
  • Fermeture : la timeline de #401 porte un pull_ref de #407 en closes, et Resolves #401 figure dans d6f42db et 5c18fdd, donc un merge ff local la ferme aussi. Aucune autre issue n'est fermée.

Condition de pile, posée par la revue de #404 : à trancher avant /merge-stack

La revue de #404 recommande la voie A : ne compter une ligne imported_files que si elle a des transactions, dans un commit en tête de pile. #407 est cette tête, et son texte décrit le comportement actuel. Si la voie A est retenue, le même commit doit réécrire dans ce maillon :

  1. docs/guide-utilisateur.md:38, et le point 5 de la sous-section (fr.json:903, en.json:903) : « sur le rapport d'un import qui n'a ajouté aucune transaction, elle ne l'annonce pas » devient « jamais pour un import qui n'a ajouté aucune transaction » ;
  2. CHANGELOG.md:9 et CHANGELOG.fr.md:9, avec une entrée Fixed / Corrigé, puisque la v0.17.0 coche déjà l'étape après un import sans ligne valide ;
  3. docs/qa-onboarding.html:256-257 (guided-noop-import) : retirer « À juger », et attendre au repos « Étape 4 sur 6 » avec la première source entourée ;
  4. docs/architecture.md:329 (ligne « Importer un premier fichier ») et :361 (importCardModel).

Avec la voie B, le texte de ce maillon est exact. Reste alors à décider si le guide nomme la case cochée après « Terminé » ; la liste QA la porte déjà.

Suggestions (non bloquantes)

  1. Édition Gratuite dans le CHANGELOG (CHANGELOG.md:10, CHANGELOG.fr.md:10) : « which has no Budget step » / « qui n'a pas d'étape Budget ». En Gratuite, la liste montre une ligne Budget verrouillée « Base et plus ». La note du guide est exacte (« l'étape Budget est verrouillée et ne compte pas ») : reprendre « where the Budget step is locked » / « où l'étape Budget est verrouillée ». Ces notes s'affichent dans l'app.
  2. Trois cas renvoyés à la QA de #401 par les revues de la pile, que la liste ne nomme pas :
    • aucun anneau de focus sur le contrôle entouré (revue de #404, suggestion 1 : l'outline de styles.css:158 l'emporte sur l'anneau du navigateur). guided-keyboard (qa-onboarding.html:285-286) demande un focus visible en général : nommer le contrôle entouré, ou ajuster le cas si le correctif part en tête de pile ;
    • la carte Budget figée sur « Cliquez Tout déplier… » au-dessus de l'état vide, sur un profil sans transaction dont les étapes 3 à 5 sont passées (revue de #406, suggestion 1 : visible seulement dans un build de production) ;
    • « Passer » sur l'étape du dossier, sans dossier : la carte titre « Étape 3 sur 6 · Configurer une source d'import » avec la phrase et l'anneau du dossier (revue de #404, suggestion 2). Vérifié dans cardStep et importCardModel.
  3. Détails : qa-onboarding.html:265, « octobre est vers la droite » ne tiendra plus au moment de la QA (« les derniers mois de l'année sont à droite ») ; architecture.md:351, la ligne au Journal de D9 s'écrit après le COMMIT, et seulement quand le masquage est validé, pas entre les deux écritures.

Actions faites

  • Label de #401 : status:review → status:approved.
  • Copie hors dépôt /tmp/pr407-copy et fichiers /tmp/pr407-* supprimés ; arbre du dépôt intact.
## Revue adversariale — verdict : APPROVE **Résumé** : le guide (FR, EN et `.md`), `architecture.md`, la liste QA et le CHANGELOG décrivent fidèlement le code de la pile au tip `5c18fdd`. Chaque affirmation vérifiable a été confrontée au code, et le nouveau test rougit sous les neuf mutations structurelles du relecteur. Aucun bloquant sur ce maillon. La condition de merge posée par la revue de #404 le touche : il porte cinq des textes qu'elle ferait réécrire (voir plus bas). ### Exécuté - Copie hors dépôt (`git archive 5c18fdd`, `npm ci`) : `npx vitest run` 109 fichiers, 1891 tests verts ; `npm run build` vert (tsc + vite). - CI `check-frontend`, run 506, lue dans le journal du job : checkout de `5c18fdd`, build, 109 fichiers et 1891 tests, « Job succeeded ». - Script de la liste QA rejoué dans node avec un faux DOM : 5 groupes, 41 cas, identifiants uniques, rapport de 54 lignes, état rangé sous `simpl-resultat.qa-onboarding.v2`. - Libellés : 72 citations « … » (FR) et 18 "…" (EN) extraites des lignes ajoutées, cherchées dans les valeurs des fichiers de langue hors `docs.*`. Toutes se retrouvent dans l'interface, sauf des noms de sections (guide, architecture, liste QA), le bouton de la page QA, des noms du dossier d'exemple, une citation abrégée par « … » et la ligne de Journal de D9, présente mot pour mot à `onboardingService.ts:161`. - « Paramètres → Système → Envoyer un feedback », qui remplace « Systèmes → Rétroaction » dans la liste QA : conforme à `settings.systems.title` et à `feedback.button`. ### Mutations du relecteur Distinctes des M1 à M4 de l'auteur, appliquées une à la fois. Après chacune, les fichiers sont restaurés et comparés à l'octet avec `5c18fdd`. | # | Mutation | Rouges | |---|---|---| | R1 | `en.json` : sous-section du parcours retirée en entier, FR la garde | 2 ; sur la suite complète, ce fichier est le seul à les voir | | R2 | `fr.json` : `note` de la sous-section vide | 1 | | R3 | `GETTING_STARTED_GUIDE` pointé sur `#profiles` | 1, plus 1 dans `OnboardingBanner.render.test.tsx` | | R5 | `SECTIONS` sans `editions` | 1 | | R6 | `status` ajouté à la seule sous-section FR | 1 | | R7 | un point de la sous-section devient un nombre, que `readSubsections` garde | 1 | | R8 | `docs.tipsHeader` retiré de `en.json` | 1 | | R9 | deux sous-sections d'Import avec le même `id` en EN | 2 | | R11 | `docs.dashboard.tips` vide en EN | 2 | | R10 | point 7 de la sous-section FR réécrit faux | **0**, attendu | R10 borne ce que prouve le test : il garde la forme, pas le sens. La justesse du texte repose sur la relecture, d'où la confrontation au code qui suit. ### Vérifié contre le code du tip - **Bandeau** : `bannerMode` (`none` sur le tableau de bord vide, `card` sur la page du verrou, `complete` quand tout est fait ou passé et `budgetReady`) ; `key={pathname}` sur le slot dans `AppShell`, d'où la liste repliée à chaque page ; « Masquer » dans le bandeau et dans la liste dépliée. - **Carte** : `cardStep`, `cardNext` et `StepCard` (zone `role="status"`, « Passer » tant que l'étape n'est pas faite, fin avec « Ouvrir le guide » et « Fermer ») ; focus gardé sur `location.key` ; « Reprendre » est un lien vers la page de l'étape qui appelle `resume`. - **Import** : `importCardModel` dit « Fait. » sur le rapport seulement si `importedCount > 0`, puis au repos dès que source et import sont cochés. C'est ce que disent le point 5 du guide et l'entrée #398 depuis `5c18fdd`. - **Transactions et Budget** : `GUIDED_ENTRY_FILTERS` (`dateFrom: null`, non catégorisées) et « Tout » actif dans `TransactionFilterBar` ; `budgetOnboardingTarget` (première feuille visible, sinon « Tout déplier »). - **D9, préférences, canal, contour** : `initializeGuidedPath`, `getOnboardingSnapshot`, `followDataChanges` à 150 ms ; contour de 3 px décalé de 2 px, pulsation de 1,2 s jouée trois fois, retirée sous `prefers-reduced-motion`. - **Comptes d'`architecture.md`** : 16 modules dans `utils/` au tip (15 `.ts` et `chartPatterns.tsx`), 26 services, 29 hooks. - **Fermeture** : la timeline de #401 porte un `pull_ref` de #407 en `closes`, et `Resolves #401` figure dans `d6f42db` et `5c18fdd`, donc un merge ff local la ferme aussi. Aucune autre issue n'est fermée. ### Condition de pile, posée par la revue de #404 : à trancher avant `/merge-stack` La revue de #404 recommande la voie A : ne compter une ligne `imported_files` que si elle a des transactions, dans un commit en tête de pile. #407 est cette tête, et son texte décrit le comportement actuel. Si la voie A est retenue, le même commit doit réécrire dans ce maillon : 1. `docs/guide-utilisateur.md:38`, et le point 5 de la sous-section (`fr.json:903`, `en.json:903`) : « sur le rapport d'un import qui n'a ajouté aucune transaction, elle ne l'annonce pas » devient « jamais pour un import qui n'a ajouté aucune transaction » ; 2. `CHANGELOG.md:9` et `CHANGELOG.fr.md:9`, avec une entrée Fixed / Corrigé, puisque la v0.17.0 coche déjà l'étape après un import sans ligne valide ; 3. `docs/qa-onboarding.html:256-257` (`guided-noop-import`) : retirer « À juger », et attendre au repos « Étape 4 sur 6 » avec la première source entourée ; 4. `docs/architecture.md:329` (ligne « Importer un premier fichier ») et `:361` (`importCardModel`). Avec la voie B, le texte de ce maillon est exact. Reste alors à décider si le guide nomme la case cochée après « Terminé » ; la liste QA la porte déjà. ### Suggestions (non bloquantes) 1. **Édition Gratuite dans le CHANGELOG** (`CHANGELOG.md:10`, `CHANGELOG.fr.md:10`) : « which has no Budget step » / « qui n'a pas d'étape Budget ». En Gratuite, la liste montre une ligne Budget verrouillée « Base et plus ». La note du guide est exacte (« l'étape Budget est verrouillée et ne compte pas ») : reprendre « where the Budget step is locked » / « où l'étape Budget est verrouillée ». Ces notes s'affichent dans l'app. 2. **Trois cas renvoyés à la QA de #401 par les revues de la pile, que la liste ne nomme pas** : - aucun anneau de focus sur le contrôle entouré (revue de #404, suggestion 1 : l'`outline` de `styles.css:158` l'emporte sur l'anneau du navigateur). `guided-keyboard` (`qa-onboarding.html:285-286`) demande un focus visible en général : nommer le contrôle entouré, ou ajuster le cas si le correctif part en tête de pile ; - la carte Budget figée sur « Cliquez Tout déplier… » au-dessus de l'état vide, sur un profil sans transaction dont les étapes 3 à 5 sont passées (revue de #406, suggestion 1 : visible seulement dans un build de production) ; - « Passer » sur l'étape du dossier, sans dossier : la carte titre « Étape 3 sur 6 · Configurer une source d'import » avec la phrase et l'anneau du dossier (revue de #404, suggestion 2). Vérifié dans `cardStep` et `importCardModel`. 3. **Détails** : `qa-onboarding.html:265`, « octobre est vers la droite » ne tiendra plus au moment de la QA (« les derniers mois de l'année sont à droite ») ; `architecture.md:351`, la ligne au Journal de D9 s'écrit après le `COMMIT`, et seulement quand le masquage est validé, pas entre les deux écritures. ### Actions faites - Label de #401 : `status:review` → `status:approved`. - Copie hors dépôt `/tmp/pr407-copy` et fichiers `/tmp/pr407-*` supprimés ; arbre du dépôt intact.
maximus added 7 commits 2026-10-09 01:06:51 +00:00
The "Import a first file" step counted `imported_files` rows in status
`completed`. `executeImport` writes that row before its first insert, so
an import that added nothing (a file holding only its header, or one
whose rows were all in error in the preview) ticked the step: the Import
card then said "Done." at rest and sent the user to /transactions, which
had nothing to categorize and led back to the import.

The counter now keeps a completed file only when a transaction points at
it (`EXISTS` on `transactions.file_id`, covered by
`idx_transactions_file`). Replayed with sqlite3 on
`consolidated_schema.sql`: 0 after an import without a valid row, 0
before a successful import's first insert and 1 after, 0 once the file
turns to `error`. Duplicates only change nothing: their transactions
came with an earlier completed file, and a restore writes its own.

The tests run without SQLite, so the rule is pinned on the query, and
the Import page is pinned at rest after such an import: step 4 again,
on the first source card, without "Done.".

Review of #398 (PR #404), option A chosen by Max.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`initializeGuidedPath` opened BEGIN, read the flag, then COMMIT at every
mount of the provider: start-up, and every profile switch, creation or
deletion. While a `withTransaction` callback runs, `db.ts` lets every
other query bypass its lock, the overlap its serialization exists to
prevent.

The flag is now read first, outside any transaction, through the queued
connection: once D9 ran, an opening costs that one read. Without it, the
transaction re-reads the flag before writing, so two first loads still
cannot apply the rule twice (CWE-362).

Pinned: no transaction and no write with the flag set; the flag counts
only for "1", on both reads; a first load that sets the flag between
the two reads wins; the in-transaction reads still follow BEGIN.

Review of #396 (PR #402).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ADR 0022 wants a transactional write to notify once `withTransaction`
has returned, never from its callback. Only the categorization test
checked the lock; the restore tests checked that the notification
followed the COMMIT, which a notification sent from inside the callback
also satisfies. Each restore mode now asserts the lock was released.

Review of #396 (PR #402).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ring of `[data-onboarding-highlight="true"]` is an author outline:
it wins over the browser's focus ring, so a keyboard user who reached
the highlighted control saw nothing change (WCAG 2.4.7, failure F78).
Measured by the review in headless Chromium, WebView2's engine: the
highlighted button kept `solid 3px` focused or not. `outline: revert`
under `:focus-visible` gives the browser's ring back, kept as is in the
built stylesheet; the contrast test reads the rule from the stylesheet.

Review of #398 (PR #404).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reducer tests sent SET_PAGE_RESULT right after the initial state,
while the hook sends SET_LOADING then SET_ERROR(null) before each read,
and the mount effect's categories, sources and count before or after
the first page. Had any of those three actions disarmed the guided
fallback, the fallback would never run in the app, and the tests stayed
green: a test now reduces both real orders.

The page tests now also let the list's filters move, as a later
dispatch would: after the fallback the card names every transaction,
and an ordinary visit with "Uncategorized" picked by hand names the
uncategorized ones. The sentence follows the list, not the navigation
state.

Review of #399 (PR #405).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a profile without transactions whose import steps were skipped, the
rows can land before the transaction count, both reads queueing behind
the DB lock: the grid mounted, reported "Expand all", then gave way to
the empty state, and the card kept "Click Expand all…" above it with no
grid on the page. The page now passes no target while it shows the
empty state, and a wiring test replays that sequence. Invisible in dev,
where StrictMode reorders the two reads.

The month test sets the clock to 23:00 on December 31, which is still
December in UTC: under the CI runner's zone, a month read in UTC passed.
The zone is pinned west of Greenwich, as in useImportWizard.test.ts.

Review of #400 (PR #406).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs(onboarding): the import counter, D9 and the QA cases from the stack's review
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 2m1s
ee17f31352
- Guide (FR, EN, in-app keys and `.md`) and CHANGELOG: the Import card
  never says "Done." for an import that added no transaction, and the
  step waits for a file that brought one; a Fixed entry, since v0.17.0
  already ticked the step after such an import.
- CHANGELOG: the Free edition shows the Budget step locked, it does not
  lack one.
- architecture.md: the import counter's query, and D9's flag read
  outside any transaction, its log line written after the COMMIT.
- ADR 0022: `applyMigration` and `deleteTransaction` named among the
  writes that do not notify, with their reason.
- QA list (44 cases): the noop import at rest, the focus ring on the
  highlighted control, "Skip" on the folder step without a folder, the
  Transactions and Budget cards on a profile without transactions, the
  focus after "Hide" and "Close", the doubled counter of the unfolded
  list, and a month-agnostic note on the off-screen cell.

Reviews of #402 to #407.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maximus changed target branch from issue-400-onboarding-budget-card to main 2026-10-09 01:10:57 +00:00
maximus merged commit ee17f31352 into main 2026-10-09 01:11:03 +00:00
Author
Owner

Merge de la pile — commits ajoutés après la revue, non relus par une revue indépendante

Pile #402 → #407 mergée le 2026-10-08 par /merge-stack, en avance rapide par l'API, chaque tête épinglée (main ee17f31). Sur décision de Max (« option A, corrige la tête et merge »), sept commits ont été posés sur cette branche, en tête de pile, après les six APPROVE : les têtes revues de #402 à #406 n'ont pas bougé.

Commit Objet Revue d'origine
a58f8b9 l'étape « Importer un premier fichier » ne compte un fichier completed qu'avec une transaction (EXISTS sur transactions.file_id) : voie A #404
696b83f D9 lit son drapeau hors transaction et n'ouvre la transaction que s'il manque #402
ec3b5d5 épingle : chaque mode de restauration notifie une fois le verrou relâché #402
74a6572 :focus-visible { outline: revert } sur le contrôle entouré (WCAG 2.4.7) #404
ba71a64 épingles : séquence réelle du reducer de Transactions, phrase de la carte selon le filtre #405
abc9076 carte Budget sans cible sur l'état vide ; fuseau fixé dans le test du mois #406
ee17f31 docs : guide FR/EN, CHANGELOG (dont une entrée Corrigé), architecture.md, ADR 0022, liste QA (44 cas) #402 à #407

Aucun ne touche un chemin de sécurité. Les trois correctifs de code (compteur, D9, cible Budget) changent une règle de production : relecture possible par /pr-review sur main si voulue.

Preuves

  • 16 mutations sur ces correctifs, une à la fois, restaurées par git : 16 rouges. Quatre d'entre elles survivaient aux revues : la notification de restauration envoyée dans le rappel, et SET_ERROR, SET_LOADING ou SET_TOTAL_IN_DB qui désarment le repli guidé.
  • Compteur rejoué avec sqlite3 sur consolidated_schema.sql : 0 après un import sans ligne valide, 0 avant la première insertion d'un import réussi et 1 après, 0 une fois le fichier passé en error. Plan d'exécution : SEARCH t USING COVERING INDEX idx_transactions_file.
  • Tip ee17f31 éprouvé dans un worktree jetable (npm ci) : sonde rouge rc=1, build vert, 109 fichiers et 1904 tests verts (1891 + 13). CI check-frontend run 507 verte, journal lu : checkout de ee17f31, mêmes chiffres.
  • Aucun fichier Rust, de CI ni de dépendance changé depuis main (src-tauri, .cargo, .forgejo, package*.json : diff vide).

Suites : #408 (db.ts laisse passer hors verrou toute requête pendant une transaction) et #409 (angles morts des harnais React des tests). Les autres constats non bloquants des revues sont devenus des cas de docs/qa-onboarding.html : focus après « Masquer » et « Fermer », compteur doublé de la liste dépliée, « Passer » sur l'étape du dossier sans dossier, cartes Transactions et Budget sur un profil sans transaction, cellule du mois hors champ.

## Merge de la pile — commits ajoutés après la revue, non relus par une revue indépendante Pile #402 → #407 mergée le 2026-10-08 par `/merge-stack`, en avance rapide par l'API, chaque tête épinglée (`main` `ee17f31`). Sur décision de Max (« option A, corrige la tête et merge »), sept commits ont été posés sur cette branche, en tête de pile, après les six APPROVE : les têtes revues de #402 à #406 n'ont pas bougé. | Commit | Objet | Revue d'origine | |---|---|---| | `a58f8b9` | l'étape « Importer un premier fichier » ne compte un fichier `completed` qu'avec une transaction (`EXISTS` sur `transactions.file_id`) : voie A | #404 | | `696b83f` | D9 lit son drapeau hors transaction et n'ouvre la transaction que s'il manque | #402 | | `ec3b5d5` | épingle : chaque mode de restauration notifie une fois le verrou relâché | #402 | | `74a6572` | `:focus-visible { outline: revert }` sur le contrôle entouré (WCAG 2.4.7) | #404 | | `ba71a64` | épingles : séquence réelle du reducer de Transactions, phrase de la carte selon le filtre | #405 | | `abc9076` | carte Budget sans cible sur l'état vide ; fuseau fixé dans le test du mois | #406 | | `ee17f31` | docs : guide FR/EN, CHANGELOG (dont une entrée Corrigé), `architecture.md`, ADR 0022, liste QA (44 cas) | #402 à #407 | Aucun ne touche un chemin de sécurité. Les trois correctifs de code (compteur, D9, cible Budget) changent une règle de production : relecture possible par `/pr-review` sur `main` si voulue. **Preuves** - 16 mutations sur ces correctifs, une à la fois, restaurées par git : 16 rouges. Quatre d'entre elles survivaient aux revues : la notification de restauration envoyée dans le rappel, et `SET_ERROR`, `SET_LOADING` ou `SET_TOTAL_IN_DB` qui désarment le repli guidé. - Compteur rejoué avec sqlite3 sur `consolidated_schema.sql` : 0 après un import sans ligne valide, 0 avant la première insertion d'un import réussi et 1 après, 0 une fois le fichier passé en `error`. Plan d'exécution : `SEARCH t USING COVERING INDEX idx_transactions_file`. - Tip `ee17f31` éprouvé dans un worktree jetable (`npm ci`) : sonde rouge rc=1, build vert, 109 fichiers et 1904 tests verts (1891 + 13). CI `check-frontend` run 507 verte, journal lu : checkout de `ee17f31`, mêmes chiffres. - Aucun fichier Rust, de CI ni de dépendance changé depuis `main` (`src-tauri`, `.cargo`, `.forgejo`, `package*.json` : diff vide). **Suites** : #408 (`db.ts` laisse passer hors verrou toute requête pendant une transaction) et #409 (angles morts des harnais React des tests). Les autres constats non bloquants des revues sont devenus des cas de `docs/qa-onboarding.html` : focus après « Masquer » et « Fermer », compteur doublé de la liste dépliée, « Passer » sur l'étape du dossier sans dossier, cartes Transactions et Budget sur un profil sans transaction, cellule du mois hors champ.
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: maximus/Simpl-Resultat#407
No description provided.