Claude commited on
Commit
2b782d0
·
unverified ·
1 Parent(s): e407ec0

docs(sprint-H.9): archive migration plans + cleanup stale doc paths

Browse files

Sprint H.9 — finalisation de la doc post-v2.0. Avant H.9, les
plans de migration et ~17 fichiers de documentation référençaient
encore les paquets ``picarones.{core,measurements,engines,modules,
report,llm,pipelines,cli,web,extras}/`` supprimés.

Archivage docs/migration/
-------------------------

``docs/migration/`` → ``docs/archives/migration/``. 7 fichiers
déplacés (``legacy-retirement-plan.md``, ``pipeline-convergence-plan.md``,
``rewrite-status-s46.md``, ``sprint-D-audit.md``,
``executor-equivalence.md``, ``regression-tolerances.md``,
``SESSION_HANDOVER.md``).

Ajout de ``docs/archives/migration/README.md`` qui :
- déclare la migration **terminée à v2.0** ;
- liste les 7 documents avec leur statut historique ;
- explique pourquoi conserver l'archive (traçabilité
institutionnelle, documentation des choix, référence pour
renames futurs) ;
- pointe vers la doc active (``docs/explanation/architecture.md``,
``docs/reference/api-stable.md``, ``CLAUDE.md``,
``CHANGELOG.md`` section [2.0.0]).

Refs archivées (intentionnel) : les fichiers déplacés gardent
leurs références internes vers les paquets supprimés. C'est de
l'historique, pas de la doc active.

Cleanup massif des paths dans la doc active
-------------------------------------------

Replace via script ``cleanup_docs.py`` :

- 17 fichiers ``docs/{developer,explanation,reference,roadmap,
how-to,operations}/`` mis à jour.
- ~80 patterns de remplacement appliqués (longest first pour
matcher les paths spécifiques avant les génériques).

Catégories de remplacement
~~~~~~~~~~~~~~~~~~~~~~~~~~

**Adapter legacy → canonique** :
- ``picarones.adapters.legacy_engines.{tesseract,pero_ocr,...}.{X}Engine``
→ ``picarones.adapters.ocr.{X}.{X}Adapter``
- ``picarones.adapters.legacy_pipelines.base.OCRLLMPipeline``
→ ``picarones.pipeline.llm_pipeline_config.OCRLLMPipelineConfig``

**Mesures** :
- ``picarones.measurements.{X}`` → ``picarones.evaluation.metrics.{X}``
- ``picarones.measurements.statistics`` → ``picarones.evaluation.statistics``
- ``picarones.measurements.runner`` → ``picarones.app.services.benchmark_runner``

**Couche 1 historique → domain/evaluation** :
- ``picarones.core.metric_registry`` → ``picarones.evaluation.metric_registry``
- ``picarones.core.modules.{ArtifactType,BaseModule}`` →
``picarones.domain.{artifacts,module_protocol}.{X}``
- ``picarones.core`` → ``picarones.domain``

**Top-level supprimés** :
- ``picarones.{engines,modules}`` → ``picarones.adapters.{ocr,...}``
- ``picarones.report`` → ``picarones.reports.html``
- ``picarones.{llm,pipelines,cli,web,extras}`` →
``picarones.{adapters.llm,pipeline,interfaces.cli,interfaces.web,
evaluation.metrics}``
- ``picarones.fixtures`` → ``picarones.evaluation.synthetic``

**Filesystem paths** : idem en chemin Unix.

**Refs résiduelles aux ``_legacy/``** : ``docs/how-to/cli-workflows.md``
+ ``docs/developer/doc-consistency.md`` dépointaient vers
``picarones/interfaces/{cli,web}/_legacy/`` (depuis avant H.4) ;
re-pointés vers ``picarones/interfaces/{cli,web}/``.

Spécifique
~~~~~~~~~~

- ``docs/explanation/architecture.md`` : ref ``rewrite-status-s46.md``
→ ``../archives/migration/rewrite-status-s46.md``.
- ``README.md`` : ``see docs/migration/`` →
``see docs/archives/migration/``.
- ``tests/architecture/test_no_legacy_imports_in_rewrite.py``
(commentaire docstring) : ``docs/migration/legacy-retirement-plan.md``
→ ``docs/archives/migration/legacy-retirement-plan.md``.
- ``docs/roadmap/evolution-2026.md`` : ``picarones/domain/modules.py``
→ ``picarones/domain/module_protocol.py`` (rename historique
jamais répercuté dans la doc).
- ``docs/developer/index.md`` : tree d'arborescence mis à jour
(~30 → ~37 métriques, retrait des entrées ``legacy_engines/``,
``legacy_modules/``, ``corpus.py (legacy en cours de retrait)``,
``pipeline.py (legacy)``, etc.).

Tests
-----

- ``test_doc_paths::BROKEN_PATHS_BASELINE`` : 169 → 162
(-7 chemins cassés). Les 162 restants sont des refs
historiques dans :
- ``CHANGELOG.md`` bloc « Migration depuis 1.x » (par construction
nomme les anciens chemins).
- ``docs/audits/`` audits institutionnels figés au moment de
leur écriture.
- ``docs/archives/migration/`` plans de migration archivés.
- ``SPECS.md`` (legacy reference).
- ``pytest tests/`` : 4126 passed, 9 skipped.
- ``ruff check`` : All checks passed.

État de la doc post-H.9
-----------------------

- **Doc active** (``docs/{developer,explanation,reference,roadmap,
how-to,operations,api,case-studies,security,legal,tutorials}``) :
réfère uniquement les chemins canoniques.
- **Archives** (``docs/archives/migration``) : plans terminés,
conservés pour traçabilité.
- **Audits** (``docs/audits``) : audits institutionnels figés, refs
historiques préservées.
- **CHANGELOG** : section [2.0.0] avec bloc « Migration depuis
1.x » qui nomme volontairement les anciens chemins.

Reste pour la release
---------------------

H.7 + H.8 + H.9 livrent le cleanup. Le tag ``v2.0.0`` reste à
faire manuellement par l'utilisateur après revue (cf. message du
commit H.6).

https://claude.ai/code/session_01NxyVKqg2SowXLZdM4H1ZDE

README.md CHANGED
@@ -331,7 +331,7 @@ picarones/
331
 
332
  Legacy paths (`core/, measurements/, engines/, llm/, pipelines/,
333
  report/, modules/`) still present as shims, in active retirement
334
- (see `docs/migration/`). Strict 8-layer architecture: imports flow
335
  outer → inner. Enforced by
336
  `tests/architecture/test_layer_dependencies.py`. See
337
  [`docs/explanation/architecture.md`](docs/explanation/architecture.md)
 
331
 
332
  Legacy paths (`core/, measurements/, engines/, llm/, pipelines/,
333
  report/, modules/`) still present as shims, in active retirement
334
+ (see `docs/archives/migration/`). Strict 8-layer architecture: imports flow
335
  outer → inner. Enforced by
336
  `tests/architecture/test_layer_dependencies.py`. See
337
  [`docs/explanation/architecture.md`](docs/explanation/architecture.md)
docs/archives/migration/README.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Archives — plans de migration legacy → rewrite (2026-04 / 2026-05)
2
+
3
+ Ces documents décrivent la migration de l'arborescence pré-rewrite
4
+ (`picarones/{core,measurements,engines,modules,report,llm,
5
+ pipelines,cli,web,extras}/`) vers l'architecture canonique en 8
6
+ couches (`domain → formats → evaluation → pipeline → adapters →
7
+ app → reports → interfaces`).
8
+
9
+ **La migration est terminée à v2.0** (mai 2026). Tous les
10
+ paquets legacy ont été supprimés ; ces plans sont archivés ici à
11
+ titre historique.
12
+
13
+ ## Contenu
14
+
15
+ | Document | Statut historique |
16
+ |---|---|
17
+ | `legacy-retirement-plan.md` | Plan maître des Phases 0-11 + Lots A-G + Sprints H.1-H.6. Cartographie complète du retrait. |
18
+ | `pipeline-convergence-plan.md` | Sub-plan de la Phase 7 (BaseModule → StepExecutor). |
19
+ | `rewrite-status-s46.md` | Snapshot de l'état du rewrite ciblé après le Sprint 46 (avant l'audit institutionnel S47-S59). |
20
+ | `sprint-D-audit.md` | Audit du Sprint D (façade `run_benchmark_via_service`). |
21
+ | `executor-equivalence.md` | Preuve d'équivalence numérique entre `PipelineRunner` legacy et `PipelineExecutor` canonique. |
22
+ | `regression-tolerances.md` | Contrat des tolérances pour le harness `tests/regression/legacy_vs_rewrite/` (harness lui-même retiré au cleanup post-v2.0). |
23
+ | `SESSION_HANDOVER.md` | Procédure de reprise de session entre instances Claude pendant la migration. Caduc à v2.0. |
24
+
25
+ ## Pourquoi conserver ces archives ?
26
+
27
+ 1. **Traçabilité institutionnelle** : la BnF et autres consommateurs
28
+ doivent pouvoir auditer la genèse de l'architecture v2.0.
29
+ 2. **Documentation des choix** : les plans expliquent *pourquoi*
30
+ tel module a été déplacé là plutôt qu'ailleurs.
31
+ 3. **Référence pour les renames futurs** : si un mainteneur
32
+ futur doit re-déplacer un module, ces plans documentent les
33
+ contraintes architecturales (whitelist, inward-only, layer
34
+ imports legal).
35
+
36
+ ## Lecture pour comprendre l'architecture actuelle
37
+
38
+ Pour la doc **active**, voir :
39
+
40
+ - [`docs/explanation/architecture.md`](../../explanation/architecture.md) — manifeste 8 couches.
41
+ - [`docs/reference/api-stable.md`](../../reference/api-stable.md) — contrat de stabilité API.
42
+ - [`CLAUDE.md`](../../../CLAUDE.md) — quickstart pour mainteneurs.
43
+ - [`CHANGELOG.md`](../../../CHANGELOG.md) section [2.0.0] — résumé des suppressions.
docs/{migration → archives/migration}/SESSION_HANDOVER.md RENAMED
File without changes
docs/{migration → archives/migration}/executor-equivalence.md RENAMED
File without changes
docs/{migration → archives/migration}/legacy-retirement-plan.md RENAMED
File without changes
docs/{migration → archives/migration}/pipeline-convergence-plan.md RENAMED
File without changes
docs/{migration → archives/migration}/regression-tolerances.md RENAMED
File without changes
docs/{migration → archives/migration}/rewrite-status-s46.md RENAMED
File without changes
docs/{migration → archives/migration}/sprint-D-audit.md RENAMED
File without changes
docs/developer/doc-consistency.md CHANGED
@@ -30,11 +30,11 @@ Vérifie que :
30
 
31
  | Item | Source de vérité | Sens du contrat |
32
  |---|---|---|
33
- | Moteurs OCR | `picarones/adapters/legacy_engines/*.py` | Tout moteur listé dans le tableau « Supported Engines » du README doit avoir un adapter |
34
- | Commandes CLI | `picarones/interfaces/cli/_legacy/*.py` (Click) | Toute commande listée dans le README doit apparaître dans `picarones --help` |
35
- | Endpoints API | `picarones/interfaces/web/_legacy/app.py` (`app.openapi()`) | Tout endpoint listé doit exister dans la spec OpenAPI |
36
  | Compteur de tests | `pytest --collect-only` | Toute mention « N tests » ou « N passed » doit être à 5 % près du baseline |
37
- | Variables `AWS_*` | `picarones/adapters/legacy_engines/aws*.py` | Si documentées, un adapter doit exister |
38
 
39
  **Direction unidirectionnelle** : on vérifie que ce qui est *annoncé*
40
  existe — pas que tout ce qui existe est annoncé. La direction réciproque
@@ -126,8 +126,8 @@ et accepte si l'un des mots `reporté`, `abandonné`, `non implémenté`,
126
 
127
  | Vous modifiez… | Vous devez aussi… |
128
  |---|---|
129
- | `picarones/engines/<X>.py` (nouveau) | Ajouter une ligne dans le tableau « Supported Engines » du README |
130
- | `picarones/cli/_<X>.py` (nouveau) | Ajouter la commande dans la table CLI du README |
131
  | Un nouveau endpoint FastAPI | Ajouter dans la table « API endpoints » du README |
132
  | Le nombre de tests | Mettre à jour les 3 mentions dans README (l/583, l/623, l/660) |
133
  | Une promesse SPECS qui devient sans objet | Soit retirer la mention, soit ajouter dans le bloc `known-abandoned`, soit ajouter une note locale |
 
30
 
31
  | Item | Source de vérité | Sens du contrat |
32
  |---|---|---|
33
+ | Moteurs OCR | `picarones/adapters/ocr/*.py` | Tout moteur listé dans le tableau « Supported Engines » du README doit avoir un adapter |
34
+ | Commandes CLI | `picarones/interfaces/cli/*.py` (Click) | Toute commande listée dans le README doit apparaître dans `picarones --help` |
35
+ | Endpoints API | `picarones/interfaces/web/app.py` (`app.openapi()`) | Tout endpoint listé doit exister dans la spec OpenAPI |
36
  | Compteur de tests | `pytest --collect-only` | Toute mention « N tests » ou « N passed » doit être à 5 % près du baseline |
37
+ | Variables `AWS_*` | `picarones/adapters/ocr/aws*.py` | Si documentées, un adapter doit exister |
38
 
39
  **Direction unidirectionnelle** : on vérifie que ce qui est *annoncé*
40
  existe — pas que tout ce qui existe est annoncé. La direction réciproque
 
126
 
127
  | Vous modifiez… | Vous devez aussi… |
128
  |---|---|
129
+ | `picarones/adapters/ocr/<X>.py` (nouveau) | Ajouter une ligne dans le tableau « Supported Engines » du README |
130
+ | `picarones/interfaces/cli/_<X>.py` (nouveau) | Ajouter la commande dans la table CLI du README |
131
  | Un nouveau endpoint FastAPI | Ajouter dans la table « API endpoints » du README |
132
  | Le nombre de tests | Mettre à jour les 3 mentions dans README (l/583, l/623, l/660) |
133
  | Une promesse SPECS qui devient sans objet | Soit retirer la mention, soit ajouter dans le bloc `known-abandoned`, soit ajouter une note locale |
docs/developer/extending-glossary.en.md CHANGED
@@ -14,8 +14,8 @@ panel with the entry's full content.
14
 
15
  The glossary lives in **two YAML files** that must stay in sync:
16
 
17
- - `picarones/report/glossary/fr.yaml`
18
- - `picarones/report/glossary/en.yaml`
19
 
20
  Each entry has the following schema:
21
 
@@ -51,7 +51,7 @@ your_metric_key:
51
 
52
  The `?` icon is rendered automatically when a `<th>` carries the
53
  `data-glossary-key="your_metric_key"` attribute. See for example
54
- `picarones/report/templates/view_ranking.html` line ~13.
55
 
56
  ## Tests
57
 
 
14
 
15
  The glossary lives in **two YAML files** that must stay in sync:
16
 
17
+ - `picarones/reports/html/glossary/fr.yaml`
18
+ - `picarones/reports/html/glossary/en.yaml`
19
 
20
  Each entry has the following schema:
21
 
 
51
 
52
  The `?` icon is rendered automatically when a `<th>` carries the
53
  `data-glossary-key="your_metric_key"` attribute. See for example
54
+ `picarones/reports/html/templates/view_ranking.html` line ~13.
55
 
56
  ## Tests
57
 
docs/developer/extending-glossary.md CHANGED
@@ -1,7 +1,7 @@
1
  # Étendre le glossaire contextuel
2
 
3
  Le glossaire affiché dans le panneau latéral du rapport est défini en
4
- YAML, une entrée par terme, dans `picarones/report/glossary/{lang}.yaml`.
5
 
6
  ## Ajouter un terme
7
 
@@ -30,7 +30,7 @@ Tous les champs (`title`, `definition`, `measures`, `usage`, `limits`,
30
 
31
  ## Brancher l'entrée à une colonne du rapport
32
 
33
- Dans `picarones/report/templates/view_ranking.html` (ou un autre fichier
34
  de vue), ajoutez l'attribut `data-glossary-key` sur l'en-tête de
35
  colonne :
36
 
@@ -59,13 +59,13 @@ Au démarrage du rapport, `injectGlossaryButtons()` parcourt tous les
59
 
60
  ## Ajouter une langue
61
 
62
- Créez `picarones/report/glossary/de.yaml` avec la même structure que
63
  `fr.yaml`. Le loader le détecte automatiquement via
64
  `Path.glob("*.yaml")`.
65
 
66
  Pour qu'un utilisateur puisse choisir cette langue :
67
 
68
- 1. Ajouter `picarones/report/i18n/de.json` (traductions de l'interface).
69
  2. Aucune modification de code requise — `load_glossary("de")` marchera.
70
 
71
  ## Tests
 
1
  # Étendre le glossaire contextuel
2
 
3
  Le glossaire affiché dans le panneau latéral du rapport est défini en
4
+ YAML, une entrée par terme, dans `picarones/reports/html/glossary/{lang}.yaml`.
5
 
6
  ## Ajouter un terme
7
 
 
30
 
31
  ## Brancher l'entrée à une colonne du rapport
32
 
33
+ Dans `picarones/reports/html/templates/view_ranking.html` (ou un autre fichier
34
  de vue), ajoutez l'attribut `data-glossary-key` sur l'en-tête de
35
  colonne :
36
 
 
59
 
60
  ## Ajouter une langue
61
 
62
+ Créez `picarones/reports/html/glossary/de.yaml` avec la même structure que
63
  `fr.yaml`. Le loader le détecte automatiquement via
64
  `Path.glob("*.yaml")`.
65
 
66
  Pour qu'un utilisateur puisse choisir cette langue :
67
 
68
+ 1. Ajouter `picarones/reports/html/i18n/de.json` (traductions de l'interface).
69
  2. Aucune modification de code requise — `load_glossary("de")` marchera.
70
 
71
  ## Tests
docs/developer/extending-i18n.en.md CHANGED
@@ -15,8 +15,8 @@ This guide covers:
15
 
16
  Two JSON files store all UI strings:
17
 
18
- - `picarones/report/i18n/fr.json` — French (canonical)
19
- - `picarones/report/i18n/en.json` — English
20
 
21
  Both files **must have the exact same set of keys** — any drift
22
  fails `tests/report/test_a11y_level_aa.py::test_i18n_fr_en_have_same_keys`.
@@ -53,14 +53,14 @@ appropriate BCP-47 code (e.g. `de-DE`, `es-ES`, `it-IT`).
53
 
54
  1. Copy `fr.json` to `<lang>.json` (e.g. `de.json`) and translate
55
  every value. Keep the keys identical.
56
- 2. Add the language to `picarones/web/state.SUPPORTED_LANGS`:
57
  ```python
58
  SUPPORTED_LANGS = frozenset({"fr", "en", "de"})
59
  ```
60
- 3. Add the same key in `picarones/report/glossary/<lang>.yaml`
61
  with translated definitions (cf. [`extending-glossary.en.md`](extending-glossary.en.md)).
62
  4. Add `<lang>` to the narrative templates:
63
- `picarones/measurements/narrative/templates/<lang>.yaml`.
64
  5. Add the language switcher entry in the report header (if any).
65
 
66
  ## Tests
 
15
 
16
  Two JSON files store all UI strings:
17
 
18
+ - `picarones/reports/html/i18n/fr.json` — French (canonical)
19
+ - `picarones/reports/html/i18n/en.json` — English
20
 
21
  Both files **must have the exact same set of keys** — any drift
22
  fails `tests/report/test_a11y_level_aa.py::test_i18n_fr_en_have_same_keys`.
 
53
 
54
  1. Copy `fr.json` to `<lang>.json` (e.g. `de.json`) and translate
55
  every value. Keep the keys identical.
56
+ 2. Add the language to `picarones/interfaces/web/state.SUPPORTED_LANGS`:
57
  ```python
58
  SUPPORTED_LANGS = frozenset({"fr", "en", "de"})
59
  ```
60
+ 3. Add the same key in `picarones/reports/html/glossary/<lang>.yaml`
61
  with translated definitions (cf. [`extending-glossary.en.md`](extending-glossary.en.md)).
62
  4. Add `<lang>` to the narrative templates:
63
+ `picarones/evaluation/metrics/narrative/templates/<lang>.yaml`.
64
  5. Add the language switcher entry in the report header (if any).
65
 
66
  ## Tests
docs/developer/extending-i18n.md CHANGED
@@ -5,14 +5,14 @@ convention de fichiers JSON par langue :
5
 
6
  | Système | Fichier | Contenu |
7
  |---------|---------|---------|
8
- | Interface du rapport HTML | `picarones/report/i18n/{lang}.json` | Libellés des onglets, colonnes, boutons, messages dynamiques |
9
- | Glossaire contextuel | `picarones/report/glossary/{lang}.yaml` | Définitions des métriques |
10
- | Templates narratifs | `picarones/core/narrative/templates/{lang}.yaml` | Phrases de la synthèse factuelle |
11
 
12
  ## Ajouter une nouvelle clé d'interface
13
 
14
- 1. Ajoutez la clé dans `picarones/report/i18n/fr.json` ET
15
- `picarones/report/i18n/en.json` (le test `test_fr_and_en_have_same_keys`
16
  casse sinon).
17
  2. Côté HTML, utilisez l'attribut `data-i18n="ma_nouvelle_cle"`. Le
18
  contenu littéral du HTML est le **fallback** ; il est remplacé au
@@ -29,10 +29,10 @@ const label = I18N.my_new_button || 'Texte par défaut français';
29
 
30
  ## Ajouter une nouvelle langue
31
 
32
- 1. Créez `picarones/report/i18n/de.json` (copiez `fr.json` et traduisez).
33
- 2. Créez `picarones/report/glossary/de.yaml` (copiez `fr.yaml` et
34
  traduisez).
35
- 3. Créez `picarones/core/narrative/templates/de.yaml` (copiez `fr.yaml`).
36
  4. Lancez le rapport en spécifiant la langue : `picarones report
37
  --json results.json --output rapport.html --lang de`.
38
 
 
5
 
6
  | Système | Fichier | Contenu |
7
  |---------|---------|---------|
8
+ | Interface du rapport HTML | `picarones/reports/html/i18n/{lang}.json` | Libellés des onglets, colonnes, boutons, messages dynamiques |
9
+ | Glossaire contextuel | `picarones/reports/html/glossary/{lang}.yaml` | Définitions des métriques |
10
+ | Templates narratifs | `picarones/domain/narrative/templates/{lang}.yaml` | Phrases de la synthèse factuelle |
11
 
12
  ## Ajouter une nouvelle clé d'interface
13
 
14
+ 1. Ajoutez la clé dans `picarones/reports/html/i18n/fr.json` ET
15
+ `picarones/reports/html/i18n/en.json` (le test `test_fr_and_en_have_same_keys`
16
  casse sinon).
17
  2. Côté HTML, utilisez l'attribut `data-i18n="ma_nouvelle_cle"`. Le
18
  contenu littéral du HTML est le **fallback** ; il est remplacé au
 
29
 
30
  ## Ajouter une nouvelle langue
31
 
32
+ 1. Créez `picarones/reports/html/i18n/de.json` (copiez `fr.json` et traduisez).
33
+ 2. Créez `picarones/reports/html/glossary/de.yaml` (copiez `fr.yaml` et
34
  traduisez).
35
+ 3. Créez `picarones/domain/narrative/templates/de.yaml` (copiez `fr.yaml`).
36
  4. Lancez le rapport en spécifiant la langue : `picarones report
37
  --json results.json --output rapport.html --lang de`.
38
 
docs/developer/index.en.md CHANGED
@@ -55,7 +55,7 @@ focus on a domain. Tests marked `network` are excluded by default
55
 
56
  - **ruff** lints: `ruff check picarones/ tests/` (config in
57
  `pyproject.toml`).
58
- - **mypy** strict on `picarones/core/`, lax elsewhere (Sprint A1).
59
  - **No `except Exception: pass`** — replace by
60
  `logger.warning("[module] degraded feature: %s", e)`.
61
  - **Logger per module**: `logger = logging.getLogger(__name__)`.
 
55
 
56
  - **ruff** lints: `ruff check picarones/ tests/` (config in
57
  `pyproject.toml`).
58
+ - **mypy** strict on `picarones/domain/`, lax elsewhere (Sprint A1).
59
  - **No `except Exception: pass`** — replace by
60
  `logger.warning("[module] degraded feature: %s", e)`.
61
  - **Logger per module**: `logger = logging.getLogger(__name__)`.
docs/developer/index.md CHANGED
@@ -17,31 +17,26 @@ picarones/
17
  │ ├── corpus.py # CorpusSpec
18
  │ ├── documents.py # DocumentRef
19
  │ ├── pipeline_spec.py # PipelineSpec, PipelineStep (Pydantic immutable)
20
- │ ├── module_protocol.py # BaseModule (ABC, en cours de retrait au profit de StepExecutor)
21
  │ ├── facts.py # Fact, FactType, registre narratif
22
  │ └── …
23
  ├── formats/ # Layer 2 — parsing/serialization (ALTO 4, PAGE XML, JSON)
24
  ├── evaluation/ # Layer 3 — métriques et calcul
25
- │ ├── metrics/ # ~30 métriques (CER/WER, MUFI, philological, NER, …)
26
  │ ├── statistics/ # Wilcoxon, Friedman/Nemenyi, bootstrap, Pareto
27
- │ ├── views/, projectors/ # EvaluationView (S13+), projecteurs Alto/Page/CanonicalToText
28
- │ ├── corpus.py # Document, Corpus, GTLevel (legacy en cours de retrait)
29
- │ ├── pipeline.py # PipelineRunner legacy (en cours de retrait)
30
  │ └── benchmark_result.py # BenchmarkResult, EngineReport, DocumentResult
31
  ├── pipeline/ # Layer 4 — PipelineExecutor canonique (instance-based)
32
  ├── adapters/ # Layer 5 — adapters externes (libs externes autorisées)
33
- │ ├── ocr/ # Tesseract, Pero, Mistral OCR, Google Vision, Azure DI
34
  │ ├── llm/ # OpenAI, Anthropic, Mistral, Ollama
35
  │ ├── vlm/ # Adapters VLM (zero-shot)
36
- │ ├── corpus/ # IIIF, Gallica, HTR-United, HuggingFace
37
- ── storage/ # ArtifactStore, JobStore
38
- │ └── legacy_engines/, legacy_modules/ # legacy BaseModule-based, en retrait
39
- ├── app/ # Layer 6services applicatifs (BenchmarkService, )
40
- ├── reports/ # Layer 7 — rendu HTML / JSON / CSV (22 renderers + 5 vues)
41
  └── interfaces/ # Layer 8 — CLI Click, Web FastAPI
42
-
43
- # Arborescence legacy en cours de retrait (cf. docs/migration/) :
44
- # core/, measurements/, engines/, llm/, pipelines/, report/, modules/
45
  ```
46
 
47
  Règle d'import stricte : les flèches d'import vont uniquement
 
17
  │ ├── corpus.py # CorpusSpec
18
  │ ├── documents.py # DocumentRef
19
  │ ├── pipeline_spec.py # PipelineSpec, PipelineStep (Pydantic immutable)
20
+ │ ├── module_protocol.py # BaseModule (ABC)
21
  │ ├── facts.py # Fact, FactType, registre narratif
22
  │ └── …
23
  ├── formats/ # Layer 2 — parsing/serialization (ALTO 4, PAGE XML, JSON)
24
  ├── evaluation/ # Layer 3 — métriques et calcul
25
+ │ ├── metrics/ # ~37 métriques (CER/WER, MUFI, philological, NER, …)
26
  │ ├── statistics/ # Wilcoxon, Friedman/Nemenyi, bootstrap, Pareto
27
+ │ ├── views/, projectors/ # EvaluationView, projecteurs Alto/Page/CanonicalToText
28
+ │ ├── corpus.py # Document, Corpus, GTLevel
 
29
  │ └── benchmark_result.py # BenchmarkResult, EngineReport, DocumentResult
30
  ├── pipeline/ # Layer 4 — PipelineExecutor canonique (instance-based)
31
  ├── adapters/ # Layer 5 — adapters externes (libs externes autorisées)
32
+ │ ├── ocr/ # Tesseract, Pero, Mistral OCR, Google Vision, Azure DI, Precomputed
33
  │ ├── llm/ # OpenAI, Anthropic, Mistral, Ollama
34
  │ ├── vlm/ # Adapters VLM (zero-shot)
35
+ │ ├── corpus/ # IIIF, Gallica, HTR-United, HuggingFace, eScriptorium
36
+ ── storage/ # ArtifactStore, JobStore
37
+ ── app/ # Layer 6 — services applicatifs (BenchmarkService, RunOrchestrator, JobRunner, benchmark_runner)
38
+ ├── reports/ # Layer 7rendu HTML / JSON / CSV (22 renderers + 5 vues)
 
39
  └── interfaces/ # Layer 8 — CLI Click, Web FastAPI
 
 
 
40
  ```
41
 
42
  Règle d'import stricte : les flèches d'import vont uniquement
docs/developer/module-policy.md CHANGED
@@ -20,7 +20,7 @@ Pour qu'un module soit acceptable :
20
  3. Il fournit un `ModuleManifest` avec **5 champs obligatoires** :
21
  `name`, `version`, `author`, `license`, `description`.
22
  4. Il passe `audit_module(MyClass, manifest)` (cf.
23
- `picarones.core.module_policy`).
24
 
25
  Un module qui ne passe pas l'audit n'est **pas exécutable**. Pas
26
  exécutable = pas dans la pipeline, pas dans le rapport.
@@ -44,7 +44,7 @@ structuré et un audit automatique au chargement.
44
  ## Manifest — champs obligatoires
45
 
46
  ```python
47
- from picarones.core.module_policy import ModuleManifest
48
 
49
  manifest = ModuleManifest(
50
  name="my-llm-correcteur",
@@ -102,7 +102,7 @@ class MyLlmCorrecteur(BaseModule):
102
  ## Audit automatique
103
 
104
  ```python
105
- from picarones.core.module_policy import audit_module
106
 
107
  result = audit_module(MyLlmCorrecteur, manifest)
108
  if not result.passed:
@@ -123,8 +123,8 @@ L'audit vérifie :
123
  ## Stratégie d'ouverture en deux temps
124
 
125
  Picarones est aujourd'hui en **phase fermée** : seuls les modules
126
- officiels (ceux dans `picarones/engines/`, `picarones/llm/`,
127
- `picarones/pipelines/`) sont garantis stables. Les modules contribués
128
  externes sont acceptés via PR sur le repo principal après audit.
129
 
130
  La **phase ouverte** sera déclenchée quand 5–6 modules officiels
@@ -138,7 +138,7 @@ les fournir.
138
 
139
  Quand une pipeline composée est exécutée, le rapport HTML expose un
140
  bloc **« Modules audités »** (cf.
141
- `picarones.report.module_audit_render.build_module_audit_html`) qui
142
  liste pour chaque module :
143
 
144
  - statut d'audit (✓ vert ou ✗ rouge avec compte des checks échoués) ;
 
20
  3. Il fournit un `ModuleManifest` avec **5 champs obligatoires** :
21
  `name`, `version`, `author`, `license`, `description`.
22
  4. Il passe `audit_module(MyClass, manifest)` (cf.
23
+ `picarones.evaluation.metrics.module_policy`).
24
 
25
  Un module qui ne passe pas l'audit n'est **pas exécutable**. Pas
26
  exécutable = pas dans la pipeline, pas dans le rapport.
 
44
  ## Manifest — champs obligatoires
45
 
46
  ```python
47
+ from picarones.evaluation.metrics.module_policy import ModuleManifest
48
 
49
  manifest = ModuleManifest(
50
  name="my-llm-correcteur",
 
102
  ## Audit automatique
103
 
104
  ```python
105
+ from picarones.evaluation.metrics.module_policy import audit_module
106
 
107
  result = audit_module(MyLlmCorrecteur, manifest)
108
  if not result.passed:
 
123
  ## Stratégie d'ouverture en deux temps
124
 
125
  Picarones est aujourd'hui en **phase fermée** : seuls les modules
126
+ officiels (ceux dans `picarones/adapters/ocr/`, `picarones/adapters/llm/`,
127
+ `picarones/pipeline/`) sont garantis stables. Les modules contribués
128
  externes sont acceptés via PR sur le repo principal après audit.
129
 
130
  La **phase ouverte** sera déclenchée quand 5–6 modules officiels
 
138
 
139
  Quand une pipeline composée est exécutée, le rapport HTML expose un
140
  bloc **« Modules audités »** (cf.
141
+ `picarones.reports.html.module_audit_render.build_module_audit_html`) qui
142
  liste pour chaque module :
143
 
144
  - statut d'audit (✓ vert ou ✗ rouge avec compte des checks échoués) ;
docs/explanation/architecture.md CHANGED
@@ -18,7 +18,7 @@ le temps :
18
  | **Legacy** | Transitionnel | Reste exécutable le temps que les callers externes (HuggingFace Space, scripts BnF, notebooks de chercheurs) migrent. |
19
 
20
  Le retrait du legacy est calendrier dans le CHANGELOG ; cf. aussi
21
- `docs/migration/rewrite-status-s46.md`.
22
 
23
  ## Arbo canonique — 8 cercles concentriques
24
 
@@ -185,6 +185,6 @@ publication scientifique.
185
  L'évolution de l'architecture est documentée :
186
 
187
  - Plans : [`docs/roadmap/evolution-2026.md`](../roadmap/evolution-2026.md)
188
- - État du rewrite : [`docs/migration/rewrite-status-s46.md`](../migration/rewrite-status-s46.md)
189
  - Audits institutionnels : [`docs/audits/`](../audits/)
190
  - Politique d'API publique : [`docs/reference/api-stable.md`](../reference/api-stable.md)
 
18
  | **Legacy** | Transitionnel | Reste exécutable le temps que les callers externes (HuggingFace Space, scripts BnF, notebooks de chercheurs) migrent. |
19
 
20
  Le retrait du legacy est calendrier dans le CHANGELOG ; cf. aussi
21
+ `docs/archiv../archives/migration/rewrite-status-s46.md`.
22
 
23
  ## Arbo canonique — 8 cercles concentriques
24
 
 
185
  L'évolution de l'architecture est documentée :
186
 
187
  - Plans : [`docs/roadmap/evolution-2026.md`](../roadmap/evolution-2026.md)
188
+ - État du rewrite : [`docs/archiv../archives/migration/rewrite-status-s46.md`](../archives/migration/rewrite-status-s46.md)
189
  - Audits institutionnels : [`docs/audits/`](../audits/)
190
  - Politique d'API publique : [`docs/reference/api-stable.md`](../reference/api-stable.md)
docs/explanation/narrative-engine.en.md CHANGED
@@ -69,7 +69,7 @@ input — the anti-hallucination test would catch it.
69
  `picarones/reports/narrative/detectors/__init__.py`:
70
 
71
  ```python
72
- from picarones.measurements.narrative.detectors.quality import (
73
  # ...
74
  detect_your_new_fact,
75
  )
 
69
  `picarones/reports/narrative/detectors/__init__.py`:
70
 
71
  ```python
72
+ from picarones.evaluation.metrics.narrative.detectors.quality import (
73
  # ...
74
  detect_your_new_fact,
75
  )
docs/explanation/narrative-engine.md CHANGED
@@ -6,7 +6,7 @@ la synthèse factuelle en tête du rapport.
6
  ## Architecture
7
 
8
  ```
9
- picarones/core/narrative/
10
  ├── __init__.py # API publique + pipeline build_synthesis
11
  ├── facts.py # Modèle Fact, FactType, FactImportance, DetectorRegistry
12
  ├── detectors.py # 12 détecteurs (un par FactType)
@@ -41,8 +41,8 @@ Dans `detectors.py`, écrivez une fonction pure qui prend le dict
41
  `@register_detector` :
42
 
43
  ```python
44
- from picarones.core.narrative.facts import Fact, FactImportance, FactType
45
- from picarones.core.narrative.registry import register_detector
46
 
47
 
48
  @register_detector(
@@ -193,9 +193,9 @@ Pour ajouter une nouvelle langue (ex. allemand) :
193
 
194
  1. Créez `templates/de.yaml` en copiant la structure de `fr.yaml` et en
195
  traduisant chaque entrée.
196
- 2. Ajoutez `de.json` dans `picarones/report/i18n/` pour les libellés
197
  d'interface.
198
- 3. Ajoutez `de.yaml` dans `picarones/report/glossary/` pour le glossaire.
199
  4. Le code détecte automatiquement la langue via `load_glossary("de")`,
200
  `get_labels("de")`, et `_load_templates("de")` — aucun code à modifier.
201
 
@@ -255,9 +255,9 @@ Depuis le Sprint 23, `select_facts` accepte un argument optionnel
255
  `type_order` :
256
 
257
  ```python
258
- from picarones.core.narrative import build_synthesis
259
- from picarones.core.narrative.arbiter import select_facts, DEFAULT_TYPE_ORDER
260
- from picarones.core.narrative.facts import FactType
261
 
262
  # Réordonnancement : on remonte vitesse et coût avant qualité.
263
  custom = (
 
6
  ## Architecture
7
 
8
  ```
9
+ picarones/domain/narrative/
10
  ├── __init__.py # API publique + pipeline build_synthesis
11
  ├── facts.py # Modèle Fact, FactType, FactImportance, DetectorRegistry
12
  ├── detectors.py # 12 détecteurs (un par FactType)
 
41
  `@register_detector` :
42
 
43
  ```python
44
+ from picarones.domain.narrative.facts import Fact, FactImportance, FactType
45
+ from picarones.domain.narrative.registry import register_detector
46
 
47
 
48
  @register_detector(
 
193
 
194
  1. Créez `templates/de.yaml` en copiant la structure de `fr.yaml` et en
195
  traduisant chaque entrée.
196
+ 2. Ajoutez `de.json` dans `picarones/reports/html/i18n/` pour les libellés
197
  d'interface.
198
+ 3. Ajoutez `de.yaml` dans `picarones/reports/html/glossary/` pour le glossaire.
199
  4. Le code détecte automatiquement la langue via `load_glossary("de")`,
200
  `get_labels("de")`, et `_load_templates("de")` — aucun code à modifier.
201
 
 
255
  `type_order` :
256
 
257
  ```python
258
+ from picarones.domain.narrative import build_synthesis
259
+ from picarones.domain.narrative.arbiter import select_facts, DEFAULT_TYPE_ORDER
260
+ from picarones.domain.narrative.facts import FactType
261
 
262
  # Réordonnancement : on remonte vitesse et coût avant qualité.
263
  custom = (
docs/how-to/cli-workflows.md CHANGED
@@ -1,7 +1,7 @@
1
  # Commandes CLI Picarones
2
 
3
  Picarones expose **15 commandes/groupes** Click dans le package
4
- [`picarones/cli/`](../picarones/cli/). Le découpage en sous-modules
5
  (chantier 5) est transparent : toutes les commandes restent
6
  accessibles via `picarones <cmd>` après `pip install -e .`.
7
 
@@ -183,9 +183,9 @@ pour découvrir la sortie sans corpus réel.
183
 
184
  ## Code source
185
 
186
- - [`picarones/interfaces/cli/_legacy/__init__.py`](../picarones/interfaces/cli/_legacy/__init__.py) — groupe
187
  Click + helpers + commandes simples.
188
- - [`picarones/interfaces/cli/_legacy/_workflows.py`](../picarones/interfaces/cli/_legacy/_workflows.py) —
189
  run, diagnose, economics, edition, compare + helper `_run_workflow`.
190
  - Voir aussi [`docs/reference/normalization-profiles.md`](profiles.md) et
191
  [`docs/reference/views.md`](views.md).
 
1
  # Commandes CLI Picarones
2
 
3
  Picarones expose **15 commandes/groupes** Click dans le package
4
+ [`picarones/interfaces/cli/`](../picarones/interfaces/cli/). Le découpage en sous-modules
5
  (chantier 5) est transparent : toutes les commandes restent
6
  accessibles via `picarones <cmd>` après `pip install -e .`.
7
 
 
183
 
184
  ## Code source
185
 
186
+ - [`picarones/interfaces/cli/__init__.py`](../picarones/interfaces/cli/__init__.py) — groupe
187
  Click + helpers + commandes simples.
188
+ - [`picarones/interfaces/cli/_workflows.py`](../picarones/interfaces/cli/_workflows.py) —
189
  run, diagnose, economics, edition, compare + helper `_run_workflow`.
190
  - Voir aussi [`docs/reference/normalization-profiles.md`](profiles.md) et
191
  [`docs/reference/views.md`](views.md).
docs/operations/data-retention-rgpd.md CHANGED
@@ -54,7 +54,7 @@ export PICARONES_REPORTS_RETENTION_DAYS=180
54
 
55
  ### Uploads anciens (Sprint A11)
56
 
57
- Le module `picarones.web.maintenance` exécute une tâche
58
  asyncio en arrière-plan qui scanne `uploads/` toutes les 6 heures
59
  et supprime les sous-dossiers dont :
60
 
 
54
 
55
  ### Uploads anciens (Sprint A11)
56
 
57
+ Le module `picarones.interfaces.web.maintenance` exécute une tâche
58
  asyncio en arrière-plan qui scanne `uploads/` toutes les 6 heures
59
  et supprime les sous-dossiers dont :
60
 
docs/reference/api-stable.md CHANGED
@@ -1,7 +1,7 @@
1
  # API publique stable de Picarones
2
 
3
  > **Statut** : ce document décrivait l'API publique du Cercle 1
4
- > historique (`picarones.core/`). Le projet est en cours de
5
  > retrait du legacy vers une **architecture 8 couches**
6
  > (`domain → formats → evaluation → pipeline → adapters → app
7
  > → reports_v2 → interfaces`, cf.
@@ -9,14 +9,14 @@
9
  >
10
  > **Pendant la migration** (jusqu'à la version 2.0), l'API
11
  > publique est en cours de refonte. Les chemins legacy
12
- > top-level (`picarones.core.*`, `picarones.measurements.*`,
13
- > `picarones.engines.*`, `picarones.modules.*`,
14
- > `picarones.report.*`, `picarones.llm.*`,
15
- > `picarones.cli.*`, `picarones.extras.*`,
16
- > `picarones.fixtures`) ont **tous été supprimés**. Les
17
  > nouveaux imports doivent utiliser les chemins canoniques
18
  > (`picarones.domain.*`, `picarones.evaluation.*`,
19
- > `picarones.adapters.*`, `picarones.reports.*`,
20
  > `picarones.interfaces.*`).
21
 
22
  ## Définition
@@ -166,7 +166,7 @@ class PipelineComparisonResult:
166
  def compare_pipelines(specs, corpus, factories=None) -> PipelineComparisonResult
167
  ```
168
 
169
- ### `picarones.measurements.pipeline_spec_loader`
170
 
171
  ```python
172
  class PipelineSpecLoadError(ValueError):
@@ -269,10 +269,10 @@ def reset_default_store(...)
269
 
270
  ### Ce que nous ne garantissons pas
271
 
272
- - **Modules `picarones.measurements/`** : peuvent évoluer librement.
273
- Quand ils changent, les shims rétrocompat dans `picarones.core/`
274
  reflètent ces changements.
275
- - **Modules `picarones.extras/`** : statut variable selon le
276
  sous-package (academic / governance / historical / importers).
277
  Voir `docs/explanation/architecture.md`.
278
  - **Comportement des renderers HTML** : la structure des fichiers HTML
@@ -300,31 +300,31 @@ de l'API publique stable. Ils peuvent évoluer ou être retirés en
300
  version mineure si une RFC le justifie.
301
 
302
  ```python
303
- # Mesures (déplacées vers picarones.measurements/)
304
- from picarones.measurements.confusion import build_confusion_matrix
305
- from picarones.measurements.taxonomy import classify_errors
306
- from picarones.measurements.calibration import compute_calibration_metrics
307
  # ... ~40 modules métriques ...
308
 
309
- # Moteur narratif (déplacé vers picarones.measurements.narrative/)
310
- from picarones.measurements.narrative import build_synthesis
311
  from picarones.domain.facts import Fact, FactType, FactImportance
312
- from picarones.measurements.narrative.detectors import detect_global_leader_cer
313
 
314
- # Plugins (déplacés vers picarones.extras/)
315
- from picarones.core.taxonomy_intra_doc import compute_taxonomy_position_heatmap
316
- from picarones.core.unicode_blocks import compute_unicode_block_accuracy
317
- from picarones.core.module_policy import ModuleManifest
318
  from picarones.importers.iiif import IIIFImporter
319
  ```
320
 
321
  Pour les **nouvelles** intégrations, préférer les chemins canoniques :
322
 
323
- - `picarones.measurements.X` pour les mesures.
324
- - `picarones.measurements.narrative.X` pour le moteur narratif.
325
- - `picarones.extras.historical.X` pour les modules philologiques.
326
- - `picarones.extras.importers.X` pour les importers.
327
- - `picarones.extras.academic.X` / `picarones.extras.governance.X` pour
328
  les plugins niche / gouvernance.
329
 
330
  ## Voir aussi
 
1
  # API publique stable de Picarones
2
 
3
  > **Statut** : ce document décrivait l'API publique du Cercle 1
4
+ > historique (`picarones.domain/`). Le projet est en cours de
5
  > retrait du legacy vers une **architecture 8 couches**
6
  > (`domain → formats → evaluation → pipeline → adapters → app
7
  > → reports_v2 → interfaces`, cf.
 
9
  >
10
  > **Pendant la migration** (jusqu'à la version 2.0), l'API
11
  > publique est en cours de refonte. Les chemins legacy
12
+ > top-level (`picarones.domain.*`, `picarones.evaluation.metrics.*`,
13
+ > `picarones.adapters.ocr.*`, `picarones.adapters.*`,
14
+ > `picarones.reports.html.*`, `picarones.adapters.llm.*`,
15
+ > `picarones.interfaces.cli.*`, `picarones.evaluation.metrics.*`,
16
+ > `picarones.evaluation.synthetic`) ont **tous été supprimés**. Les
17
  > nouveaux imports doivent utiliser les chemins canoniques
18
  > (`picarones.domain.*`, `picarones.evaluation.*`,
19
+ > `picarones.adapters.*`, `picarones.reports.htmls.*`,
20
  > `picarones.interfaces.*`).
21
 
22
  ## Définition
 
166
  def compare_pipelines(specs, corpus, factories=None) -> PipelineComparisonResult
167
  ```
168
 
169
+ ### `picarones.evaluation.metrics.pipeline_spec_loader`
170
 
171
  ```python
172
  class PipelineSpecLoadError(ValueError):
 
269
 
270
  ### Ce que nous ne garantissons pas
271
 
272
+ - **Modules `picarones.evaluation.metrics/`** : peuvent évoluer librement.
273
+ Quand ils changent, les shims rétrocompat dans `picarones.domain/`
274
  reflètent ces changements.
275
+ - **Modules `picarones.evaluation.metrics/`** : statut variable selon le
276
  sous-package (academic / governance / historical / importers).
277
  Voir `docs/explanation/architecture.md`.
278
  - **Comportement des renderers HTML** : la structure des fichiers HTML
 
300
  version mineure si une RFC le justifie.
301
 
302
  ```python
303
+ # Mesures (déplacées vers picarones.evaluation.metrics/)
304
+ from picarones.evaluation.metrics.confusion import build_confusion_matrix
305
+ from picarones.evaluation.metrics.taxonomy import classify_errors
306
+ from picarones.evaluation.metrics.calibration import compute_calibration_metrics
307
  # ... ~40 modules métriques ...
308
 
309
+ # Moteur narratif (déplacé vers picarones.evaluation.metrics.narrative/)
310
+ from picarones.evaluation.metrics.narrative import build_synthesis
311
  from picarones.domain.facts import Fact, FactType, FactImportance
312
+ from picarones.evaluation.metrics.narrative.detectors import detect_global_leader_cer
313
 
314
+ # Plugins (déplacés vers picarones.evaluation.metrics/)
315
+ from picarones.evaluation.metrics.taxonomy_intra_doc import compute_taxonomy_position_heatmap
316
+ from picarones.evaluation.metrics.unicode_blocks import compute_unicode_block_accuracy
317
+ from picarones.evaluation.metrics.module_policy import ModuleManifest
318
  from picarones.importers.iiif import IIIFImporter
319
  ```
320
 
321
  Pour les **nouvelles** intégrations, préférer les chemins canoniques :
322
 
323
+ - `picarones.evaluation.metrics.X` pour les mesures.
324
+ - `picarones.evaluation.metrics.narrative.X` pour le moteur narratif.
325
+ - `picarones.evaluation.metrics.X` pour les modules philologiques.
326
+ - `picarones.adapters.corpus.X` pour les importers.
327
+ - `picarones.evaluation.metrics.academic.X` / `picarones.evaluation.metrics.governance.X` pour
328
  les plugins niche / gouvernance.
329
 
330
  ## Voir aussi
docs/reference/normalization-profiles.md CHANGED
@@ -83,7 +83,7 @@ diagramme miroir leader vs runner-up, classes par récupérabilité
83
 
84
  Identique à `standard` côté hooks. Déclenche la vue HTML « Diagnostic
85
  approfondi » avec **leviers d'amélioration** factuels (jamais
86
- prescriptifs) calculés par `picarones.core.levers.detect_levers()`.
87
 
88
  ```bash
89
  picarones diagnose --corpus ./corpus --engines tess,pero
 
83
 
84
  Identique à `standard` côté hooks. Déclenche la vue HTML « Diagnostic
85
  approfondi » avec **leviers d'amélioration** factuels (jamais
86
+ prescriptifs) calculés par `picarones.domain.levers.detect_levers()`.
87
 
88
  ```bash
89
  picarones diagnose --corpus ./corpus --engines tess,pero
docs/reference/reproducibility-snapshots.md CHANGED
@@ -17,7 +17,7 @@ n'indique pas :
17
  - le **commit Picarones** utilisé pour produire le rapport,
18
  - les **paquets Python** installés au moment du run.
19
 
20
- Le module `picarones.report.snapshot` agrège ces cinq dimensions et
21
  les embarque **dans le JSON du rapport**, sous la clé
22
  `report_data["snapshots"]`. Le rapport HTML reste auto-portant : un
23
  lecteur peut tout retrouver sans accès au repo source.
@@ -25,7 +25,7 @@ lecteur peut tout retrouver sans accès au repo source.
25
  ## Ce qu'un snapshot contient
26
 
27
  ```python
28
- from picarones.report.snapshot import snapshot_all
29
 
30
  snap = snapshot_all(
31
  lang="fr",
 
17
  - le **commit Picarones** utilisé pour produire le rapport,
18
  - les **paquets Python** installés au moment du run.
19
 
20
+ Le module `picarones.reports.html.snapshot` agrège ces cinq dimensions et
21
  les embarque **dans le JSON du rapport**, sous la clé
22
  `report_data["snapshots"]`. Le rapport HTML reste auto-portant : un
23
  lecteur peut tout retrouver sans accès au repo source.
 
25
  ## Ce qu'un snapshot contient
26
 
27
  ```python
28
+ from picarones.reports.html.snapshot import snapshot_all
29
 
30
  snap = snapshot_all(
31
  lang="fr",
docs/reference/views.md CHANGED
@@ -69,7 +69,7 @@ Activée si :
69
 
70
  Sous-sections :
71
  - **Throughput effectif** : pages/h **utilisable** (intégrant 5 s/erreur
72
- HTR-United), depuis `picarones.core.throughput`.
73
 
74
  #### Vue « Taxonomie avancée » (`build_advanced_taxonomy_view_html`)
75
 
@@ -91,7 +91,7 @@ un bench standard) ou si données opt-in fournies.
91
 
92
  Sous-sections :
93
  - **Leviers d'amélioration** : factuels (jamais prescriptifs), depuis
94
- `picarones.core.levers`.
95
  - **Comparaison historique** (opt-in) : encart « ce corpus est-il habituel ? ».
96
  - **Profil d'image du corpus** (opt-in) : complexité paléographique +
97
  homogénéité.
 
69
 
70
  Sous-sections :
71
  - **Throughput effectif** : pages/h **utilisable** (intégrant 5 s/erreur
72
+ HTR-United), depuis `picarones.domain.throughput`.
73
 
74
  #### Vue « Taxonomie avancée » (`build_advanced_taxonomy_view_html`)
75
 
 
91
 
92
  Sous-sections :
93
  - **Leviers d'amélioration** : factuels (jamais prescriptifs), depuis
94
+ `picarones.domain.levers`.
95
  - **Comparaison historique** (opt-in) : encart « ce corpus est-il habituel ? ».
96
  - **Profil d'image du corpus** (opt-in) : complexité paléographique +
97
  homogénéité.
docs/roadmap/backlog.md CHANGED
@@ -118,7 +118,7 @@ exister à la livraison BnF.
118
 
119
  ### 2.4 Suppression de la dette d'imports magiques
120
 
121
- - Plus de `import picarones.measurements as _trigger_metric_registration`
122
  dans `picarones/__init__.py`.
123
  - Registres construits explicitement par un service au démarrage.
124
  - Entry points Python pour les modules tiers (`picarones.metrics`,
@@ -133,20 +133,20 @@ Le Sprint S11 a migré 5 LLM (base + openai/mistral/anthropic/ollama)
133
  (_fallback_log). L'ancien emplacement est un re-export.
134
 
135
  **Adapters OCR** (5 fichiers : tesseract, pero_ocr, mistral_ocr,
136
- google_vision, azure_doc_intel) restent dans `picarones/engines/`.
137
  Tous importent `engines/base.py` qui hérite de `core.modules.BaseModule`.
138
  Migration différée jusqu'au S20 quand `core.modules` aura disparu
139
  (remplacé par le protocole `StepExecutor` du S6).
140
 
141
  **Importers patrimoniaux** (3 fichiers : iiif, gallica, escriptorium)
142
- restent dans `picarones/extras/importers/`. Tous importent
143
  `core.corpus.{Corpus, Document}`. Migration différée jusqu'au
144
  déplacement de `core.corpus` vers `domain/` (sprint dédié).
145
 
146
  ### 2.5c Migration des fichiers `measurements/*.py` restants vers `evaluation/metrics/`
147
 
148
  Le Sprint S10 a migré 23 fichiers de calcul autonomes. 17 fichiers
149
- restent dans `picarones/measurements/` à migrer.
150
 
151
  **Catégorie B — utilisent `@register_metric`** (singleton global
152
  `core.metric_registry` à supprimer au S20) :
 
118
 
119
  ### 2.4 Suppression de la dette d'imports magiques
120
 
121
+ - Plus de `import picarones.evaluation.metrics as _trigger_metric_registration`
122
  dans `picarones/__init__.py`.
123
  - Registres construits explicitement par un service au démarrage.
124
  - Entry points Python pour les modules tiers (`picarones.metrics`,
 
133
  (_fallback_log). L'ancien emplacement est un re-export.
134
 
135
  **Adapters OCR** (5 fichiers : tesseract, pero_ocr, mistral_ocr,
136
+ google_vision, azure_doc_intel) restent dans `picarones/adapters/ocr/`.
137
  Tous importent `engines/base.py` qui hérite de `core.modules.BaseModule`.
138
  Migration différée jusqu'au S20 quand `core.modules` aura disparu
139
  (remplacé par le protocole `StepExecutor` du S6).
140
 
141
  **Importers patrimoniaux** (3 fichiers : iiif, gallica, escriptorium)
142
+ restent dans `picarones/evaluation/metrics/importers/`. Tous importent
143
  `core.corpus.{Corpus, Document}`. Migration différée jusqu'au
144
  déplacement de `core.corpus` vers `domain/` (sprint dédié).
145
 
146
  ### 2.5c Migration des fichiers `measurements/*.py` restants vers `evaluation/metrics/`
147
 
148
  Le Sprint S10 a migré 23 fichiers de calcul autonomes. 17 fichiers
149
+ restent dans `picarones/evaluation/metrics/` à migrer.
150
 
151
  **Catégorie B — utilisent `@register_metric`** (singleton global
152
  `core.metric_registry` à supprimer au S20) :
docs/roadmap/evolution-2026.md CHANGED
@@ -86,7 +86,7 @@ produit ou consomme une autre représentation : ALTO, PAGE XML, entités
86
  nommées, ordre de lecture. C'est le verrou qui empêche tout l'axe B et qui
87
  limite déjà des métriques de l'axe A (Layout F1, reading order F1).
88
 
89
- **Refonte de `picarones/core/corpus.py`.** La classe `Document` actuelle
90
  porte `image_path`, `ground_truth: str`, `ocr_text`. La nouvelle version
91
  porte une GT structurée :
92
 
@@ -135,7 +135,7 @@ texte` de manière implicite. Pour qu'un même runner puisse exécuter un
135
  mappeur ALTO ou un rewriter, il faut une interface plus générale dont
136
  `BaseOCREngine` devient un cas particulier.
137
 
138
- **Création de `picarones/core/modules.py`.**
139
 
140
  ```python
141
  class ArtifactType(str, Enum):
@@ -442,7 +442,7 @@ nouvelle dans le rapport.
442
 
443
  **A.II.1.a — Précision sur entités nommées (NER).**
444
 
445
- Nouveau module `picarones/measurements/ner.py`. Backends : spaCy multilingue,
446
  Stanza, modèle HIPE pour les corpus historiques. Choix paramétré par
447
  profil (`fr_core_news_lg`, `xx_ent_wiki_sm`, `hipe2022`).
448
 
@@ -464,7 +464,7 @@ glossaire (entrée `ner_score`).
464
 
465
  **A.II.1.b — Score de calibration des moteurs.**
466
 
467
- Nouveau module `picarones/measurements/calibration.py`. Tous les moteurs cibles
468
  fournissent une confidence par token ou par ligne (Tesseract `tsv`
469
  output, Pero OCR via `PageLayout`, Mistral OCR via `confidence`, Google
470
  Vision via `Word.confidence`). Ajout d'un champ
 
86
  nommées, ordre de lecture. C'est le verrou qui empêche tout l'axe B et qui
87
  limite déjà des métriques de l'axe A (Layout F1, reading order F1).
88
 
89
+ **Refonte de `picarones/domain/corpus.py`.** La classe `Document` actuelle
90
  porte `image_path`, `ground_truth: str`, `ocr_text`. La nouvelle version
91
  porte une GT structurée :
92
 
 
135
  mappeur ALTO ou un rewriter, il faut une interface plus générale dont
136
  `BaseOCREngine` devient un cas particulier.
137
 
138
+ **Création de `picarones/domain/module_protocol.py`.**
139
 
140
  ```python
141
  class ArtifactType(str, Enum):
 
442
 
443
  **A.II.1.a — Précision sur entités nommées (NER).**
444
 
445
+ Nouveau module `picarones/evaluation/metrics/ner.py`. Backends : spaCy multilingue,
446
  Stanza, modèle HIPE pour les corpus historiques. Choix paramétré par
447
  profil (`fr_core_news_lg`, `xx_ent_wiki_sm`, `hipe2022`).
448
 
 
464
 
465
  **A.II.1.b — Score de calibration des moteurs.**
466
 
467
+ Nouveau module `picarones/evaluation/metrics/calibration.py`. Tous les moteurs cibles
468
  fournissent une confidence par token ou par ligne (Tesseract `tsv`
469
  output, Pero OCR via `PageLayout`, Mistral OCR via `confidence`, Google
470
  Vision via `Word.confidence`). Ajout d'un champ
tests/architecture/test_doc_paths.py CHANGED
@@ -133,7 +133,14 @@ REPO_ROOT = Path(__file__).resolve().parents[2]
133
  # la migration de l'exemple de docstring dans ``robustness.py``
134
  # vers ``adapters.ocr.tesseract`` cassent quelques refs dans des
135
  # audits historiques (CHANGELOG, docs/audits/).
136
- BROKEN_PATHS_BASELINE = 169
 
 
 
 
 
 
 
137
 
138
  #: Patrons de fichiers de documentation à scanner.
139
  DOC_GLOBS: tuple[str, ...] = (
 
133
  # la migration de l'exemple de docstring dans ``robustness.py``
134
  # vers ``adapters.ocr.tesseract`` cassent quelques refs dans des
135
  # audits historiques (CHANGELOG, docs/audits/).
136
+ # Sprint H.9 : -7 — nettoyage massif de ~17 fichiers ``docs/`` qui
137
+ # pointaient vers les paquets supprimés (``picarones.measurements.*``
138
+ # / ``picarones.core.*`` / ``picarones.engines.*`` / ``picarones.cli.*``
139
+ # / ``picarones.web.*`` / ``picarones.report.*`` / etc.) re-pointent
140
+ # désormais vers les chemins canoniques. ``docs/migration/`` archivée
141
+ # vers ``docs/archives/migration/`` (les refs internes y restent
142
+ # intentionnellement, c'est de l'historique).
143
+ BROKEN_PATHS_BASELINE = 162
144
 
145
  #: Patrons de fichiers de documentation à scanner.
146
  DOC_GLOBS: tuple[str, ...] = (
tests/architecture/test_no_legacy_imports_in_rewrite.py CHANGED
@@ -122,7 +122,7 @@ def test_rewrite_modules_dont_import_from_legacy() -> None:
122
  1. Le code legacy importé existe en équivalent dans le rewrite
123
  → migrer l'import.
124
  2. Il n'existe pas encore → la fonctionnalité doit être inscrite
125
- au plan ``docs/migration/legacy-retirement-plan.md`` comme
126
  bloquante avant le retrait du paquet legacy concerné.
127
  """
128
  offenders: list[tuple[str, int, str]] = []
@@ -146,7 +146,7 @@ def test_rewrite_modules_dont_import_from_legacy() -> None:
146
  f"{sample}{more}\n\n"
147
  "Soit migrer l'import vers l'équivalent rewrite, soit "
148
  "inscrire la fonctionnalité manquante dans "
149
- "``docs/migration/legacy-retirement-plan.md`` comme "
150
  "bloquante.",
151
  )
152
 
 
122
  1. Le code legacy importé existe en équivalent dans le rewrite
123
  → migrer l'import.
124
  2. Il n'existe pas encore → la fonctionnalité doit être inscrite
125
+ au plan ``docs/archives/migration/legacy-retirement-plan.md`` comme
126
  bloquante avant le retrait du paquet legacy concerné.
127
  """
128
  offenders: list[tuple[str, int, str]] = []
 
146
  f"{sample}{more}\n\n"
147
  "Soit migrer l'import vers l'équivalent rewrite, soit "
148
  "inscrire la fonctionnalité manquante dans "
149
+ "``docs/archives/migration/legacy-retirement-plan.md`` comme "
150
  "bloquante.",
151
  )
152