Repository navigation
feat(ml-pipeline,#18923): étape 3 -- shadow_schedule.py, cadence mensuelle répartie des rejeus en ombre - #19330
Conversation
…uelle repartie des rejeus en ombre Organe de decision pur : lit registre et CSV (jamais d'ecriture), rend un plan horodate du passage mensuel. Consomme les organes de l'etape 1 (due, validate, qc_entrypoint de shadow_replay.py), ne les redefinit pas. Marche : replay-local (locales dues, 0 appel QC), plan-qc (extraction au SHA gele), puis par candidate QC une qc-passage MCP (5 appels, espacee de min_interval_min, garde qc_rate <= budget flotte 10/min) et son ingest-qc. first_session_of_month rend la premiere seance deterministe (premier jour ouvre) ; determinisme complet du plan (ordre frozen_on puis id, heure explicite). Aucun cablage d'horloge : workflow .github/ ou tache planifiee reviennent au coordinateur. Tests : 10 passes (date de seance, ordre et espacement, determinisme, due-mensuelle, lecture seule, refus etat invalide et budget) ; test_shadow_replay 33/33 sans regression ; plan reel du 2026-11-02 rendu sur le registre courant (mhm676, 0,5 appel/min). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
|
Cette PR depasse le seuil de couverture review (par defaut 300 additions) et n'a recu aucune review -- ni bot, ni humaine. Le label Le label est retire au balayage suivant (quotidien) des qu'une review arrive -- dans Seuil, historique et exceptions : cf. |
|
[ADJOINT PREFLIGHT] note: MED/PO lot c451 addendum. 2 fichiers, +353/-0, lane porteuse po-2024:CoursIA. PR gate SUCCESS (post-DWELL 16:34Z, balayage OK), B.0 rc=0 OK, scope pass (2<15), domain not-applicable. READY -> merge_ready eligible. |
Grain: MED/tooling — lane myia-po-2024:CoursIA — prev: MED/refactor #19328
Étape 3 de #18923 : la cadence — un passage mensuel, réparti pour rester sous la limite d'appels MCP (10/min pour toute la flotte, un backtest à la fois, annonce dashboard avant de lancer). Nouvel organe
scripts/shadow_schedule.py: un planificateur de décision pure, sans aucune écriture du registre ou du CSV.Ce que l'organe décide (et ce qu'il ne décide pas)
first_session_of_monthrend la première séance du mois déterministe (premier jour ouvré, lundi-vendredi — un jour férié décale la vraie séance, la PR de passage note la date réellement jouée, le CSV reste la vérité).pass_date_for(today)ne planifie jamais dans le passé.shadow_replay.py—replay-local: toutes les locales dues en une invocation (0 appel QC) ;plan-qc: extraction au SHA gelé de toutes les QC dues (0 appel QC) ;create_compile,create_backtest, attendrecompleted:true,read_backtest+read_backtest_chart— ≈QC_CALLS_PER_PASS = 5appels) puis soningest-qc. Deuxqc-passagesont espacées de--min-interval-min(défaut 10 min → 0,5 appel/min, budget 10/min) ; la gardeqc_raterefuse un espacement dont le débit moyen dépasserait le budget.shadow_replay.pyetshadow/registry.json(tenus par la lane de l'étape 2, feat(shadow,#18923): gel de la 676, premiere candidate QC ; plan-qc lit le chemin depuis la racine #19250 ouverte) ne sont pas touchés. Le passage reste porté par une lane — une PR qui ne touche quepasses.csv(README §Cadence). Aucun câblage d'horloge : workflow.github/ou tâche planifiée machine reviennent au coordinateur, qui arbitrera le déclencheur.Consommation, pas duplication
Le planificateur importe
due,validate,qc_entrypointdeshadow_replay.py(étape 1, mergée) — aucune redéfinition.validatetourne avant tout plan : un état invalide est refusé (ValueError), jamais planifié. Les commandes émises reprennent la forme documentée (python scripts/shadow_replay.py --registry … --csv …,shadow/README.md).Déterminisme
Même registre, même CSV, même date → même plan. Ordre
frozen_onpuisid; heure de départ explicite (--start, défaut 09:17 Europe/Paris — hors minutes pleines), jamais l'horloge du moment.Validation (Section H)
python -m pytest scripts/tests/test_shadow_schedule.py -q→ 10 passed : date de première séance (dimanche/samedi/vendredi épinglés),pass_date_forjamais dans le passé, ordre de la marche et espacement exact des slots,qc_projectet budget par passage, déterminisme (JSON identique), due-mensuelle (déjà rejouée ce mois → exclue ; gelée le jour du passage → exclue, strict avant), lecture seule (registre byte-identique, CSV toujours absent), refus d'un état falsifié après gel, refus d'un espacement hors budget,main --jsonde bout en bout.test_shadow_replay.py33/33.validate→OK 1 candidates, 0 passes;plan --on 2026-11-02→ 1 candidate due (mhm676, gelée 2026-10-05), marche complèteplan-qc09:17 →qc-passage09:18 (5 appels) →ingest-qc09:28, 0,5 appel/min pour un budget de 10/min ;git status -- shadow/inchangé après le plan.py_compileOK ; pré-commit gitleaks/secrets Passed au commit.See #18923 (étape 3 — l'issue reste ouverte : les étapes 2 et suivantes vivent leur vie)
🤖 Generated with Claude Code