feat: dp_finalizer — arbitrage Trackare vs CRH-only avec traçabilité audit

Nouveau module src/medical/dp_finalizer.py :
- 5 règles d'arbitrage (R1-R5) : CRH CONFIRMED override, Trackare corroboré,
  symptôme R* override/review, ambigu REVIEW, Z-code/R-code interdits auto-confirm
- Traçabilité : dp_trackare, dp_crh_only, dp_final sur DossierMedical
- quality_flags dict (merge sans écraser) + alertes_codage (append)

Modèles config.py :
- DPCandidate, DPSelection (NUKE-3)
- get_dp_ranker_llm_enabled(), check_adversarial_model_config()
- Champs DossierMedical : dp_trackare, dp_crh_only, dp_final, quality_flags

Intégration :
- main.py : appel finalize_dp() après vetos/GHM (individuel + fusionné)
- benchmark : finalizer dans _rebuild_and_select(), dp_final dans output

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dom
2026-02-24 17:50:07 +01:00
parent cad0dd22b1
commit c7317af447
4 changed files with 457 additions and 9 deletions

View File

@@ -560,21 +560,37 @@ def _rebuild_and_select(data: dict) -> dict:
}
selection = select_dp(dossier, synthese, config={"llm_enabled": False})
dossier.dp_selection = selection
# Finalizer DP (arbitrage Trackare vs CRH, traçabilité)
try:
from src.medical.dp_finalizer import finalize_dp
finalize_dp(dossier)
except Exception:
pass
# Utiliser dp_final si disponible, sinon dp_selection
final = dossier.dp_final or selection
# Convertir en dict compatible analyze_dp_selection
cands = [c.model_dump() for c in selection.candidates]
return {
cands = [c.model_dump() for c in final.candidates]
result = {
"dp_selection": {
"verdict": selection.verdict,
"confidence": selection.confidence,
"chosen_code": selection.chosen_code,
"chosen_term": selection.chosen_term,
"verdict": final.verdict,
"confidence": final.confidence,
"chosen_code": final.chosen_code,
"chosen_term": final.chosen_term,
"candidates": cands,
"evidence": selection.evidence,
"reason": selection.reason,
"debug_scores": selection.debug_scores,
"evidence": final.evidence,
"reason": final.reason,
"debug_scores": final.debug_scores,
}
}
if dossier.dp_final:
result["dp_final"] = dossier.dp_final.model_dump(exclude_none=True)
if dossier.quality_flags:
result["quality_flags"] = dossier.quality_flags
return result
def _run_debug_reports(