Skip to content

feat(ml-pipeline,#18923): étape 3 -- shadow_schedule.py, cadence mensuelle répartie des rejeus en ombre - #19330

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/18923-etape3-shadow-schedule
Oct 5, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/18923-etape3-shadow-schedule

Conversation

@jsboige

@jsboige jsboige commented Oct 5, 2026

Copy link
Copy Markdown
Owner

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)

  • QUAND : first_session_of_month rend 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é.
  • DANS QUEL ORDRE, À QUEL ESPACEMENT : la marche suit la grammaire de shadow_replay.py —
    1. replay-local : toutes les locales dues en une invocation (0 appel QC) ;
    2. plan-qc : extraction au SHA gelé de toutes les QC dues (0 appel QC) ;
    3. par candidate QC : une qc-passage (MCP uniquement : pousser les fichiers, create_compile, create_backtest, attendre completed:true, read_backtest + read_backtest_chart — ≈ QC_CALLS_PER_PASS = 5 appels) puis son ingest-qc. Deux qc-passage sont espacées de --min-interval-min (défaut 10 min → 0,5 appel/min, budget 10/min) ; la garde qc_rate refuse un espacement dont le débit moyen dépasserait le budget.
  • RIEN D'AUTRE : ni registre ni CSV ne sont écrits ; shadow_replay.py et shadow/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 que passes.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_entrypoint de shadow_replay.py (étape 1, mergée) — aucune redéfinition. validate tourne 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_on puis id ; 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_for jamais dans le passé, ordre de la marche et espacement exact des slots, qc_project et 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 --json de bout en bout.
  • Sans régression sur l'organe sœur : test_shadow_replay.py 33/33.
  • Outil réel sur le registre réel (lecture seule) : validate → OK 1 candidates, 0 passes ; plan --on 2026-11-02 → 1 candidate due (mhm676, gelée 2026-10-05), marche complète plan-qc 09:17 → qc-passage 09:18 (5 appels) → ingest-qc 09:28, 0,5 appel/min pour un budget de 10/min ; git status -- shadow/ inchangé après le plan.
  • py_compile OK ; 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

…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>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Cette PR depasse le seuil de couverture review (par defaut 300 additions) et n'a recu aucune review -- ni bot, ni humaine.

Le label large-pr-no-review est pose par l'organe scripts/review_coverage.py porte par l'issue #11232. Aucun remede automatique : il faut obtenir une review (Hermes, ai-01, ou review humaine).

Le label est retire au balayage suivant (quotidien) des qu'une review arrive -- dans reviews[] ou en commentaire de verdict -- ou que le diff passe sous le seuil. Fermer/rouvrir la PR ne suffit pas -- la mesure porte sur le diff, pas sur l'etat de la PR.

Seuil, historique et exceptions : cf. docs/reference/review-coverage-threshold.md.

@jsboige

jsboige commented Oct 5, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 19330
head: 3eb48a5
complete: true
body: read
comments-reviewed: 2
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: f31777869787fb321b67c9138ab003ff6dff28477deb8172ca0375683e195ae6
diff-files: 2
diff-additions: 353
diff-deletions: 0
checks: latest-wins-green
b0: clear
scope: pass
domain: not-applicable
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 19330
organ-rc: 0
[/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.

@myia-ai-01
myia-ai-01 merged commit d61938d into main Oct 5, 2026
21 of 22 checks passed
@jsboige
jsboige deleted the feature/18923-etape3-shadow-schedule branch October 7, 2026 07:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

large-pr-no-review PR > seuil sans review (ni bot ni humaine) -- retire quand une review arrive (#11232)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants