File size: 40,424 Bytes
e4838d8
f0641dd
e4838d8
 
f0641dd
416bee1
 
 
 
 
e4838d8
 
416bee1
 
 
 
 
e4838d8
 
2f5797b
e4838d8
 
 
f0641dd
 
 
 
 
e4838d8
a42c174
e4838d8
 
 
 
 
 
 
 
 
 
f0641dd
 
 
e4838d8
f0641dd
 
 
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
e4838d8
 
 
 
 
 
f0641dd
 
 
a42c174
f0641dd
 
a42c174
f0641dd
 
e4838d8
a42c174
 
 
e4838d8
 
a42c174
 
 
 
 
d5f9a91
a42c174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9011070
a42c174
 
 
 
 
 
 
 
 
 
 
f0641dd
 
 
e4838d8
f0641dd
 
 
e4838d8
 
 
 
 
 
 
f0641dd
e4838d8
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
 
 
e4838d8
 
 
 
 
 
f0641dd
 
 
e4838d8
f0641dd
 
 
e4838d8
8a02022
e4838d8
 
 
 
f0641dd
e4838d8
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
 
 
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
f0641dd
e4838d8
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
f0641dd
 
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7e28f42
e4838d8
 
 
 
 
46bb905
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
f0641dd
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
 
2f5797b
e4838d8
 
 
 
 
 
 
 
 
 
f0641dd
 
 
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0641dd
 
e4838d8
 
 
 
f0641dd
 
e4838d8
 
 
 
 
f0641dd
 
 
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
f0641dd
e4838d8
 
 
 
 
 
f0641dd
e4838d8
d0a3fab
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
 
 
 
 
 
 
f0641dd
e4838d8
f0641dd
e4838d8
f0641dd
e4838d8
 
 
 
f0641dd
 
 
e4838d8
eb547cb
e4838d8
416bee1
 
 
 
 
 
3bffe86
 
 
e4838d8
416bee1
 
 
 
 
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3bffe86
 
 
e4838d8
eb547cb
e4838d8
eb547cb
e4838d8
eb547cb
e4838d8
 
d5f9a91
416bee1
d5f9a91
416bee1
 
eb547cb
e4838d8
eb547cb
e4838d8
 
 
 
 
 
 
 
 
 
 
eb547cb
e4838d8
eb547cb
416bee1
 
 
 
 
 
 
 
 
eb547cb
e4838d8
657a5ae
e4838d8
eb547cb
416bee1
e4838d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eb547cb
 
 
e4838d8
 
 
 
 
 
 
416bee1
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
# Picarones — Spécifications fonctionnelles et techniques

> **Plateforme de banc d'essai d'OCR / HTR / VLM et de pipelines de
> post-correction pour documents patrimoniaux.**
>
> Version 0.9.0 (pré-1.0) — Mai 2026.  Politique de versionning :
> [`../explanation/versioning.md`](../explanation/versioning.md).
>
> Itération de spec **2** (révision éditoriale du document, distincte
> du numéro de version du logiciel ; mai 2026).

> **Note de lecture** : ce document décrit ce que Picarones **fait
> aujourd'hui**, dans la version `0.9.0`.  Pour les
> **non-fonctionnalités assumées** (ce que Picarones *ne fait pas et
> ne fera pas* dans la lignée `0.x` — par exemple la recommandation
> prescriptive, l'export PDF, les adapters Kraken/AWS Textract), voir
> la section §10.
>
> Pour la cartographie technique du code et les règles de
> contribution interne, voir [`CLAUDE.md`](../../CLAUDE.md). Ce document
> reste tourné « public » (vocabulaire bibliothécaire, exemples
> patrimoniaux). Les deux documents sont complémentaires, pas
> redondants.

---

## Table des matières

1. [Vision et positionnement](#1-vision-et-positionnement)
2. [Architecture en 8 couches concentriques](#2-architecture-en-8-couches-concentriques)
3. [Module 1 — Corpus et imports](#3-module-1--corpus-et-imports)
4. [Module 2 — Adaptateurs OCR / HTR](#4-module-2--adaptateurs-ocr--htr)
5. [Module 3 — Pipelines OCR+LLM et pipelines composables](#5-module-3--pipelines-ocrllm-et-pipelines-composables)
6. [Module 4 — Métriques et analyses](#6-module-4--métriques-et-analyses)
7. [Module 5 — Rapport HTML interactif](#7-module-5--rapport-html-interactif)
8. [Module 6 — Interface web et CLI](#8-module-6--interface-web-et-cli)
9. [Reproductibilité et sécurité](#9-reproductibilité-et-sécurité)
10. [Limites assumées et non-fonctionnalités](#10-limites-assumées-et-non-fonctionnalités)
11. [Roadmap d'évolution](#11-roadmap-dévolution)
12. [Migration v1 → v2 — annexe historique](#12-migration-v1--v2--annexe-historique)

---

## 1. Vision et positionnement

### 1.1 Problématique

Les équipes OCR/HTR travaillant sur des fonds patrimoniaux
(manuscrits, imprimés anciens, archives) disposent d'un paysage
hétérogène — moteurs locaux (Tesseract, Pero OCR), services cloud
(Mistral OCR, Google Vision, Azure Document Intelligence), modèles
fine-tunés maison, VLMs (GPT-4o, Claude, Mistral Large) — sans
outil unifié pour les comparer rigoureusement sur leurs propres
corpus.

Les outils existants (ocrevalUAtion, dinglehopper) sont soit
obsolètes, soit limités au CER/WER, soit non adaptés aux
spécificités des documents historiques : glyphes anciens,
ligatures, abréviations, graphies variables, pathologies d'image,
ordre de lecture multi-colonnes, structure ALTO/PAGE.

À cela s'ajoute une question de recherche émergente : **est-ce
qu'une couche de correction par LLM améliore réellement la sortie
OCR, de combien, sur quels types d'erreurs, et sans introduire
d'over-normalisation moderne ?** Aucun outil existant ne permet
de tester et mesurer cela rigoureusement.

### 1.2 Philosophie : un banc d'essai, pas un atelier

Picarones est conçu comme un **banc d'essai** :

- L'utilisateur amène son **golden dataset** annoté (paires image +
  vérité terrain). Sans VT, pas de benchmark.
- Picarones exécute les IA candidates et **mesure** l'écart à la VT.
- Picarones **classe** les résultats avec rigueur statistique.
- Picarones **n'arbitre pas le débat éditorial**. Il ne dit pas si
  un moteur diplomatique vaut mieux qu'un moteur modernisant —
  il rapporte les chiffres et laisse le chercheur, l'archiviste
  ou le paléographe trancher selon ses critères propres.

Cette philosophie est tenue jusque dans le moteur narratif
factuel : chaque phrase de la synthèse en tête du rapport est
traçable à un payload de `Fact` qui provient du JSON d'entrée
(garde-fou anti-hallucination prouvé par tests).

### 1.3 Contributions scientifiques

Au-delà de la simple agrégation de moteurs, Picarones apporte
plusieurs briques nouvelles dans l'écosystème OCR/HTR open-source :

- **Registre typé de métriques** (Sprint 34) : chaque métrique
  est enregistrée pour une jonction de types `ArtifactType`
  (TEXT/ALTO/PAGE/ENTITIES/READING_ORDER) ; un pipeline composé
  peut alors calculer automatiquement la métrique adéquate à
  chaque jonction de son DAG.
- **Interface BaseModule générique** (Sprint 33) : OCR, mappeur
  VLM→ALTO, rewriter ALTO→ALTO, classifieur d'entités texte→entités
  partagent la même API ; le runner les enchaîne sans privilégier
  un type particulier.
- **GT multi-niveaux** (Sprint 32) : un document peut porter
  simultanément une vérité terrain texte, ALTO, PAGE, entités,
  et reading order — chacune calibrée à son niveau d'évaluation.
- **Moteur narratif factuel anti-hallucination** (Sprint 19+) :
  20+ détecteurs déterministes produisent une synthèse en
  langage naturel dont chaque chiffre est traçable au payload
  d'un `Fact`. Aucune intervention LLM, garde-fou prouvé par
  test (`test_sprint23_anti_hallucination`).
- **Test multi-moteurs Friedman + Nemenyi + Critical Difference
  Diagram** (Sprint 18, Demšar 2006) : référence canonique pour
  la comparaison statistique de classifieurs, transposée à l'OCR.
- **Pareto coût / vitesse / CO₂** (Sprint 20) : positionnement
  tri-objectifs avec front explicite, table de pricing
  surchargeable.
- **Métriques philologiques transversales** (Sprints 55–60) :
  six modules couvrant l'imprimé ancien, le médiéval, les
  archives modernes (XIXᵉ–XXᵉ), avec scores éditoriaux séparés
  (préservation stricte vs équivalence diplomatique).

### 1.4 Utilisateurs cibles

| Profil | Cas d'usage typique |
|---|---|
| **Ingénieur OCR/ML** | Pipeline programmatique, métriques fines, export JSON, intégration CI/CD via `picarones run --fail-if-cer-above` |
| **Chargé de numérisation** | Rapport HTML autonome, comparaison A vs B, lecture du Pareto coût/qualité |
| **Responsable de projet** | Vue agrégée multi-corpus, analyse coût/bénéfice des APIs cloud, suivi longitudinal SQLite |
| **Chercheur en humanités numériques** | Métriques philologiques, corpus HTR-United, taxonomie d'erreurs en 10 classes, glossaire contextuel |
| **Paléographe / éditeur critique** | Diff visuel par document, bascule diplomatique / normalisé, profil philologique séparant strict et expansion |
| **DSI institutionnel** | Déploiement intranet derrière SSO, RGPD, observabilité (cf. `docs/operations/`) |

---

## 2. Architecture en 8 couches concentriques

```
domain → formats → evaluation → pipeline → adapters → app → reports_v2 → interfaces
```

**Règle de dépendance** : les imports vont uniquement de
l'extérieur vers l'intérieur (de gauche à droite dans le
diagramme).  La règle est appliquée par
`tests/architecture/test_layer_dependencies.py` qui parse
l'AST de chaque fichier et bloque toute violation au merge.

> **Note sur le legacy** : le projet est en cours de retrait
> du legacy.  Une arborescence historique
> (``picarones/{core,measurements,engines,llm,pipelines,
> report,modules}``) cohabite encore et est en train de
> disparaître phase par phase.  Cf.
> [`docs/archive/2026-migration/legacy-retirement-plan.md`](docs/archive/2026-migration/legacy-retirement-plan.md)
> pour le statut et le calendrier.  Tout nouveau code va
> dans l'arborescence canonique ; les chemins legacy
> existants sont des shims minimaux destinés à être
> supprimés.

### 2.1 `picarones/domain/` — types purs

Cercle le plus interne.  Stdlib + Pydantic uniquement, aucune
I/O, aucun framework, aucun module legacy.

| Module | Contenu |
|---|---|
| `artifacts.py` | `Artifact`, `ArtifactType` (10 types : IMAGE, RAW_TEXT, CORRECTED_TEXT, ALTO_XML, PAGE_XML, CANONICAL_DOCUMENT, ENTITIES, READING_ORDER, ALIGNMENT, CONFIDENCES) |
| `corpus.py` | `CorpusSpec` |
| `documents.py` | `DocumentRef` |
| `evaluation_spec.py` | `MetricSpec`, `EvaluationView`, `EvaluationSpec` |
| `pipeline_spec.py` | `PipelineSpec`, `PipelineStep`, `INITIAL_STEP_ID` |
| `projection_spec.py` | `ProjectionSpec` |
| `provenance.py` | `ProvenanceRecord` |
| `run_manifest.py` | `RunManifest` |
| `module_protocol.py` | `BaseModule` (ABC, voie de retrait au profit de `StepExecutor`) |
| `facts.py` | `Fact`, `FactType`, `FactImportance`, `DetectorRegistry` |
| `errors.py` | Hiérarchie d'exceptions (`PicaronesError`, `AdapterStepError`, …) |

### 2.2 `picarones/formats/` — parsing / sérialisation

ALTO 4, PAGE XML, JSON, XML utilitaires.  Stdlib + lxml +
defusedxml.  Pas de logique métier.

### 2.3 `picarones/evaluation/` — métriques et calcul

Cœur de la valeur ajoutée.  Stdlib + numpy + scipy + jiwer +
spacy + rapidfuzz.

| Sous-paquet | Contenu |
|---|---|
| `metrics/` | ~30 métriques (CER, WER, MUFI, philological, NER, calibration, taxonomy, …) |
| `statistics/` | Wilcoxon, Friedman/Nemenyi, bootstrap, Pareto, clustering, CDD |
| `views/`, `projectors/` | EvaluationView (Sprint S13+), projecteurs `AltoToText`, `PageToText`, `CanonicalToText` |
| `corpus.py` | `Document`, `Corpus`, `GTLevel`, payloads (legacy en cours de retrait) |
| `metric_registry.py`, `metric_hooks.py`, `metric_result.py` | Registres typés + hooks + dataclasses résultats |
| `pipeline.py`, `pipeline_benchmark.py`, `pipeline_comparison.py` | `PipelineRunner` legacy + orchestration corpus-wide (en cours de convergence vers `pipeline.executor`) |
| `benchmark_result.py` | `BenchmarkResult`, `EngineReport`, `DocumentResult`, sérialisation JSON |
| `engines/` | OCR engines legacy (`BaseOCREngine`-based) — temporairement avant suppression complète |
| `_diff_utils.py` | `compute_word_diff`, `compute_char_diff`, `diff_stats` |

### 2.4 `picarones/pipeline/` — orchestration canonique

`PipelineExecutor` instance-based, `StepExecutor` Protocol,
`ExecutionPlan` immuable.  Cible canonique pour le bench
d'axe B (pipelines composées).

### 2.5 `picarones/adapters/` — adapters externes

Adapters OCR / LLM / VLM consommant des libs externes
(pytesseract, mistralai, openai, anthropic, google.cloud,
azure.*, pero_ocr, ollama).  Implémentent `StepExecutor`.

| Sous-paquet | Contenu |
|---|---|
| `ocr/` | `TesseractAdapter`, `PeroOCRAdapter`, `MistralOCRAdapter`, `GoogleVisionAdapter`, `AzureDocIntelAdapter`, `PrecomputedAdapter` |
| `llm/` | `BaseLLMAdapter` + Mistral / OpenAI / Anthropic / Ollama |
| `vlm/` | Adapters VLM (zero-shot OCR via vision-language models) |
| `corpus/` | Loaders externes : IIIF, Gallica, HTR-United, HuggingFace |
| `storage/` | `ArtifactStore`, `JobStore` (S29 + S47) |
| `legacy_engines/`, `legacy_modules/` | Engines + modules legacy `BaseModule`-based (en cours de retrait, cf. Phase 7.A) |

### 2.6 `picarones/app/` — services applicatifs

`BenchmarkService`, `CorpusRunner`, `RunOrchestrator`.
Orchestrent les pipelines canoniques sur corpus.

### 2.7 `picarones/reports/` — rendu HTML / JSON / CSV

Rapport final consommant un `BenchmarkResult` ou `RunResult`.
22 renderers thématiques + 5 vues (advanced_taxonomy,
diagnostics, economics, pipeline, robustness) +
`ReportGenerator` orchestrateur + templates Jinja2 +
glossaire bilingue (25 entrées) + i18n FR/EN.

### 2.8 `picarones/interfaces/` — entrées utilisateur

CLI Click, Web FastAPI, IIIF/Gallica/eScriptorium importers
exposés en interface.

---

## 3. Module 1 — Corpus et imports

### 3.1 Formats de vérité terrain acceptés

| Format | Extension | Niveau GT | Usage typique |
|---|---|---|---|
| Texte brut | `image.gt.txt` | TEXT | Convention Tesseract, HTR-United |
| ALTO XML v4 | `.gt.alto.xml` | ALTO | Standard bibliothèques nationales, eScriptorium export |
| PAGE XML 2019 | `.gt.page.xml` | PAGE | Transkribus, OCRopus |
| Entités nommées | `.gt.entities.json` | ENTITIES | Format HIPE simplifié |
| Reading order | `.gt.reading_order.json` | READING_ORDER | Liste ordonnée de region IDs |

Le loader (`load_corpus_from_directory`) détecte automatiquement
chacun de ces niveaux à côté de l'image. Un même document peut
porter plusieurs niveaux simultanément (Sprint 32).

### 3.2 Sources d'import

#### Local
Import d'un dossier de paires image / GT. Détection automatique
du format. Filtrage des fichiers macOS `._*`.

#### IIIF
Import par URL de manifeste IIIF v2 et v3. Compatible Gallica
(BnF), Bodleian, BL, Vatican, e-codices, Europeana, et tout
entrepôt IIIF-compliant. Sélection par range de canvas.

#### HuggingFace Datasets
Recherche par filtre langue/script/époque/institution. Datasets
patrimoniaux pré-référencés (IAM, RIMES, READ-BAD, Esposalles,
HTR-United datasets). Statut : module
`extras/importers/huggingface.py` marqué expérimental
(`UserWarning` à l'import).

#### HTR-United
Listing du catalogue distant + import direct. Lecture des
métadonnées (langue, script, institution, époque). En cas
d'échec réseau ou parsing, fallback sur catalogue de démo +
émission d'un `Fact` `IMPORTER_FALLBACK_TRIGGERED` (Sprint A3).

#### Gallica (API BnF)
Recherche par cote, titre, auteur, date. Récupération des
images via API IIIF Gallica.

#### eScriptorium
Connexion à une instance distante via API. Statut
expérimental.

#### Upload ZIP via navigateur
Endpoint `POST /api/corpus/upload`. Validation Pillow
(décompression bombs), zip-slip prévenu, taille plafonnée
(`PICARONES_MAX_UPLOAD_MB`).

### 3.3 Gestion des corpus

- Corpus nommés et versionnés avec métadonnées descriptives.
- Tags : type de script, langue, siècle, institution, état de
  conservation.
- Stratification par `script_type` (Sprint 45-46) — vue stratifiée
  dans le rapport, détecteur narratif `STRATIFICATION_RECOMMENDED`
  qui invite l'utilisateur quand le corpus est hétérogène.

---

## 4. Module 2 — Adaptateurs OCR / HTR

### 4.1 Architecture des adaptateurs

Chaque moteur OCR est une classe Python qui hérite de
`BaseOCREngine` (`picarones/adapters/legacy_engines/base.py`), elle-même héritière
de `BaseModule` (Sprint 33). Une instance déclare son
`execution_mode` (`"io"` ou `"cpu"`) que le runner utilise pour
choisir entre `ThreadPoolExecutor` (cloud APIs) et
`ProcessPoolExecutor` (Tesseract, Pero).

Ajouter un nouveau moteur = créer une classe Python de ~50 lignes
qui implémente `_run_ocr(image_path) -> str` et déclare son
`execution_mode`.

### 4.2 Moteurs OCR livrés

| Moteur | Type | Mode d'exécution | Confidence native exposée ? |
|---|---|---|---|
| **Tesseract 5** | Local CLI | CPU (ProcessPool) | ✅ Sprint 47 (`image_to_data`) |
| **Pero OCR** | Local Python | CPU (ProcessPool) | ✅ Sprint 48 (`transcription_confidence` ligne) |
| **Mistral OCR** | Cloud API | IO (ThreadPool) | ✅ Sprint 49 (quand disponible côté API) |
| **Google Vision** | Cloud API | IO (ThreadPool) | ✅ Sprint 50 (`Word.confidence` en mode `DOCUMENT_TEXT_DETECTION`) |
| **Azure Doc Intelligence** | Cloud API | IO (ThreadPool) | ✅ Sprint 51 (`Word.confidence`) |

Quand un moteur expose ses confidences natives, le runner calcule
automatiquement les métriques de calibration (ECE, MCE, reliability
diagram — Sprint 39-43).

### 4.3 Robustesse runtime

- **Erreurs HTTP cloud** (4xx/5xx, timeout, body mal formé) :
  remontées dans `EngineResult.error` avec le code HTTP, jamais
  avalées silencieusement (Sprint A5 / m-10, 19 cas testés).
- **Crash isolé d'un document** : le runner continue avec les
  autres documents. Le doc en échec a `engine_error` rempli.
- **Cancel mid-run** : `cancel_event.set()` interrompt proprement.
- **Timeout par document** : configurable via paramètre
  `timeout_seconds`.

---

## 5. Module 3 — Pipelines OCR+LLM et pipelines composables

### 5.1 Pipelines OCR+LLM historiques (Sprint 3+)

L'unité de comparaison est le **concurrent** — pas forcément un
moteur seul, mais une chaîne produisant du texte à partir d'une
image.

| Mode | Description | Usage typique |
|---|---|---|
| `zero_shot` | Le LLM/VLM reçoit l'image directement et transcrit | Test si GPT-4o ou Claude peut remplacer un OCR sur des documents anciens |
| `post_correction_texte` | OCR → texte brut → LLM corrige le texte | LLM non multimodal (Llama local), grand volume |
| `post_correction_image_texte` | OCR → LLM reçoit image ET texte brut | Meilleure qualité ; le LLM voit le contexte visuel |

Les prompts sont **versionnés** dans `picarones/prompts/` (8 fichiers
FR + EN), embarqués dans le snapshot du rapport pour
reproductibilité.

### 5.2 Pipelines composables (Sprint 63+)

Au-delà des 3 modes historiques, Picarones livre une infrastructure
générique : un pipeline est une **liste d'étapes `BaseModule`**
qui produit un artefact à chaque étape (TEXT, ALTO, PAGE,
ENTITIES…) ; à chaque jonction, le runner calcule
**automatiquement** la métrique adéquate via `compute_at_junction`
(registre typé Sprint 34).

```yaml
# Spec YAML chargée par picarones pipeline run
name: ocr_then_corrector
steps:
  - name: ocr
    module: picarones.engines.tesseract.TesseractEngine
    args: { lang: "fra", psm: 6 }
  - name: post_correction
    module: my_module.MyLLMCorrector
    args: { model: "gpt-4o" }
```

`picarones pipeline compare specs.yaml --corpus ./scans --output rapport.html`
exécute N pipelines sur le même corpus et produit un rapport
comparatif. Conçu pour qu'un mainteneur tiers puisse contribuer
ses propres modules sans toucher au cœur de Picarones (cf.
`docs/developer/module-policy.md`, Sprint 97).

### 5.3 Détection d'over-normalisation LLM

Risque spécifique aux pipelines OCR+LLM : le LLM modernise à tort
des graphies historiques légitimes. Picarones mesure :

- **Modernisation lexicale** (Sprint 80) : top-N tokens GT
  systématiquement remplacés (`maistre → maître` dans 100 % des
  cas → signal exploitable).
- **Score d'absorption d'erreur** (Sprint 94) : à chaque jonction
  OCR→LLM, calcule le **taux de correction** (parmi les erreurs
  avant, combien corrigées) **et** le **taux d'introduction**
  (parmi les erreurs après, combien nouvelles). Distingue un
  module qui *corrige* d'un module qui *écrase*.
- **Delta Flesch** (Sprint 52) : sur les langues prises en
  charge, signale les LLM qui rendent le texte « trop moderne »
  par rapport à la GT.
- **Score d'ancrage** (Sprint 10) : proportion des trigrammes
  produits par le LLM qui s'ancrent dans la GT — score bas =
  hallucination probable.

---

## 6. Module 4 — Métriques et analyses

### 6.1 Catalogue exhaustif des métriques

Picarones livre **plus de 30 métriques** organisées en familles.
Pour chaque métrique : son nom, sa jonction de types, sa source,
ses limites — voir le **glossaire contextuel** intégré au rapport
HTML (25 entrées bilingues, ouvre via le `?` à côté du nom de
colonne) et `picarones/report/glossary/{fr,en}.yaml`.

#### Classique OCR/HTR

| Métrique | Jonction | Source primaire |
|---|---|---|
| CER (raw, NFC, caseless, diplomatique) | `(TEXT, TEXT)` | Levenshtein character / [jiwer](https://github.com/jitsi/jiwer) |
| WER, MER, WIL | `(TEXT, TEXT)` | jiwer |
| Bootstrap CI 95 % | dérivé | Efron (1979) |
| Distribution CER par ligne, Gini | dérivé | Sprint 10 |
| Détection hallucinations VLM (anchor score, length ratio) | dérivé | Sprint 10 |

#### Philologique (Sprints 52-60, 80, 84-85, 92-94)

| Métrique | Jonction | Cible patrimoniale |
|---|---|---|
| Couverture MUFI | `(TEXT, TEXT)` | Manuscrits médiévaux |
| Score d'expansion d'abréviations Capelli | `(TEXT, TEXT)` | Médiéval |
| Précision par bloc Unicode | `(TEXT, TEXT)` | Imprimés anciens / médiéval |
| Préservation des marqueurs typographiques de l'imprimé ancien (long-s, ligatures, tildes nasaux) | `(TEXT, TEXT)` | XVIᵉ-XVIIIᵉ |
| Marqueurs des archives modernes (titres, ordinaux, monnaies, état civil…) | `(TEXT, TEXT)` | XIXᵉ-XXᵉ |
| Préservation des numéraux romains (5 statuts) | `(TEXT, TEXT)` | Toutes périodes |
| Recherchabilité fuzzy (Levenshtein distance ≤ 2) | `(TEXT, TEXT)` | Indexation Elastic / full-text |
| Précision sur séquences numériques (dates, foliotation, monnaies) | `(TEXT, TEXT)` | Archives, économie historique |
| Modernisation lexicale (top-N tokens GT modernisés) | `(TEXT, TEXT)` | Pipelines OCR+LLM |
| Delta Flesch (FR + EN) | `(TEXT, TEXT)` | Repère VLM hallucinant du français moderne |
| Score d'absorption d'erreur par jonction | `(TEXT, TEXT)` | Pipelines composées |
| Précision sur entités nommées (HIPE) | `(ENTITIES, ENTITIES)` | Indexation prosopographique |
| Reading order F1 (ICDAR 2015) | `(READING_ORDER, READING_ORDER)` | Manuscrits glosés, journaux multi-colonnes |
| Layout F1 par type de région (IoU 0.5) | `(ALTO, ALTO)` | Texte/glose/marginalia |

#### Comparaison & décision (Sprints 18, 20, 35-37, 81, 89-92, 96)

| Métrique | Source primaire |
|---|---|
| Test multi-moteurs Friedman + post-hoc Nemenyi + CDD | Demšar (2006) |
| Test pairé Wilcoxon | Wilcoxon (1945) |
| Pareto coût / vitesse / CO₂ (multi-objectifs N dim) | Pareto (1896) |
| Divergence taxonomique inter-moteurs (Jensen-Shannon) | Lin (1991) |
| Oracle complementarity (recall borné supérieur) | Sprint 35 |
| Score de spécialisation inter-moteurs | Sprint 89 |
| Stabilité multi-runs (CV CER, accord identique) | Sprint 83 |
| Accord inter-annotateurs (Cohen κ, Krippendorff α) | Cohen (1960), Krippendorff (1970) |
| Tendance longitudinale + change-point Pettitt | Sprint 92 |
| Throughput effectif (pages/h après correction humaine 5s/erreur) | Sprint 91, HTR-United |
| Coût marginal par erreur évitée | Sprint 91 |
| Comparaison incrémentale ANOVA-like par slot | Sprint 96 |

**Note de traçabilité** : les références primaires (Demšar 2006,
Wilcoxon 1945, Efron 1979, etc.) sont citées dans les docstrings
de chaque fonction de `picarones/measurements/statistics/`.
Le glossaire contextuel relie chaque métrique à sa publication
canonique (champ `reference`).

### 6.2 Profils de normalisation

11 profils livrés (`picarones/formats/text/normalization.py`,
exposés via `/api/normalization/profiles`) : `nfc`, `caseless`,
`minimal`, `medieval_french`, `early_modern_french`,
`medieval_latin`, `medieval_english`, `early_modern_english`,
`secretary_hand`, `sans_ponctuation`, `sans_apostrophes`.

Chaque profil applique un ensemble d'équivalences diplomatiques
(ſ=s, u=v, i=j, ꝑ=per, þ=th, etc.). Un profil custom peut être
chargé depuis YAML.

**Traçabilité aux standards éditoriaux** (MUFI v4.0, TEI P5
Unicode chapter 3.4, DEAF) : prévue Sprint A12 (item B-6 du
plan de remédiation institutionnelle).

### 6.3 Taxonomie des erreurs en 10 classes

Catégorisation automatique de chaque erreur (Sprint 5) :

1. Confusion visuelle (rn/m, l/1, O/0, u/n…)
2. Erreur diacritique
3. Erreur de casse
4. Ligature non résolue
5. Abréviation non développée
6. Hapax (mot absent du lexique)
7. Segmentation (fusion / fragmentation)
8. Hors-vocabulaire
9. Lacune (texte présent en GT, absent en OCR)
10. Sur-normalisation LLM

### 6.4 Score de difficulté intrinsèque

Indicateur calculé **indépendamment des moteurs** (Sprint 7) :

- variance du CER entre tous les concurrents (si tous ratent →
  document objectivement difficile),
- métriques de qualité image,
- densité de caractères spéciaux (ligatures, abréviations,
  diacritiques),
- longueur et densité du texte.

Sépare deux questions distinctes : *« est-ce que ce moteur est
mauvais ? »* vs *« est-ce que ce document est objectivement
difficile ? »*.

---

## 7. Module 5 — Rapport HTML interactif

Le rapport est un **fichier HTML auto-portant** (Jinja2 server-side,
Chart.js vendoré inline), lisible hors-ligne, embarquant toutes
les données et visualisations.

### 7.1 Cinq vues + sections globales

#### Sections globales (en tête)

- **Synthèse narrative factuelle** (Sprint 19+) : 3-5 phrases
  produites par 20+ détecteurs déterministes. Chaque chiffre
  rendu est traçable au payload du `Fact` correspondant
  (anti-hallucination prouvé par test).
- **Critical Difference Diagram** (Sprint 18) : SVG server-side,
  Friedman + post-hoc Nemenyi.
- **Section inter-moteurs** (Sprint 37) : matrice de divergence
  taxonomique + encart oracle complementarity.
- **Front Pareto** (Sprint 20) : coût / vitesse / CO₂ avec
  toggles d'axes.
- **Section leviers d'amélioration** (Sprint 51-82) : 5 leviers
  factuels (taxonomie récupérable, concentration Pareto,
  complémentarité, modernisation lexicale, déficit projeté de
  robustesse).

#### Vue Classement (Ranking)

Tableau triable : CER (médiane par défaut depuis Sprint 44),
WER, MER, WIL, scores ligatures et diacritiques, Gini, score
d'ancrage, sur-normalisation, etc. Vue stratifiée optionnelle
par `script_type` (Sprint 45-46).

#### Vue Galerie (Gallery)

Grille de vignettes avec badge CER coloré. Filtres dynamiques
(CER > X, qualité image, type de script, longueur GT). Tri
multi-critères. Vue **« Worst lines globale »** (Sprint 72)
qui transcende les documents et liste les lignes individuelles
les plus mal transcrites.

#### Vue Document

Image originale + diff token coloré façon GitHub par moteur,
scroll synchronisé N-way. Vue spécifique OCR+LLM : triple diff
GT / sortie OCR brute / sortie après LLM.

#### Vue Analyses

Distribution CER (histogramme + densité), scatter plots
qualité image vs CER, heatmap de confusion de caractères,
diagrammes de fiabilité (calibration ECE/MCE — Sprint 43),
graphiques de bootstrap CI 95 %, profil philologique par moteur
(Sprint 62), throughput effectif (Sprint 91), tendances
longitudinales (Sprint 92), DAG de pipeline composée (Sprint 95),
etc.

#### Vue Caractères

Matrice de confusion Unicode interactive, tableau des
caractères les plus souvent manqués par chaque moteur, CER par
bloc Unicode (Sprint 55), analyse des ligatures.

### 7.2 Panneaux latéraux

- **Glossaire contextuel** (Sprint 21) : `?` à côté de chaque
  en-tête de colonne ; clic ouvre un panneau avec définition,
  ce qu'on mesure, usage, limites, référence primaire (25
  entrées bilingues).
- **Mode avancé** (Sprint 21) : choix de colonnes visibles,
  filtres par strate, opt-in score composite personnel
  (curseurs à 0 par défaut, formule visible, warning explicite
  « il n'existe pas de pondération universellement valide »),
  toggle palette daltonien-friendly (Sprint A7), URL stateful.

### 7.3 Exports

| Format | Statut |
|---|---|
| HTML autonome | ✅ Livré |
| CSV (vue courante avec filtres) | ✅ Livré |
| JSON (BenchmarkResult complet) | ✅ Livré |
| Snapshot reproductibilité (versions, commit, lock) | ✅ Sprint 27 |
| Lazy images (rapport HTML + dossier `report-assets/`) | ✅ Sprint A5 / M-16 |
| PDF | ❌ Non livré (cf. §10) |
| ALTO XML / PAGE XML / images annotées | ❌ Non livré (cf. §10) |

### 7.4 Accessibilité

Conformité WCAG 2.1 niveau AA (cf.
[`docs/operations/accessibility.md`](../operations/accessibility.md)) :

- Skip-to-content link (WCAG 2.4.1).
- `role="img"` + `aria-label` + table de données jumelle
  pour chaque graphique Chart.js (WCAG 1.1.1).
- `scope="col"` sur tous les `<th>`.
- Palette par défaut Okabe-Ito (daltonien-friendly), toggle vers
  l'ancienne palette via panneau Avancé ou `?palette=classic`.
- Bilinguisme intégral (skip-link, ARIA labels, captions des
  tables jumelles).
- Audit RGAA externe planifié Sprint A15.

---

## 8. Module 6 — Interface web et CLI

### 8.1 Interface web FastAPI

- Configuration de benchmark : sélection corpus, moteurs,
  normalisation.
- Streaming SSE de la progression en temps réel (`Last-Event-ID`
  reconnexion supportée — Sprint 26).
- Persistance des jobs en SQLite (mode WAL, thread-safe), reprise
  des jobs orphelins au boot.
- Upload ZIP depuis le navigateur.
- Imports HTR-United / HuggingFace via formulaire.
- Bilingue FR/EN.
- Healthcheck minimal `/health` (Sprint A4 / M-3).
- Token CSRF (`/api/csrf/token`) + middleware (Sprint A4 / B-11)
  activable via `PICARONES_CSRF_REQUIRED=1` pour les déploiements
  institutionnels derrière SSO.

### 8.2 Interface en ligne de commande (Click)

15 commandes :

```bash
picarones run         # benchmark
picarones report      # rapport HTML depuis JSON
picarones demo        # rapport démo synthétique
picarones compare     # compare deux runs JSON, exit-code 2 si régression
picarones diagnose    # workflow bench + leviers + recommandations factuelles
picarones economics   # workflow bench + throughput + coût projeté
picarones edition     # workflow bench + métriques philologiques
picarones pipeline    # run/compare pipelines composées YAML
picarones import      # IIIF / HF / HTR-United
picarones serve       # interface web locale
picarones history     # historique longitudinal SQLite
picarones robustness  # courbes CER vs dégradation
picarones engines     # liste les moteurs disponibles
picarones metrics     # CER/WER entre deux fichiers texte
picarones info        # version + system info
```

Toutes les commandes supportent `--help`. Workflows pré-câblés
(`diagnose`, `economics`, `edition`) sont des combinaisons
canoniques pour les profils utilisateurs typiques.

### 8.3 Intégration CI/CD

- Mode headless (`--no-progress`).
- Output JSON machine-readable.
- Exit code 2 sur `picarones compare` si régression CER détectée.
- Workflow GitHub Actions `perf_regression.yml` (Sprint A5 /
  M-14) — cron hebdomadaire + sur PR touchant le runner.

---

## 9. Reproductibilité et sécurité

### 9.1 Snapshots de reproductibilité (Sprint 27)

Chaque rapport HTML embarque un dict `report_data["snapshots"]`
qui contient :

- **pricing** — YAML brut intégral de `picarones/data/pricing.yaml`
  utilisé.
- **glossary** — entrées du glossaire effectivement référencées.
- **normalization** — profil sérialisé.
- **environment** — version Picarones, Python, plateforme, commit
  git, paquets installés (top 200).

Procédure complète de re-jeu d'un benchmark à 5 ans d'écart :
[`docs/reference/reproducibility-snapshots.md`](docs/reference/reproducibility-snapshots.md)
(Sprint A8 / M-12).

### 9.2 Reproductibilité des builds

- Lock files `requirements.lock` + `requirements-dev.lock`
  générés via `uv pip compile` (Sprint A8).
- Image Docker épinglée à un patch précis via `ARG PYTHON_BASE_IMAGE`
  (rotation trimestrielle).
- Release pipeline GitHub Actions (Sprint A9) : tag `v*.*.*` →
  PyPI via OIDC trust + ghcr.io multi-arch + GitHub Release auto.

### 9.3 Sécurité institutionnelle

- **Mode public** (`PICARONES_PUBLIC_MODE=1`) : refuse les moteurs
  cloud mutualisés et les pipelines LLM facturés à la clef serveur.
- **CSRF** double-submit (`PICARONES_CSRF_REQUIRED=1`) — Sprint A4.
- **XML défendu** par `defusedxml` partout (XXE / Billion Laughs).
- **Zip-slip prévenu** par `Path(member.filename).name`.
- **Validation Pillow** systématique (CVE bombes de
  décompression).
- **Rate limiting** par IP + sémaphore de jobs concurrents.
- **CSP + en-têtes durcis** (X-Content-Type-Options,
  Referrer-Policy).

Voir [`SECURITY.md`](SECURITY.md) pour la procédure complète.

### 9.4 RGPD et rétention

Politique documentée dans
[`docs/operations/data-retention-rgpd.md`](docs/operations/data-retention-rgpd.md)
(Sprint A11 / M-8). Purge automatique des uploads anciens
configurable via `PICARONES_UPLOAD_RETENTION_DAYS=7` par défaut.

---

## 10. Limites assumées et non-fonctionnalités

Cette section décrit explicitement **ce que Picarones ne fait pas
et ne fera pas dans la lignée `0.x`**.  Plusieurs items étaient
promis dans une itération antérieure de cette spec (SPECS v1, mars
2025) — leur abandon est un choix éditorial documenté ci-dessous,
pas un oubli.  Les mentions « v1.0 », « v1.1 », « v1.2 » dans les
items ci-dessous renvoient à la **roadmap historique** de cette
spec, pas à des versions logicielles publiées.

<!-- specs-check: known-abandoned-start -->

> Toutes les fonctionnalités listées ci-dessous étaient promises ou
> évoquées dans SPECS v1 (itération de spec) et sont **explicitement
> abandonnées, non implémentées ou reportées** dans l'itération de
> spec actuelle (qui couvre le logiciel `0.9.0`).  Le test
> ``tests/docs/test_specs_consistency.py`` détecte cette section
> comme la déclaration officielle des non-fonctionnalités du projet.

### 10.1 Adapters OCR non livrés

- **Kraken** : prévu v1.0 dans SPECS v1, jamais implémenté. Choix :
  ouverture en plugins externes via la politique de modules
  contribués (Sprint 97), pas un adapter intégré au cœur. Un
  utilisateur peut écrire son `KrakenEngine(BaseOCREngine)` et
  l'exécuter via les pipelines composables.
- **AWS Textract** : prévu v1.1, abandonné. Pas de DPA Amazon
  signé, et le périmètre patrimonial est mieux servi par les
  trois clouds déjà intégrés (Mistral OCR, Google Vision, Azure
  DI).
- **Calamari** : prévu v1.1, abandonné. Maintenance d'un adapter
  par moteur ≈ 50 PJ/an ; mieux vaut concentrer sur les 5 adapters
  livrés et ouvrir Calamari en plugin externe.
- **OCRopus4** : prévu v1.2, abandonné — projet historique en
  fin de vie.
- **Moteur custom YAML** (`type: cli` / `type: api`) : prévu en
  SPECS v1.0, abandonné. **Refondu en pipelines composables**
  (Sprint 63-70) qui permettent de brancher n'importe quel module
  via une spec YAML — plus puissant que la déclaration d'engine
  custom imaginée à l'origine.

### 10.2 Exports non livrés

- **Export PDF** du rapport. CSV + JSON + HTML autonome couvrent
  les usages observés. Reportable sur demande utilisateur si
  besoin tracé.
- **Export ALTO XML** des sorties OCR.
- **Export PAGE XML** des sorties OCR.
- **Export images annotées** (PNG avec zones d'erreur surlignées).

### 10.3 Fonctionnalités explicitement abandonnées

- **Recommandation automatique** « quel concurrent pour quel
  usage ». Promise dans SPECS v1 §7.1, **abandonnée** au profit
  du moteur narratif factuel (Sprint 19) et de la philosophie
  « Picarones mesure et classe — il ne tranche pas ». Les leviers
  d'amélioration (Sprint 51-82) restent factuels.
- **Score de consensus / vote majoritaire / ensemble** : Picarones
  livre l'**oracle borné supérieur** (Sprint 35) et le score de
  spécialisation inter-moteurs (Sprint 89) — observations
  factuelles. Pas de mécanisme de vote actif intégré ; au
  chercheur de combiner les sorties s'il le décide.
- **Clustering automatique k-means des erreurs**. Remplacé par
  la taxonomie discrète (Sprint 5) + co-occurrence Jaccard
  (Sprint 75) + heatmap intra-doc (Sprint 76).
- **Annotations inline du paléographe exportées en JSON**. Non
  implémentées.
- **Badge SVG de qualité OCR pour CI**. `picarones compare` avec
  exit code 2 sur régression couvre l'usage CI ; un badge SVG
  reste nice-to-have, non priorisé.
- **Dataset de référence embarqué de 100 documents
  patrimoniaux**. Picarones est volontairement un **banc d'essai
  sur votre golden dataset** — le 100-doc corpus de référence
  imaginé en SPECS v1 §3.3 entrerait en concurrence avec les
  corpus institutionnels existants (HTR-United, Esposalles,
  IAM, RIMES, READ-BAD) et en fragmenterait l'écosystème. Les
  5 documents synthétiques de Sprint A5 (`tests/fixtures/reference_corpus/`)
  servent uniquement à l'anti-régression CER en CI, pas à la
  valeur scientifique.

### 10.4 Fonctionnalités scientifiques planifiées

À livrer dans des sprints futurs :

- **CITATION.cff + DOI Zenodo + papier JOSS** (Sprint A12 du
  plan institutionnel) — débloque la citation académique propre.
- **Traçabilité des profils de normalisation aux standards
  éditoriaux** (MUFI v4.0, TEI P5, DEAF) — Sprint A12.
- **Citations primaires des méthodes statistiques** dans les
  docstrings (Demšar 2006, Wilcoxon 1945, Efron 1979) —
  Sprint A12.

<!-- specs-check: known-abandoned-end -->

---

## 11. Roadmap d'évolution

Trois documents complémentaires pilotent l'évolution :

- [`CHANGELOG.md`](CHANGELOG.md) — historique sprint par sprint,
  format Keep a Changelog.
- [`docs/roadmap/backlog.md`](docs/roadmap/backlog.md) — backlog
  vivant des chantiers post-`0.9.0`.
- [`docs/archive/`](docs/archive/) — audits institutionnels,
  plans de remédiation pré-rewrite, roadmap historique
  (`2026-roadmap/evolution.md`), changelog pré-rewrite.

L'**état du plan institutionnel** au 2 mai 2026 :

| Phase | Sprints | Statut |
|---|---|---|
| Phase 0 — Garde-fous CI | A1, A2 | ✅ Terminée |
| Phase 1 — Hygiène architecturale | A3 | ✅ Terminée |
| Phase 2 — Robustesse runtime | A4, A5 | ✅ Terminée |
| Phase 3 — Accessibilité | A6, A7 | ✅ Terminée |
| Phase 4 — Reproductibilité ops | A8, A9 | ✅ Terminée |
| Phase 5 — Gouvernance | A10, A11 | ✅ Terminée |
| Phase 7 — Refonte doc produit | A13, **A14 (ce document)** | ✅ Terminée |
| Phase 6 — Publication scientifique | A12 | ⏳ Planifiée |
| Phase 8 — Validation externe | A15 | ⏳ Planifiée (calendrier externe) |

---

## 12. Migration des itérations de spec (v1 → v2) — annexe historique

> Cette section trace l'évolution **éditoriale du document de
> spécification** entre son itération 1 (SPECS v1, mars 2025) et
> son itération 2 (le présent document).  Les indices « v1.0 »,
> « v1.1 » dans la colonne de gauche désignent la **roadmap**
> historique de SPECS v1, pas des versions logicielles publiées.
> Pour la politique de versionning du logiciel,
> voir [`../explanation/versioning.md`](../explanation/versioning.md).

Pour les lecteurs qui avaient pris connaissance de SPECS v1.0
(mars 2025) ou de l'Addendum Sprints 16-30, voici la table de
migration des promesses changées :

| SPECS v1 disait | SPECS itération 2 documente | Raison |
|---|---|---|
| Adapter Kraken (priorité v1.0) | Ouvert en plugin externe | Politique modules contribués Sprint 97 ; concentration sur 5 adapters cœur. |
| Adapter AWS Textract (v1.1) | Abandonné | Pas de DPA, périmètre couvert par 3 clouds existants. |
| Adapter Calamari (v1.1) | Abandonné | Maintenance par adapter ≈ 50 PJ/an ; mieux servi en plugin externe. |
| Adapter OCRopus4 (v1.2) | Abandonné | Projet historique en fin de vie. |
| Moteur custom YAML | Refondu en pipelines composables | Sprint 63-70 livre une infrastructure plus puissante. |
| Recommandation automatique | Remplacée par moteur narratif factuel | Pivot philosophique vers la neutralité éditoriale. |
| Export PDF | Abandonné | CSV + JSON + HTML couvrent les usages. |
| Export ALTO/PAGE/images annotées | Abandonné | Idem. |
| `picarones estimate` (preview coût) | Remplacé par vue Pareto post hoc | Sprint 20 livre la même information dans le rapport. |
| Score consensus / k-means | Remplacé par oracle borné + taxonomie discrète + Jaccard | Sprint 35, 5, 75 — équivalence fonctionnelle, formalisme différent. |
| Annotations inline JSON | Abandonné | Pas de demande utilisateur observée. |
| Badge SVG qualité OCR | Abandonné | `picarones compare` exit code 2 couvre la CI. |
| Dataset 100 docs embarqué | Abandonné | Banc d'essai sur votre golden dataset, pas un dataset de référence. |
| Prompt latin | Pas livré | Reportable sur demande. |

À l'inverse, **~25 modules majeurs ajoutés depuis Sprint 30** sont
documentés dans la nouvelle SPECS aux §6 (NER, reading order F1,
layout F1, recherchabilité fuzzy, séquences numériques, 6 modules
philologiques transversaux, narrative engine, Friedman+Nemenyi+CDD,
Pareto, glossaire, métriques inter-moteurs, absorption d'erreur,
pipelines composables, registre typé, audit modules, comparaison
de runs, stratification, calibration, longitudinal, throughput
effectif, etc.) — invisibles dans SPECS v1.

---

*Picarones est conçu pour devenir une référence open-source
d'évaluation OCR/HTR dans le champ patrimonial — métriques
adaptées aux documents historiques, pipelines composables,
intégration des standards bibliothéconomiques (IIIF, ALTO XML,
PAGE XML, HTR-United, eScriptorium, Gallica), rapport interactif
exportable, snapshot de reproductibilité.*

*Dernière mise à jour : 23 mai 2026 (repositionnement SemVer pré-1.0,
couvre logiciel `0.9.0`).*