Contexte
R/report.R manipule les internes de {pointblank} (16 champs de validation_set, extracts, classe has_intel) — c'est assumé et bien verrouillé par des tests de contrat. Mais l'audit relève quatre défauts propres au fichier :
- Mémoïsation ignorée :
datadiff_report_html() reconstruit agent + rapport même si print(res$reponse) vient de peupler le cache, et ne l'alimente pas en retour → double construction systématique. datadiff_render_report(res$reponse) couvrirait le cas nominal. Par ailleurs le fallback de datadiff_render_report (attribut cache absent) crée un env local jamais rattaché → mémoïsation silencieusement perdue.
- eval_error masqué : la garde
any(n_failed > 0, na.rm = TRUE) peut être FALSE alors que l'agent réel a échoué par eval_error (n_failed = NA) → branche synthétique choisie, extracts perdus ; et eval_error/eval_warning <- FALSE est forcé sur toutes les lignes, masquant une vraie erreur d'évaluation dans le rapport.
- Code mort : dans
build_report_agent(), le bloc else d'injection de compteurs par ligne (~11 lignes : row$n, n_passed, f_passed, warn/stop/notify…) est intégralement réécrit par le bloc vectorisé « authoritative from coverage » qui suit. Seuls la copie du template et l'extract survivent.
- Constantes dupliquées : les défauts
warn_at/stop_at = 1e-14 existent en 4 exemplaires (report.R ×3, compare_datasets_from_yaml.R) et les conventions de nommage __ok/__eq/__missing_col_/__type_mismatch_ sont redéclarées en dur dans report.R, pointblank_setup.R et coverage.R sans constante partagée — une dérive d'un seul côté casse le mapping silencieusement (le step réel n'est plus retrouvé, l'extract est perdu).
Reprex (point 1)
library(datadiff)
ref <- data.frame(id = 1:2, x = c(1, 2)); cand <- data.frame(id = 1:2, x = c(1, 3))
res <- compare_datasets_from_yaml(ref, cand, key = "id")
print(res$reponse) # construit + met en cache le rapport
system.time(datadiff_report_html(res, tempfile(fileext = ".html")))
# reconstruit tout au lieu de réutiliser le cache
Critères de succès
Contexte
R/report.Rmanipule les internes de {pointblank} (16 champs devalidation_set,extracts, classehas_intel) — c'est assumé et bien verrouillé par des tests de contrat. Mais l'audit relève quatre défauts propres au fichier :datadiff_report_html()reconstruit agent + rapport même siprint(res$reponse)vient de peupler le cache, et ne l'alimente pas en retour → double construction systématique.datadiff_render_report(res$reponse)couvrirait le cas nominal. Par ailleurs le fallback dedatadiff_render_report(attribut cache absent) crée un env local jamais rattaché → mémoïsation silencieusement perdue.any(n_failed > 0, na.rm = TRUE)peut être FALSE alors que l'agent réel a échoué pareval_error(n_failed = NA) → branche synthétique choisie, extracts perdus ; eteval_error/eval_warning <- FALSEest forcé sur toutes les lignes, masquant une vraie erreur d'évaluation dans le rapport.build_report_agent(), le bloc else d'injection de compteurs par ligne (~11 lignes :row$n,n_passed,f_passed,warn/stop/notify…) est intégralement réécrit par le bloc vectorisé « authoritative from coverage » qui suit. Seuls la copie du template et l'extract survivent.warn_at/stop_at = 1e-14existent en 4 exemplaires (report.R ×3, compare_datasets_from_yaml.R) et les conventions de nommage__ok/__eq/__missing_col_/__type_mismatch_sont redéclarées en dur dans report.R, pointblank_setup.R et coverage.R sans constante partagée — une dérive d'un seul côté casse le mapping silencieusement (le step réel n'est plus retrouvé, l'extract est perdu).Reprex (point 1)
Critères de succès
datadiff_report_html()passe pardatadiff_render_report()(lecture et alimentation du cache) ; le second appel est quasi instantané.eval_errorsur l'agent réel est propagé au rapport (pas de bascule silencieuse sur la branche synthétique, pas de forçage à FALSE) + test.build_report_agent()(comportement identique, tests verts).