Claude commited on
Commit
c067b8b
·
unverified ·
1 Parent(s): 2e7d5a9

feat(report): Phase 21B — dispatch Engines/Diagnostics (3 charts + 6 sections legacy)

Browse files

Deuxième commit Phase 21 : déplace les charts d'erreur/calibration et
les sections legacy sémantiquement liées au diagnostic moteur.

Déplacés vers engines_diagnostics.html :
Charts :
- chart-taxonomy — taxonomie d'erreurs par moteur
- chart-reliability — courbes de fiabilité (calibration)
- error-clusters-container — clustering des patterns d'erreurs
Sections HTML (toutes conditionnelles, adaptatives) :
- readability_html — delta Flesch (A.II.2)
- advanced_taxonomy_view_html — vue thématique composite
- diagnostics_view_html — vue thématique composite homonyme
- rare_token_recall_html — Sprint câblage modules test-only
- taxonomy_cooccurrence_html — Sprint câblage modules test-only
- taxonomy_intra_doc_html — Sprint câblage modules test-only

Laissés intacts dans view_analyses.html (futurs commits) :
- chart-cer-doc, chart-quality-cer, pareto-chart → Commit C
- marginal_cost_html (cross-dimensional) → Commit C → Crosses
- view_results_html → Phase 23
- corr-matrix interactif JS → Commit D (suppression)

Tests :
- 10 nouveaux tests paramétrés (TestPhase21BDispatch) : 3 canvas + 6
sections + 1 anti-confusion marginal_cost.
- Anti-theater validé par 2 sabotages distincts (canvas rename +
conditional wiring rename).
- test_template_uses_three_views mis à jour : advanced_taxonomy +
diagnostics dans engines_diagnostics.html (et non plus view_analyses).

i18n :
- Nouvelle clé h_readability ajoutée FR + EN (parité 636/636).
- Toutes les autres clés (h_taxonomy, h_reliability, h_clusters, notes)
préexistaient — pas de duplication.

Convention HTML :
- <section class="card xer-chart-card" aria-labelledby="..."> aligné
sur engines_table.html et engines_stability.html.
- Pas de classe CSS inventée. Pas d'inline style hex.

https://claude.ai/code/session_01WYDbfkhKPeBZ15BTP4e9Ye

picarones/reports/html/templates/view_analyses.html CHANGED
@@ -35,32 +35,6 @@
35
  </div>
36
  </div>
37
 
38
- <div class="chart-card" style="grid-column:1/-1">
39
- <h3 data-i18n="h_taxonomy">Taxonomie des erreurs par moteur</h3>
40
- <div class="chart-canvas-wrap" style="max-height:300px">
41
- <canvas id="chart-taxonomy" role="img" aria-label="Taxonomie d'erreurs par moteur" data-a11y-label="Taxonomie d'erreurs par moteur"></canvas>
42
- </div>
43
- <div style="font-size:.72rem;color:var(--text-muted);margin-top:.4rem" data-i18n="taxonomy_note">
44
- Distribution des classes d'erreurs (classes 1–9 de la taxonomie Picarones).
45
- </div>
46
- </div>
47
-
48
- <div class="chart-card" style="grid-column:1/-1">
49
- <h3 data-i18n="h_reliability">Courbes de fiabilité</h3>
50
- <div class="chart-canvas-wrap" style="max-height:300px">
51
- <canvas id="chart-reliability" role="img" aria-label="Diagramme de fiabilité (calibration)" data-a11y-label="Diagramme de fiabilité (calibration)"></canvas>
52
- </div>
53
- <div style="font-size:.72rem;color:var(--text-muted);margin-top:.4rem" data-i18n="reliability_note">
54
- Pour les X% documents les plus faciles (triés par CER croissant), quel est le CER moyen cumulé ?
55
- Une courbe basse = moteur performant même sur les documents faciles.
56
- </div>
57
- </div>
58
-
59
- <div class="chart-card" style="grid-column:1/-1">
60
- <h3 data-i18n="h_clusters">Clustering des patterns d'erreurs</h3>
61
- <div id="error-clusters-container"></div>
62
- </div>
63
-
64
  <div class="chart-card pareto-card" style="grid-column:1/-1">
65
  <h3 data-i18n="h_pareto">Compromis qualité / coût</h3>
66
  <div class="pareto-toolbar" role="group" aria-label="Axe d'analyse Pareto">
@@ -108,46 +82,6 @@
108
  {{ view_results_html | safe }}
109
  {% endif %}
110
 
111
- {# A.II.2 — lisibilité (delta Flesch). Pas encore migrée vers
112
- une vue XerOCR — conservée le temps qu'on décide de son
113
- emplacement (Engines/Diagnostics ou Crosses). #}
114
- {% if readability_html %}
115
- <div class="chart-card" style="grid-column:1/-1">
116
- {{ readability_html | safe }}
117
- </div>
118
- {% endif %}
119
-
120
- {# Vues thématiques composées : seules sources de leur contenu —
121
- à migrer plus tard vers la nouvelle IA. #}
122
- {% if advanced_taxonomy_view_html %}
123
- <div class="chart-card" style="grid-column:1/-1">
124
- {{ advanced_taxonomy_view_html | safe }}
125
- </div>
126
- {% endif %}
127
- {% if diagnostics_view_html %}
128
- <div class="chart-card" style="grid-column:1/-1">
129
- {{ diagnostics_view_html | safe }}
130
- </div>
131
- {% endif %}
132
-
133
- <!-- Sprint « câblage des modules test-only » (mai 2026) :
134
- 4 sections issues de ``report_data.extra_metrics``.
135
- Adaptive : ne s'affichent que si le calcul a remonté du signal. -->
136
- {% if rare_token_recall_html %}
137
- <div class="chart-card" style="grid-column:1/-1">
138
- {{ rare_token_recall_html | safe }}
139
- </div>
140
- {% endif %}
141
- {% if taxonomy_cooccurrence_html %}
142
- <div class="chart-card" style="grid-column:1/-1">
143
- {{ taxonomy_cooccurrence_html | safe }}
144
- </div>
145
- {% endif %}
146
- {% if taxonomy_intra_doc_html %}
147
- <div class="chart-card" style="grid-column:1/-1">
148
- {{ taxonomy_intra_doc_html | safe }}
149
- </div>
150
- {% endif %}
151
  {% if marginal_cost_html %}
152
  <div class="chart-card" style="grid-column:1/-1">
153
  {{ marginal_cost_html | safe }}
 
35
  </div>
36
  </div>
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  <div class="chart-card pareto-card" style="grid-column:1/-1">
39
  <h3 data-i18n="h_pareto">Compromis qualité / coût</h3>
40
  <div class="pareto-toolbar" role="group" aria-label="Axe d'analyse Pareto">
 
82
  {{ view_results_html | safe }}
83
  {% endif %}
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  {% if marginal_cost_html %}
86
  <div class="chart-card" style="grid-column:1/-1">
87
  {{ marginal_cost_html | safe }}
picarones/reports/html/templates/views/engines_diagnostics.html CHANGED
@@ -5,9 +5,28 @@
5
  # si rien n'a de signal, info-message pédagogique qui liste les
6
  # leviers de déblocage de chaque section.
7
  #
 
 
 
 
 
 
 
 
8
  # Variables consommées (injectées par generator.py / section_registry) :
9
  # - ``engines_diagnostics_section_html`` — composite legacy (7 sections)
10
  # - ``engines_correlation_matrix_html`` — matrice corrélation (migré HTML)
 
 
 
 
 
 
 
 
 
 
 
11
  #}
12
  {{ engines_diagnostics_section_html | safe }}
13
 
@@ -18,3 +37,74 @@
18
  {% if engines_confusion_heatmap_html %}
19
  {{ engines_confusion_heatmap_html | safe }}
20
  {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  # si rien n'a de signal, info-message pédagogique qui liste les
6
  # leviers de déblocage de chaque section.
7
  #
8
+ # Phase 21B dispatch — ajoute 3 charts Chart.js et 6 sections HTML
9
+ # qui vivaient dans view_analyses.html :
10
+ # Charts : taxonomy, reliability, error-clusters
11
+ # Vues thématiques : readability, advanced_taxonomy, diagnostics
12
+ # Extra metrics : rare_token_recall, taxonomy_cooccurrence,
13
+ # taxonomy_intra_doc
14
+ # (marginal_cost reste pour Crosses — cross-dimensional cost/quality.)
15
+ #
16
  # Variables consommées (injectées par generator.py / section_registry) :
17
  # - ``engines_diagnostics_section_html`` — composite legacy (7 sections)
18
  # - ``engines_correlation_matrix_html`` — matrice corrélation (migré HTML)
19
+ # - ``engines_confusion_heatmap_html`` — heatmap confusion unicode
20
+ # - ``readability_html`` — delta Flesch (A.II.2)
21
+ # - ``advanced_taxonomy_view_html`` — vue thématique composite
22
+ # - ``diagnostics_view_html`` — vue thématique composite
23
+ # - ``rare_token_recall_html`` — Sprint câblage modules
24
+ # - ``taxonomy_cooccurrence_html`` — Sprint câblage modules
25
+ # - ``taxonomy_intra_doc_html`` — Sprint câblage modules
26
+ # Charts Chart.js (construits par buildCharts()) :
27
+ # - ``chart-taxonomy`` — taxonomie d'erreurs par moteur
28
+ # - ``chart-reliability`` — courbes de fiabilité (calibration)
29
+ # - ``error-clusters-container`` — clustering patterns d'erreurs
30
  #}
31
  {{ engines_diagnostics_section_html | safe }}
32
 
 
37
  {% if engines_confusion_heatmap_html %}
38
  {{ engines_confusion_heatmap_html | safe }}
39
  {% endif %}
40
+
41
+ <section class="card xer-chart-card" aria-labelledby="engines-taxonomy-title"
42
+ style="margin-top:1.25rem">
43
+ <h3 id="engines-taxonomy-title" data-i18n="h_taxonomy">Taxonomie des erreurs par moteur</h3>
44
+ <p data-i18n="taxonomy_note">
45
+ Distribution des classes d'erreurs (classes 1–9 de la taxonomie Picarones).
46
+ </p>
47
+ <div class="chart-canvas-wrap" style="max-height:300px">
48
+ <canvas id="chart-taxonomy" role="img"
49
+ aria-label="Taxonomie d'erreurs par moteur"
50
+ data-a11y-label="Taxonomie d'erreurs par moteur"></canvas>
51
+ </div>
52
+ </section>
53
+
54
+ <section class="card xer-chart-card" aria-labelledby="engines-reliability-title"
55
+ style="margin-top:1.25rem">
56
+ <h3 id="engines-reliability-title" data-i18n="h_reliability">Courbes de fiabilité</h3>
57
+ <p data-i18n="reliability_note">
58
+ Pour les X% documents les plus faciles (triés par CER croissant), quel est le CER moyen cumulé ?
59
+ Une courbe basse = moteur performant même sur les documents faciles.
60
+ </p>
61
+ <div class="chart-canvas-wrap" style="max-height:300px">
62
+ <canvas id="chart-reliability" role="img"
63
+ aria-label="Diagramme de fiabilité (calibration)"
64
+ data-a11y-label="Diagramme de fiabilité (calibration)"></canvas>
65
+ </div>
66
+ </section>
67
+
68
+ <section class="card xer-chart-card" aria-labelledby="engines-clusters-title"
69
+ style="margin-top:1.25rem">
70
+ <h3 id="engines-clusters-title" data-i18n="h_clusters">Clustering des patterns d'erreurs</h3>
71
+ <div id="error-clusters-container"></div>
72
+ </section>
73
+
74
+ {% if readability_html %}
75
+ <section class="card xer-chart-card" aria-labelledby="engines-readability-title"
76
+ style="margin-top:1.25rem">
77
+ <h3 id="engines-readability-title" data-i18n="h_readability">Lisibilité (delta Flesch)</h3>
78
+ {{ readability_html | safe }}
79
+ </section>
80
+ {% endif %}
81
+
82
+ {% if advanced_taxonomy_view_html %}
83
+ <section class="card xer-chart-card" style="margin-top:1.25rem">
84
+ {{ advanced_taxonomy_view_html | safe }}
85
+ </section>
86
+ {% endif %}
87
+
88
+ {% if diagnostics_view_html %}
89
+ <section class="card xer-chart-card" style="margin-top:1.25rem">
90
+ {{ diagnostics_view_html | safe }}
91
+ </section>
92
+ {% endif %}
93
+
94
+ {% if rare_token_recall_html %}
95
+ <section class="card xer-chart-card" style="margin-top:1.25rem">
96
+ {{ rare_token_recall_html | safe }}
97
+ </section>
98
+ {% endif %}
99
+
100
+ {% if taxonomy_cooccurrence_html %}
101
+ <section class="card xer-chart-card" style="margin-top:1.25rem">
102
+ {{ taxonomy_cooccurrence_html | safe }}
103
+ </section>
104
+ {% endif %}
105
+
106
+ {% if taxonomy_intra_doc_html %}
107
+ <section class="card xer-chart-card" style="margin-top:1.25rem">
108
+ {{ taxonomy_intra_doc_html | safe }}
109
+ </section>
110
+ {% endif %}
picarones/reports/i18n/en.json CHANGED
@@ -243,6 +243,7 @@
243
  "h_radar": "Engine Profile (radar)",
244
  "h_ranking": "Engine Ranking",
245
  "h_ratio_anchor": "Length Ratio vs Anchor Score",
 
246
  "h_reliability": "Reliability Curves",
247
  "h_taxonomy": "Error Taxonomy by Engine",
248
  "h_venn": "Shared / Exclusive Errors (Venn)",
 
243
  "h_radar": "Engine Profile (radar)",
244
  "h_ranking": "Engine Ranking",
245
  "h_ratio_anchor": "Length Ratio vs Anchor Score",
246
+ "h_readability": "Readability (Flesch delta)",
247
  "h_reliability": "Reliability Curves",
248
  "h_taxonomy": "Error Taxonomy by Engine",
249
  "h_venn": "Shared / Exclusive Errors (Venn)",
picarones/reports/i18n/fr.json CHANGED
@@ -243,6 +243,7 @@
243
  "h_radar": "Profil des moteurs (radar)",
244
  "h_ranking": "Classement des moteurs",
245
  "h_ratio_anchor": "Ratio longueur vs ancrage",
 
246
  "h_reliability": "Courbes de fiabilité",
247
  "h_taxonomy": "Taxonomie des erreurs par moteur",
248
  "h_venn": "Erreurs communes / exclusives (Venn)",
 
243
  "h_radar": "Profil des moteurs (radar)",
244
  "h_ranking": "Classement des moteurs",
245
  "h_ratio_anchor": "Ratio longueur vs ancrage",
246
+ "h_readability": "Lisibilité (delta Flesch)",
247
  "h_reliability": "Courbes de fiabilité",
248
  "h_taxonomy": "Taxonomie des erreurs par moteur",
249
  "h_venn": "Erreurs communes / exclusives (Venn)",
tests/reports/test_engines_diagnostics_view.py CHANGED
@@ -315,3 +315,46 @@ class TestDiagnosticsTemplate:
315
  def test_template_consumes_section_html(self) -> None:
316
  text = DIAG_TEMPLATE.read_text(encoding="utf-8")
317
  assert "engines_diagnostics_section_html" in text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  def test_template_consumes_section_html(self) -> None:
316
  text = DIAG_TEMPLATE.read_text(encoding="utf-8")
317
  assert "engines_diagnostics_section_html" in text
318
+
319
+
320
+ class TestPhase21BDispatch:
321
+ """Phase 21B — vérifie le dispatch des 3 charts Chart.js et 6 sections
322
+ HTML legacy depuis view_analyses.html vers engines_diagnostics.html.
323
+
324
+ Anti-theater : un retrait silencieux d'un élément déplacé fait
325
+ échouer le test correspondant.
326
+ """
327
+
328
+ @pytest.fixture(scope="class")
329
+ def diag_src(self) -> str:
330
+ return DIAG_TEMPLATE.read_text(encoding="utf-8")
331
+
332
+ @pytest.mark.parametrize("canvas_id", [
333
+ "chart-taxonomy",
334
+ "chart-reliability",
335
+ "error-clusters-container",
336
+ ])
337
+ def test_chart_canvas_present(self, diag_src: str, canvas_id: str) -> None:
338
+ assert f'id="{canvas_id}"' in diag_src, (
339
+ f"Canvas/container {canvas_id!r} doit être dans engines_diagnostics.html "
340
+ "(Phase 21B dispatch depuis view_analyses.html)"
341
+ )
342
+
343
+ @pytest.mark.parametrize("section_var", [
344
+ "readability_html",
345
+ "advanced_taxonomy_view_html",
346
+ "diagnostics_view_html",
347
+ "rare_token_recall_html",
348
+ "taxonomy_cooccurrence_html",
349
+ "taxonomy_intra_doc_html",
350
+ ])
351
+ def test_legacy_section_wired(self, diag_src: str, section_var: str) -> None:
352
+ assert f"{{% if {section_var} %}}" in diag_src, (
353
+ f"Section {section_var!r} doit être câblée (conditionnelle) "
354
+ "dans engines_diagnostics.html"
355
+ )
356
+
357
+ def test_marginal_cost_not_in_diagnostics(self, diag_src: str) -> None:
358
+ """marginal_cost_html va dans Crosses (cross-dimensional
359
+ cost/quality), pas dans Diagnostics — anti-confusion."""
360
+ assert "{% if marginal_cost_html %}" not in diag_src
tests/reports/test_views.py CHANGED
@@ -378,12 +378,14 @@ class TestGeneratorWiring:
378
 
379
  def test_template_uses_three_views(self):
380
  """Les 3 vues thématiques sont câblées dans leur destination
381
- XerOCR sémantique (Phase 21 — dispatch depuis view_analyses).
382
-
383
- - economics_view_html → Engines/Tableau (throughput rejoint le
384
- tableau de référence par moteur).
385
- - advanced_taxonomy_view_html / diagnostics_view_html → encore
386
- dans view_analyses.html en attendant leur dispatch.
 
 
387
  """
388
  from pathlib import Path
389
 
@@ -391,12 +393,16 @@ class TestGeneratorWiring:
391
  Path(__file__).parent.parent.parent
392
  / "picarones" / "reports" / "html" / "templates"
393
  )
394
- analyses_src = (templates_dir / "view_analyses.html").read_text(encoding="utf-8")
395
  engines_table_src = (templates_dir / "views" / "engines_table.html").read_text(encoding="utf-8")
 
396
 
397
  assert "{% if economics_view_html %}" in engines_table_src, (
398
  "economics_view_html doit être câblée dans engines_table.html "
399
  "(Phase 21 dispatch — throughput va avec le tableau moteurs)"
400
  )
401
- assert "{% if advanced_taxonomy_view_html %}" in analyses_src
402
- assert "{% if diagnostics_view_html %}" in analyses_src
 
 
 
 
 
378
 
379
  def test_template_uses_three_views(self):
380
  """Les 3 vues thématiques sont câblées dans leur destination
381
+ XerOCR sémantique (Phase 21 — dispatch depuis view_analyses) :
382
+
383
+ - economics_view_html → Engines/Tableau (throughput rejoint
384
+ le tableau de référence par moteur).
385
+ - advanced_taxonomy_view_html → Engines/Diagnostics (extends the
386
+ basic taxonomy chart).
387
+ - diagnostics_view_html → Engines/Diagnostics (composite
388
+ thématique homonyme).
389
  """
390
  from pathlib import Path
391
 
 
393
  Path(__file__).parent.parent.parent
394
  / "picarones" / "reports" / "html" / "templates"
395
  )
 
396
  engines_table_src = (templates_dir / "views" / "engines_table.html").read_text(encoding="utf-8")
397
+ engines_diag_src = (templates_dir / "views" / "engines_diagnostics.html").read_text(encoding="utf-8")
398
 
399
  assert "{% if economics_view_html %}" in engines_table_src, (
400
  "economics_view_html doit être câblée dans engines_table.html "
401
  "(Phase 21 dispatch — throughput va avec le tableau moteurs)"
402
  )
403
+ assert "{% if advanced_taxonomy_view_html %}" in engines_diag_src, (
404
+ "advanced_taxonomy_view_html doit être câblée dans engines_diagnostics.html"
405
+ )
406
+ assert "{% if diagnostics_view_html %}" in engines_diag_src, (
407
+ "diagnostics_view_html doit être câblée dans engines_diagnostics.html"
408
+ )