Spaces:
Sleeping
docs(sprint-H.9): archive migration plans + cleanup stale doc paths
Browse filesSprint 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 +1 -1
- docs/archives/migration/README.md +43 -0
- docs/{migration → archives/migration}/SESSION_HANDOVER.md +0 -0
- docs/{migration → archives/migration}/executor-equivalence.md +0 -0
- docs/{migration → archives/migration}/legacy-retirement-plan.md +0 -0
- docs/{migration → archives/migration}/pipeline-convergence-plan.md +0 -0
- docs/{migration → archives/migration}/regression-tolerances.md +0 -0
- docs/{migration → archives/migration}/rewrite-status-s46.md +0 -0
- docs/{migration → archives/migration}/sprint-D-audit.md +0 -0
- docs/developer/doc-consistency.md +6 -6
- docs/developer/extending-glossary.en.md +3 -3
- docs/developer/extending-glossary.md +4 -4
- docs/developer/extending-i18n.en.md +5 -5
- docs/developer/extending-i18n.md +8 -8
- docs/developer/index.en.md +1 -1
- docs/developer/index.md +9 -14
- docs/developer/module-policy.md +6 -6
- docs/explanation/architecture.md +2 -2
- docs/explanation/narrative-engine.en.md +1 -1
- docs/explanation/narrative-engine.md +8 -8
- docs/how-to/cli-workflows.md +3 -3
- docs/operations/data-retention-rgpd.md +1 -1
- docs/reference/api-stable.md +27 -27
- docs/reference/normalization-profiles.md +1 -1
- docs/reference/reproducibility-snapshots.md +2 -2
- docs/reference/views.md +2 -2
- docs/roadmap/backlog.md +4 -4
- docs/roadmap/evolution-2026.md +4 -4
- tests/architecture/test_doc_paths.py +8 -1
- tests/architecture/test_no_legacy_imports_in_rewrite.py +2 -2
|
@@ -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)
|
|
@@ -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.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -30,11 +30,11 @@ Vérifie que :
|
|
| 30 |
|
| 31 |
| Item | Source de vérité | Sens du contrat |
|
| 32 |
|---|---|---|
|
| 33 |
-
| Moteurs OCR | `picarones/adapters/
|
| 34 |
-
| Commandes CLI | `picarones/interfaces/cli/
|
| 35 |
-
| Endpoints API | `picarones/interfaces/web/
|
| 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/
|
| 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/
|
| 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 |
|
|
@@ -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/
|
| 18 |
-
- `picarones/
|
| 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/
|
| 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 |
|
|
@@ -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/
|
| 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/
|
| 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/
|
| 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/
|
| 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
|
|
@@ -15,8 +15,8 @@ This guide covers:
|
|
| 15 |
|
| 16 |
Two JSON files store all UI strings:
|
| 17 |
|
| 18 |
-
- `picarones/
|
| 19 |
-
- `picarones/
|
| 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/
|
| 61 |
with translated definitions (cf. [`extending-glossary.en.md`](extending-glossary.en.md)).
|
| 62 |
4. Add `<lang>` to the narrative templates:
|
| 63 |
-
`picarones/
|
| 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
|
|
@@ -5,14 +5,14 @@ convention de fichiers JSON par langue :
|
|
| 5 |
|
| 6 |
| Système | Fichier | Contenu |
|
| 7 |
|---------|---------|---------|
|
| 8 |
-
| Interface du rapport HTML | `picarones/
|
| 9 |
-
| Glossaire contextuel | `picarones/
|
| 10 |
-
| Templates narratifs | `picarones/
|
| 11 |
|
| 12 |
## Ajouter une nouvelle clé d'interface
|
| 13 |
|
| 14 |
-
1. Ajoutez la clé dans `picarones/
|
| 15 |
-
`picarones/
|
| 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/
|
| 33 |
-
2. Créez `picarones/
|
| 34 |
traduisez).
|
| 35 |
-
3. Créez `picarones/
|
| 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 |
|
|
@@ -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/
|
| 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__)`.
|
|
@@ -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
|
| 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/ # ~
|
| 26 |
│ ├── statistics/ # Wilcoxon, Friedman/Nemenyi, bootstrap, Pareto
|
| 27 |
-
│ ├── views/, projectors/ # EvaluationView
|
| 28 |
-
│ ├── corpus.py # Document, Corpus, GTLevel
|
| 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 |
-
│
|
| 38 |
-
|
| 39 |
-
├──
|
| 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 7 — rendu 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
|
|
@@ -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.
|
| 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.
|
| 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.
|
| 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/
|
| 127 |
-
`picarones/
|
| 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.
|
| 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) ;
|
|
@@ -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)
|
|
@@ -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.
|
| 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 |
)
|
|
@@ -6,7 +6,7 @@ la synthèse factuelle en tête du rapport.
|
|
| 6 |
## Architecture
|
| 7 |
|
| 8 |
```
|
| 9 |
-
picarones/
|
| 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.
|
| 45 |
-
from picarones.
|
| 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/
|
| 197 |
d'interface.
|
| 198 |
-
3. Ajoutez `de.yaml` dans `picarones/
|
| 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.
|
| 259 |
-
from picarones.
|
| 260 |
-
from picarones.
|
| 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 = (
|
|
@@ -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/
|
| 187 |
Click + helpers + commandes simples.
|
| 188 |
-
- [`picarones/interfaces/cli/
|
| 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).
|
|
@@ -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 |
|
|
@@ -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.
|
| 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.
|
| 13 |
-
> `picarones.
|
| 14 |
-
> `picarones.
|
| 15 |
-
> `picarones.cli.*`, `picarones.
|
| 16 |
-
> `picarones.
|
| 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.
|
| 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.
|
| 273 |
-
Quand ils changent, les shims rétrocompat dans `picarones.
|
| 274 |
reflètent ces changements.
|
| 275 |
-
- **Modules `picarones.
|
| 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.
|
| 304 |
-
from picarones.
|
| 305 |
-
from picarones.
|
| 306 |
-
from picarones.
|
| 307 |
# ... ~40 modules métriques ...
|
| 308 |
|
| 309 |
-
# Moteur narratif (déplacé vers picarones.
|
| 310 |
-
from picarones.
|
| 311 |
from picarones.domain.facts import Fact, FactType, FactImportance
|
| 312 |
-
from picarones.
|
| 313 |
|
| 314 |
-
# Plugins (déplacés vers picarones.
|
| 315 |
-
from picarones.
|
| 316 |
-
from picarones.
|
| 317 |
-
from picarones.
|
| 318 |
from picarones.importers.iiif import IIIFImporter
|
| 319 |
```
|
| 320 |
|
| 321 |
Pour les **nouvelles** intégrations, préférer les chemins canoniques :
|
| 322 |
|
| 323 |
-
- `picarones.
|
| 324 |
-
- `picarones.
|
| 325 |
-
- `picarones.
|
| 326 |
-
- `picarones.
|
| 327 |
-
- `picarones.
|
| 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
|
|
@@ -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.
|
| 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
|
|
@@ -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.
|
| 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.
|
| 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",
|
|
@@ -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.
|
| 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.
|
| 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é.
|
|
@@ -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.
|
| 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/
|
| 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/
|
| 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/
|
| 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) :
|
|
@@ -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/
|
| 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/
|
| 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/
|
| 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/
|
| 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
|
|
@@ -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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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, ...] = (
|
|
@@ -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 |
|