Code/docs/plans/2026-03-02-audit-qualite-design.md
Stéphan Peccini 6d2e877341
feat(audit): audit qualité complet — 907→0 erreurs ruff + fix multiselect labels
- Correction des 907 erreurs ruff (pathlib, imports, nommage, simplifications, docstrings)
- Fix déduplication labels dans multiselect nœuds d'arrivée (analyse)
- Expansion 1→N label→IDs pour le Sankey (Pays d'opération)
- Ajout CLAUDE.md et document de design de l'audit
- Mise à jour .gitignore (artefacts tests exploratoires)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:52:01 +01:00

205 lines
7.2 KiB
Markdown

# Audit qualite, securite et simplicite - FabNum
Date : 2 mars 2026
Objectif : Bilan de sante complet du projet
## Contexte
FabNum est une application Streamlit (Python 3.14) d'analyse de chaines de valeur numeriques.
Le projet comprend ~11 200 lignes de code Python reparties sur 6 modules applicatifs,
7 utilitaires, 4 composants UI et des scripts auxiliaires (IA, batch, generation).
### Etat actuel
| Metrique | Valeur |
|---|---|
| Securite (Bandit) | 0 vulnerabilite |
| Dependances (pip-audit --local) | 0 vulnerabilite |
| Qualite (ruff) | 907 erreurs |
| Tests | 67 tests, 100% passent |
| Couverture | 16% |
| Bugs averes | 1 (F821 nom indefini) |
| CLAUDE.md | Absent |
## Plan par phases
### Phase 1 : Critique (bugs et erreurs dangereuses)
Objectif : Corriger les problemes qui causent ou masquent des bugs.
| Regle | Nb | Description |
|---|---|---|
| F821 | 1 | Nom indefini `ingested_section_ids` dans scripts/generer_analyse.py:471 |
| E722 | 5 | `except:` nu (masque toutes les exceptions y compris KeyboardInterrupt) |
| B904 | 1 | `raise` sans `from` dans un except (perte de contexte d'erreur) |
| W605 | 1 | Sequence d'echappement invalide dans une chaine |
Total : 8 erreurs. Effort : ~30 minutes.
Verification : `ruff check . --exclude venv,pgpt,.git --select F821,E722,B904,W605`
### Phase 2 : Nettoyage automatique (ruff --fix)
Objectif : Appliquer les 330 corrections automatiques sans risque.
Commande : `ruff check . --exclude venv,pgpt,.git --fix`
Principales corrections :
- W293 (125) : Espaces sur lignes vides
- I001 (41) : Imports non tries
- D212 (38) : Docstrings multi-lignes mal formatees
- F401 (27) : Imports inutilises
- UP006 (27) : Annotations type obsoletes (List -> list, Dict -> dict)
- RET505 (16) : Else superflu apres return
- W291 (15) : Espaces en fin de ligne
- Autres (41) : UP009, UP015, F541, D202, W292, UP007, UP024, SIM114, SIM300, UP012
Verification apres fix : relancer les 67 tests pour confirmer aucune regression.
### Phase 3 : Qualite manuelle (577 erreurs restantes)
Objectif : Ameliorer la qualite du code manuellement, par sous-chantiers.
#### 3a. Modernisation pathlib (~220 erreurs)
Remplacer les appels `os.path.*` et `os.makedirs` par `pathlib.Path`.
Regles : PTH118, PTH123, PTH110, PTH208, PTH103, PTH120, PTH122, PTH112,
PTH100, PTH119, PTH204, PTH207, PTH113.
Approche : traiter fichier par fichier, en commencant par utils/ puis app/.
#### 3b. Nommage (88 erreurs)
N803 : noms d'arguments invalides.
Decision a prendre : `G` (convention NetworkX pour les graphes) est utilise partout.
Options :
- Ignorer N803 globalement pour les arguments nommes `G`, `G_temp`, `G_temp_ivc`
- Renommer en `graph` partout (refactoring lourd)
Recommandation : ajouter `G` a la liste des noms acceptes dans la config ruff.
#### 3c. Documentation (90 erreurs)
- D103 (35) : Fonctions publiques sans docstring
- D415 (26) : Docstrings sans ponctuation finale
- D200 (14) : Docstrings multi-lignes inutiles
- D205 (12) : Ligne vide manquante apres resume de docstring
- D417 (2) : Parametres non documentes
- D301 (1) : Sequence d'echappement dans docstring
#### 3d. Code inutilise (~53 erreurs)
- B007 (30) : Variables de boucle inutilisees (remplacer par `_`)
- ARG001 (11) : Arguments de fonction inutilises
- ARG002 (7) : Arguments de methode inutilises
- F841 (5) : Variables locales inutilisees
#### 3e. Imports (46 erreurs)
- E402 (29) : Imports pas en haut de fichier
Note : certains sont voulus dans Streamlit (imports apres st.set_page_config)
Decision : ajouter `# noqa: E402` pour les cas legitimes
- UP035 (17) : Imports deprecies (typing.List -> list, etc.)
#### 3f. Simplifications (~59 erreurs)
- RET504 (23) : Assignation inutile avant return
- SIM108 (7) : If/else remplacable par expression ternaire
- SIM105 (6) : Try/except remplacable par contextlib.suppress
- SIM102 (5) : If imbriques collapsibles
- SIM201 (4) : Negation de comparaison (not x == y -> x != y)
- RET503 (4) : Return implicite
- Autres (10) : C401, C408, C405, E701, E741, PIE810, SIM103, SIM117, SIM210, UP038
### Phase 4 : Couverture de tests (16% -> 40%)
Objectif : Couvrir les modules critiques qui sont a 0%.
Priorite haute :
- utils/persistance.py (0%, 112 lignes) : coeur de la gestion de session
- app/fiches/utils/dynamic/minerai/minerai.py (4%, 585 lignes) : module le plus gros
- app/fiches/generer.py (12%, 113 lignes) : generation de fiches
Priorite moyenne :
- app/personnalisation/ (0%, ~253 lignes)
- app/plan_d_action/ (0%, ~67 lignes interface)
- app/visualisations/ (0%, ~133 lignes)
Priorite basse :
- app/ia_nalyse/ (0%, 114 lignes) : depend d'un service externe
- utils/translations.py (28%)
- utils/visualisation.py (0%)
Note : les modules Streamlit sont difficiles a tester unitairement.
Strategie : tester la logique metier en l'isolant de l'interface Streamlit.
### Phase 5 : Simplification / Refactoring
Objectif : Decouper les gros fichiers pour ameliorer la maintenabilite.
Candidats :
- minerai.py (~585 lignes) : decouper par type de section (header, body, indices, etc.)
- modification.py (~341 lignes) : separer logique de donnees et interface
- fabnum.py (217 lignes) : extraire `get_total_bytes_for_session` et `charger_theme`
dans un module `utils/session.py` ou similaire
### Phase bonus : Documentation projet
- Creer un CLAUDE.md avec les conventions du projet
(structure, nommage, outils, commandes de dev, decisions architecturales)
## Ordre d'execution recommande
1. Phase 1 (critique) - a faire immediatement
2. Phase 2 (auto-fix) - dans la foulee
3. Phase 3b (nommage - decision sur `G`) - debloquer avant le reste
4. Phase 3a (pathlib) - le plus gros chantier, fichier par fichier
5. Phase 3d (code inutilise) - rapide
6. Phase 3e (imports) - rapide
7. Phase 3f (simplifications) - au fil de l'eau
8. Phase 3c (documentation) - au fil de l'eau
9. Phase 4 (tests) - en parallele des phases 3
10. Phase 5 (refactoring) - une fois les tests en place
11. Phase bonus (CLAUDE.md) - a tout moment
## Criteres de succes
| Metrique | Avant | Objectif | Resultat |
| --- | --- | --- | --- |
| Erreurs ruff | 907 | < 50 | **0** |
| Couverture tests | 16% | >= 40% | **35%** (448 tests) |
| Bugs averes | 1 | 0 | **0** |
| CLAUDE.md | Absent | Present | **Present** |
## Resultats de l'audit (2 mars 2026)
### Phase 1 : COMPLETE
- 8 erreurs critiques corrigees (F821, E722, B904, W605)
### Phase 2 : COMPLETE
- 330 corrections automatiques appliquees avec ruff --fix
### Phase 3 : COMPLETE
- 907 -> 0 erreurs ruff
- Migration complete vers pathlib (PTH)
- Ajout N803 aux ignores (convention NetworkX G)
- Corrections manuelles via 5 agents paralleles (RET, SIM, B007, D*, PTH)
### Phase 4 : COMPLETE (35% au lieu de 40% vise)
- 67 -> 448 tests (+381 tests, x6.7)
- 14 modules a 100% de couverture
- Modules non-testes : principalement interface Streamlit (difficile a tester unitairement)
- La couverture restante concerne des modules UI fortement couples a Streamlit
### Phase 5 : ANALYSEE (refactoring deporte)
- Candidats identifies : minerai.py (577L), modification.py (341L), fabnum.py (212L)
- Decision : refactoring deporte car fortement couple a Streamlit, risque eleve pour benefice limite dans le cadre de l'audit
- Recommandation : refactorer incrementalement lors des evolutions fonctionnelles
### Bonus : COMPLETE
- CLAUDE.md cree avec conventions du projet