Skip to content

Runbook (r1 — for review)

Runbook opérateur du diagnostic s18 replay-fidelity (S09). Comment le déclencher, lire le verdict, et dépanner. Réalise la règle pré-enregistrée du plan r4 + architecture r2. Statut : pré-implémentation — les noms de DAG/params sont la cible de l'archi (à figer à l'impl).

1. Quoi & quand le lancer

Quoi : vérifie, indépendamment d'un run diagnostic, (A) que le replay s18 est déterministe (cross-process, même seed) et (B) qu'il correspond au f1_buy canonique de la prod, à epsilon près. Rend un verdict qui nomme la cause (instabilité / gap logique / artefact d'environnement).

Quand : - pour lever l'astérisque A6 sur un verdict diagnostic basé s18 (dont S05/s43) ; - comme précondition au passage de skip_phase_a=true en défaut ; - en nightly (surveillance de fidélité) une fois stabilisé.

Deux jobs distincts (cadences différentes — archi #4) : 1. D0 — diagnostic__s18_eps_prod : caractérise ε_prod (rare ; seulement au changement d'image prod). 2. Verdict — diagnostic__s18_replay_fidelity : le check de fidélité par cellule (à la demande / nightly).

2. Prérequis (à vérifier AVANT le trigger)

Prérequis Vérification Si KO
Provenance canonique persistée (P0) finetune_results (ou table annexe) porte, pour la cellule de référence : build_sha, instance_type, versions features/libs INFEASIBLE-until-schema — la persistance de provenance ship d'abord (archi #2). Sans elle : P0 = unverifiableINCONCLUSIVE_TOOLING partout
ε_prod mesuré + frais le store ε_prod a une valeur pour le SHA image prod courant lancer D0 (diagnostic__s18_eps_prod) d'abord. Sinon : verdict INCONCLUSIVE_TOOLING reason=epsilon_prod_unmeasured
Canonique présent query_canonical_from_pg retourne une ligne pour (crypto, fold-3) INCONCLUSIVE_TOOLING reason=canonical_absent
Deploy à jour Deploy to Scaleway K8s SUCCESS sur le SHA qui contient le module s18-replay-fidelity attendre le deploy (~10 min post-merge)
DAG synchronisé diagnostic__s18_replay_fidelity visible dans l'UI + bannière build=<sha> (ADR-92) attendre la sync DAG-repo (~7 min)

2bis. La BARRIÈRE de validité (avant un verdict décisionnel)

Le verdict décisionnel (FIDELITY_OK / CANONICAL_DIVERGENCE) est gaté tant que ces trois ne sont pas vrais (mirror du gate coût de s43). Le smoke (machinerie) peut tourner sans.

  1. Provenance P0 disponible des deux côtés (replay et canonique) — sinon P0 unverifiable.
  2. ε_prod mesuré sous la config réelle prod (un-capped), clé = SHA image prod courant.
  3. Config déterministe replay posée au bon moment (archi §2bis) — PYTHONHASHSEED + thread caps au spawn ; flags LightGBM au train. Un replay « cru épinglé mais pas épinglé » fausse H1.

3. Déclenchement

3.A — D0 diagnostic__s18_eps_prod (rare, si ε_prod stale)

{
    "crypto_group": "defi_top5",
    "fold_id": 3,
    "n_runs": 10,
    "prod_config": true,
    "tolerance": "0.95/0.95"
}
- prod_config=true → re-runs sous la config réelle prod (un-capped) — pas §3.C. - Écrit ε_prod (borne de tolérance unilatérale) keyé par le SHA image prod dans le store. - Pod dédié (un-capped) — ne pas co-scheduler avec le verdict job.

3.B — Verdict diagnostic__s18_replay_fidelity

{
    "crypto_group": "defi_top5",
    "fold_id": 3,
    "cells": "all",
    "parallel_replays": false
}
- cells=all → les 5 cellules (classification de cause ; 1 cellule = smoke/H1 wiring). - parallel_replays → A∥B (≈2× CPU, moitié wall-clock) vs séquentiel (1 CPU). Aucun impact déterminisme (cappé) — choix sizing/latence (archi §8bis). - Lit ε_prod du store (par SHA image prod) ; ne le re-mesure jamais.

4. Catalogue des verdicts

Verdict cause / reason Sens
FIDELITY_OK P0 parité + H1 PASS + \|replay−canonique\| ≤ ε. Replay indiscernable du canonique.
NON_DETERMINISTIC cause=numeric_residue H1 FAIL mais det_delta ≤ ε_num → résidu numérique sous config épinglée (pas une vraie instabilité).
NON_DETERMINISTIC cause=real_instability H1 FAIL, det_delta > ε_num → vraie instabilité (seed/ordre/fenêtre/threads).
CANONICAL_DIVERGENCE cause=logic_fidelity_gap H1 PASS + P0 equal + > εvrai gap de fidélité (env contrôlé).
CANONICAL_DIVERGENCE cause=env_parity_gap H1 PASS + P0 differs + > ε → divergence attribuée à l'env/version, pas à la logique.
INCONCLUSIVE_TOOLING reason=replay_error replay ERROR / NaN.
INCONCLUSIVE_TOOLING reason=canonical_absent pas de canonique en PG.
INCONCLUSIVE_TOOLING reason=epsilon_prod_unmeasured ε_prod non mesuré pour le SHA prod courant → lancer D0.
INCONCLUSIVE_TOOLING reason=env_parity_unverified P0 unverifiable (dimension non enregistrable) → corriger la provenance.

Désambiguïsation clé : logic_fidelity_gap (le replay est infidèle) vs env_parity_gap (les environnements diffèrent — re-générer le canonique sous image parité avant de conclure à l'infidélité). L'ordre de décision est H1 → P0 → H2 : une divergence sous P0≠equal n'est jamais un gap logique.

5. Lire la sortie + decision routing

Output (artefact JSON + event=s18_replay_verdict) : verdict, cause/reason, cell, det_delta, canon_delta, epsilon, ε_num, ε_prod + eps_prod_image_sha, parity_state, parity_dims, provenance replay et canonique, canonical_run_id (schéma complet : archi §6).

Verdict Action
FIDELITY_OK (sur la surface couverte) lever A6 pour cette surface ; autoriser skip_phase_a=true par défaut seulement dessus
NON_DETERMINISTIC (real_instability) corriger seed/ordre/fenêtre/threads avant tout claim de fidélité ; A6 reste
NON_DETERMINISTIC (numeric_residue) résidu sous config épinglée → enquêter libs/SIMD ; pas une instabilité de logique
CANONICAL_DIVERGENCE (logic_fidelity_gap) diagnostiquer la cause (carte de contrôle _replay_cell) ; borne les verdicts s18 (dont S05) ; feeder D2/EK
CANONICAL_DIVERGENCE (env_parity_gap) re-générer le canonique sous une image parité (ou matcher l'env) — pas un fix de logique
INCONCLUSIVE_TOOLING corriger la cause reason (§4) + relancer

Prior (plan §1) : vu A6 (deltas 0.1–0.3 ≫ ε), l'issue attendue est CANONICAL_DIVERGENCE — H1 est un prérequis rapide pour écarter « c'est du bruit ». L'effort va à la carte de surface de contrôle de _replay_cell (env / ordre LdP / fenêtre / version artefact).

6. Observabilité (Loki)

Event Quand Sévérité
s18_replay_determinism status=PASS\|FAIL\|ERROR abs_delta_runs=… chaque cellule (zéro trou) info / warn
s18_replay_determinism_cause cause=… sur H1 FAIL warn (lisible sans parser l'artefact)
s18_replay_divergence abs_delta=… parity_state=… sur le chemin H2 info / warn
s18_replay_verdict verdict=… cause=… reason=… tout verdict info

Requête : loki-query skill (event=s18_replay_verdict, fenêtre du run). Le verdict JSON est aussi dans artifact_dir.

7. Troubleshooting

Symptôme Cause probable Action
INCONCLUSIVE_TOOLING reason=epsilon_prod_unmeasured partout D0 jamais lancé pour le SHA prod courant lancer diagnostic__s18_eps_prod (§3.A)
INCONCLUSIVE_TOOLING reason=env_parity_unverified partout provenance canonique absente du schéma (archi #2) schema first ; ne pas forcer
NON_DETERMINISTIC systématique avec det_delta minuscule config §3.C non posée au spawn (numpy importé avant les caps) vérifier l'injection env au spawn (archi §2bis), pas dans le worker
une cellule manque, les autres OK échec partiel de pod cette cellule = INCONCLUSIVE_TOOLING ; relancer la cellule (pas de collapse silencieux du pool)
verdict émis mais provenance canonique vide dans l'artefact query_canonical_from_pg ne surface pas les colonnes P0 corriger la requête/le schéma (archi #2)

8. Réplication

Le verdict réel n'est pas un test CI (plan §8 / test-strategy §12). Pour rejouer : déclencher §3.B sur la cellule, lire s18_replay_verdict + l'artefact JSON. Pour rejouer la caractérisation ε_prod : §3.A (N≥10, prod_config). Toute valeur décisionnelle (ε_num, ε_prod, seuils) est dans le plan r4.