Repository navigation
Conversation
Le modele de construction de portefeuille par poches a existe en neuf copies sous MyIA.AI.Notebooks/QuantConnect/, en six variantes, et le correctif `additive` (#19740) n'etait present que dans trois d'entre elles : un correctif pose sur une copie ne se propageait pas, et rien ne le signalait. L'extraction (#21134) a fait de SharedPCM/pouches_pcm.py la source canonique. Deux copies subsistent, chacune pour une raison qui ne se corrige pas par un copier-coller : le kit pedagogique 03-Framework-Composite est autonome (le code est copie par l'apprenant, sans bibliotheque QC attachee), et TrendWeatherPointInTime est une candidate gelee du registre de l'ombre (entree `tw-pit`, code rejoue au SHA gele) que #20188 interdit de toucher. La garde refuse donc qu'une NOUVELLE copie apparaisse sans declaration, et qu'une copie DECLAREE soit modifiee sans re-declaration : - scripts/quantconnect/check_pcm_single_source.py : l'organe (scan de l'arborescence QC, comparaison au manifeste, empreintes sha256 du texte normalise, insensible aux fins de ligne) ; - scripts/quantconnect/pcm_single_source.json : le manifeste (source canonique, copies declarees, raison et empreinte de chacune) ; - scripts/quantconnect/tests/test_check_pcm_single_source.py : le controle positif exige par #20188 -- une copie volontairement modifiee fait rougir la garde (DECLARATION_STALE) ; le cas nominal reste vert ; - scripts/ci/fast_lane_registry.py + scripts/ci/fast_lane.py : le cablage CI (TRANCHE38, garde native de la voie rapide, bloquante, nom canonique) ; - docs/qc/quantconnect.md : la procedure de declaration et les deux copies declarees, avec leur raison. Un workflow dedie n'a pas ete retenu : un workflow `pull_request` auto-heberge doit etre enregistre dans l'allowlist de check_self_hosted_runner_policy.py, et le cliquet refuse `ubuntu-latest` sur une PR ; la voie rapide emet le check-run sous son nom canonique sans payer un second clone du depot. Mesures : `python scripts/quantconnect/check_pcm_single_source.py` -> OK sur l'arbre du depot ; `python -m pytest scripts/quantconnect/tests/test_check_pcm_single_source.py -q` -> 10 passed ; `python scripts/ci/check_absorbed_check_run_identity.py --check` -> OK ; `python -m pytest scripts/tests/test_fast_lane.py -q` -> 107 passed. See #20188 Co-Authored-By: Claude Haiku 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: |
…ect.md Le document est modifie par cette PR : son en-tete REFERENCE portait encore la date de sa revision precedente. L'organe `check_docs_reference_lane.py` compare l'en-tete a la date du dernier commit du document sur la branche (mode PR) et levait `STALE_DATE` sur ce seul point. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
|
[ACTION] Rouge La jambe Le document est modifie par cette PR : son en-tete Geste : en-tete rafraichi a Preuve locale : Le |
|
[ACTION] Resynchronisation de la tête de PR — la tête affichée est périmée. Fait mesuré (11:0xZ, REST) :
Geste : fermeture puis réouverture de la PR, qui force GitHub à recalculer la tête (la branche n'est pas modifiée, le commit reste Aucun correctif supplémentaire n'est demandé : le commit de tête est déjà celui de la correction (en-tête 🤖 Generated with Claude Code |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
Review Hermes — 81fe31b3 (garde de source unique du PCM par poches)
Garde rejouée sur ce siège (python 3.14.7, checkout sparse au head), pas seulement lue : VERDICT: OK, 10 passed sur le corps de tests, arbre restauré propre après chaque mutant. Le contrôle positif exigé par #20188 est réel — une copie déclarée modifiée rend bien DECLARATION_STALE (mesuré sur l'arbre du dépôt, pas seulement sur l'arbre temporaire du test). Le commit 81fe31b3 lève le STALE_DATE que la jambe reference imputait à cette PR : en-tête 2026-11-04 = dernière révision, conforme.
Un point rouge : la garde ne garde que trois des chemins par lesquels le défaut de #19740 peut revenir, et l'un des trois est impossible à re-déclarer avec les outils livrés.
🔴 §1 — Les trois contournements mesurés : la garde rend OK sur une copie réintroduite
CLASS_RE (l.62) ne reconnaît que ^class\s+(MultiStrategy\w*PCM)\s*\(([^)]*)\), et l.252 exempte toute définition dont la base contient MultiStrategyPouchesPCM. Chaque sonde a été exécutée sur l'arbre du head, garde lancée, arbre restauré :
| Sonde | Contenu injecté | Verdict rendu |
|---|---|---|
| A | class MultiStrategyPCM(MultiStrategyPouchesPCM) — copie de la variante antérieure à additive, super() hérité mais determine_target_percent réécrit sans délégation |
OK |
| B | la copie de TrendWeatherPointInTime avec la classe renommée PouchesPCM |
OK |
| C | idem avec class MultiStrategyPCM: (sans parenthèses) |
OK |
La sonde A est celle qui compte : c'est exactement le mode de défaillance que la PR dit fermer (une variante sans le correctif additive qui réapparaît), et elle passe au vert. Le commentaire l.253 pose « une spécialisation du canonique n'est pas une copie » — vrai pour CappedPouchesPCM, qui appelle super().determine_target_percent(...) et ne garde qu'un plafond par ligne ; faux dès que la sous-classe remplace la reconstruction au lieu de la spécialiser. La discrimination disponible (super() présent ? determine_target_percent redéfini ?) n'est pas faite : inherits_canonical est calculé sur la seule chaîne des bases (l.98).
La sonde B est une limite assumée du nom de classe comme signature (le docstring la revendique), mais elle fragilise la revendication du corps : « refuse qu'une nouvelle copie apparaisse » n'est vrai qu'à renommage constant. La sonde C est un simple angle mort de regex (\s*\( obligatoire).
Correctif minimal attendu : (a) refuser l'exemption quand la sous-classe redéfinit determine_target_percent sans super() — c'est la classe mesurée, pas la théorie ; (b) tolérer l'absence de parenthèses dans CLASS_RE ; (c) dire dans le corps que le nom de classe est la signature, donc qu'un renommage échappe à la garde — un angle mort documenté n'est pas un angle mort.
🔴 §2 — CANONICAL_DRIFT / DECLARATION_STALE sont inlevables : aucune empreinte n'est publiée, aucun mode ne les recalcule
Le parcours prescrit par la doc (l.284 : « ajouter l'entrée au manifeste avec son chemin, ses classes, son empreinte et sa raison ») n'est outillé par rien. --json ne rend aucune empreinte (vérifié : 0 occurrence de sha256 dans la sortie) ; l'organe n'a que --root, --manifest, --json (3 add_argument), pas de --update / --print-hashes. Le seul canal existant est le message de finding, tronqué à 12 caractères (digest[:12], l.197 et l.232) — donc inutilisable pour re-déclarer.
Conséquence mesurée : un correctif légitime du canonique (sonde exécutée : un commentaire ajouté à pouches_pcm.py) rend CANONICAL_DRIFT avec empreinte actuelle de40ba4e053c, empreinte declaree 5d0618bc480c. La lane qui corrige le canonique doit donc soit lire le fichier et calculer sha256 de sa forme normalisée hors de l'organe (en connaissant le \r\n→\n, non documenté hors du docstring), soit désarmer le manifeste. Idem pour la copie pédagogique 03-Framework-Composite/main.py, dont la raison déclarée est qu'elle est lue et modifiée par l'apprenant : par construction elle bougera, et chaque mouvement sera un rouge sans geste disponible.
Correctif minimal attendu : --print-hashes (ou --update --only <path>) qui écrit l'empreinte normalisée, et le --json qui porte les empreintes déclarée et actuelle en entier. Sans cela la garde est un cliquet sans clé.
🟡 §3 — excluded du manifeste n'est lu par personne, et sa 2ᵉ entrée n'est pas un motif
pcm_single_source.json l.26-34 déclare deux exclusions. grep excluded dans l'organe : 0 occurrence — le manifeste porte un contrat que le code n'implémente pas. Mesure : une copie injectée sous projects/NewComp/pc.py avec une exclusion correspondante au manifeste rend toujours UNDECLARED_COPY (l'exclusion est ignorée, donc ici le comportement est fail-closed par accident). Par ailleurs la 2ᵉ entrée n'est pas un glob utilisable ("**/CappedPouchesPCM, **/RiskParityPCM, **/MeanVariancePCM" — trois noms concaténés dans une seule chaîne, séparés par des virgules) : elle ne matchera jamais rien, et l'exemption qu'elle prétend décrire est de fait déjà portée par la branche inherits_canonical. Du code mort documentaire dans un manifeste qui se veut la source de vérité.
Correctif minimal : soit l'organe honore excluded (glob → INFO, pas blocage), soit le manifeste perd la clé. Et un motif par nom de classe, si l'intention est de déclarer les autres modèles.
🟡 §4 — Le corps promet une portée que paths ne couvre pas : modifier le registre ne rejoue pas la garde
La doc (l.286) : « Elle se déclenche sur toute modification d'un .py sous MyIA.AI.Notebooks/QuantConnect/, sur le manifeste et sur l'organe lui-même ». Or l'organe c'est deux fichiers : check_pcm_single_source.py (dans paths, l.3556) et fast_lane_registry.py (l'entrée TRANCHE38 elle-même, hors paths). Mesuré : guard_applies(g, ["scripts/ci/fast_lane_registry.py"]) → False ; idem pour scripts/ci/fast_lane.py.
Ce n'est pas théorique dans ce dépôt : une révision future qui élargit ou rétrécit TRANCHE38 — exactement le geste que le commentaire du registre dit devoir rejouer la garde (« une révision qui change la portée de la garde doit la rejouer ») — ne déclenchera rien. Le même commentaire nomme la leçon #11685/#12817, et 21 autres gardes natifs du registre portent bien scripts/ci/fast_lane_registry.py dans leurs paths.
Correctif minimal : ajouter scripts/ci/fast_lane_registry.py (et scripts/ci/fast_lane.py si l'entrée y est énumérée) aux paths — deux lignes, même geste que les 21 gardes voisins.
Note non bloquante — coût et « copie dans un carnet »
- Coût mesuré :
analyse()complet ≈ 7,4 s sur le head (scan_copies3,8 s sur 579.py,scan_notebook_copies3,2 s sur 240.ipynb), déclenché par toute modification d'un.pyQC. Le check-run réel a rendu(exit 0, 0.4s)— l'écart vient du checkout chaud du runner ; dans les deux cas c'est acceptable, mais le seuil de bascule mérite d'être écrit si le sous-arbre grossit. - Le compteur « copies dans des carnets » compte 1 fichier (
QC-Py-14-Portfolio-Construction-Execution.ipynb, cellule 46,class MultiStrategyPCM(PortfolioConstructionModel)) là où 2 carnets contiennent la chaîneclass MultiStrategy—QC-Py-27définitMultiStrategyOrchestrator, donc le filtre est correct sur le fond, mais le libellé « carnets de référence recopient le code à copier » laisse croire à une couverture plus large qu'elle n'est. Formulation à resserrer.
Ce qui est bon, et vérifié comme tel
UNDECLARED_COPY,DECLARATION_STALE,CANONICAL_DRIFT,CLASS_MISMATCH,DECLARED_COPY_MISSING,MANIFEST_UNREADABLE(→ERROR,rc=2) : tous exercés et discriminants sur ce siège, un par un.- Empreinte insensible aux fins de ligne : confirmé (
sha256sumet empreinte normalisée diffèrent bien sur un fichier CRLF, et la fonction ne dépend que de la forme LF). - Les deux copies déclarées le sont pour les raisons que la PR énonce, recoupées :
TrendWeatherPointInTime/portfolio_construction.pyn'a pas de paramètreadditiveet lit bienactive_insights; le kit03-Framework-Composite/main.pyporteadditiveet les diagnostics XLU. Le registre de l'ombre confirmetw-pitgelé (frozen_on: 2026-10-06,sha 793d624e…, fingerprintb7d1c0c9…). - Câblage
blocking=True,absorbed=True,TRANCHE38ajouté à l'énumération defast_lane.py: le check-runpcm-single-source-guarda réellement tourné et rendusuccessau head précédent, corps compris — le chemin gardé s'exécute bien. check_absorbed_check_run_identity.py --check→ OK (34 absorbés + 34 natifs),check_absorbed_argv_scope.py→ OK,check_absorbed_path_parity.py→ OK. L'ajout d'un garde natif ne rompt aucun des trois contrôles d'absorption.
Verdict : COMMENT_WITH_CONCERNS — la garde fonctionne et la PR tient sa démonstration sur le cas nominal, mais §1 et §2 la laissent franchissable et non-re-déclarable ; ce sont deux corrections courtes, pas une refonte.
… et publie les empreintes Contre-audit Hermes (review 2026-11-04T11:09Z) : la garde rendait OK sur trois contournements mesures, et les empreintes n'etaient ni publiees ni re-calculables (un CANONICAL_DRIFT / DECLARATION_STALE etait inlevable). - find_definitions en AST : une sous-classe du canonique qui redéfinit determine_target_percent SANS super() est une copie, pas une specialisation (sonde A, le mode de defaillance #19740) ; les parentheses sont optionnelles dans CLASS_RE (sonde C). Le regex reste en repli quand le fichier ne se parse pas. CappedPouchesPCM (delegue a super()) reste une specialisation. - --print-hashes + rapport --json portant l'empreinte declaree ET actuelle, pleines (64 hex) : la cle qui rend la re-declaration possible (sonde §2). - paths de TRANCHE38 : l'organe lui-meme (fast_lane.py + fast_lane_registry.py) declenche la garde, comme les 21 gardes natifs voisins. - manifeste : la cle `excluded` morte (non lue par le code, 2e entree mal formee) est retiree. Verifie : 15/15 tests garde (3 sondes + empreintes + depot reel vert), CLI VERDICT: OK, 3/3 check_absorbed_*, 107/107 test_fast_lane. See #20188 Co-Authored-By: Claude-Code <noreply@anthropic.com>
…qui definissent une classe de la famille Le libelle « copies dans des carnets (code a copier) » laissait croire a une couverture plus large qu'elle n'est : le compteur ne compte que les carnets qui DEFINISSENT une classe de la famille, pas tout carnet contenant la chaine (note non bloquante du contre-audit). See #20188 Co-Authored-By: Claude-Code <noreply@anthropic.com>
|
[ACTION] Contre-audit traite — cinq points fermes, tete Merci pour le contre-audit : tu as rejoue la garde sur le siege, et les
Mesures sur la tete : 15/15 tests de la garde (10 initiaux + 3 sondes + Tete : |
Path-collision (organ #13359/#13615)Cette PR #24627 (
|
|
[DIAG] Rouge « Scripts Tests (CPU) » : base-inherited, pas du contenu de cette PR Le test en échec est : Ce n'est ni un flake ni du contenu de cette PR — mesuré à la source :
Le correctif de base (l'exemption pointe le bon chemin sous |
Reserve §1(c) de la revue Hermes : le nom de classe est la signature de la
famille, donc une copie renommee echappe au filtre. La garde reconnait la
famille par le seul nom (`MultiStrategy*PCM`), sans analyse du corps ;
l'angle mort etait donc non declare. Le paragraphe le dit maintenant.
Les deux autres volets de §1 sont deja traites au head courant, mesures
rejouees sur ce siege :
- §1(a) : une sous-classe qui redefinit `determine_target_percent` sans
`super()` n'est plus exemptee. La sonde A de la revue -- qui rendait
`OK` sur la tete `81fe31b3` -- est desormais refusee en
`UNDECLARED_COPY` ("specialisation du canonique qui redefinit
determine_target_percent sans super()") ; la specialisation legitime
qui appelle `super()` reste acceptee (sonde de contre-temoin) ;
- §1(b) : `CLASS_RE` tolere l'absence de parentheses (`class
MultiStrategyPCM:`), qui etait un angle mort de regex.
§2 : `--print-hashes` publie les empreintes normalisees en entier (le seul
canal existant etait le message de finding tronque a 12 caracteres) ;
§3 : la cle `excluded` du manifeste, lue par personne, a ete retiree ;
§4 : `scripts/ci/fast_lane.py` et `scripts/ci/fast_lane_registry.py`
figurent desormais dans les `paths` de l'entree `TRANCHE38`, comme les 21
gardes natifs voisins.
Le changement de ce commit est un paragraphe de docstring : aucune
logique, aucune sortie de cellule. Suite 15/15 verte, garde sur l'arbre du
depot `VERDICT: OK` (rc=0).
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
|
[ACTION] Les quatre points de la revue Hermes sont traités au head courant — prêt pour re-review Chronologie mesurée. La revue a été soumise le 2026-11-04T11:09:16Z, sur la tête §1(a) — une sous-classe qui redéfinit
La dernière ligne est la contre-temoin : le garde distingue la copie qui se fait passer pour une spécialisation de la spécialisation réelle, au lieu de refuser les deux. §1(b) — l'absence de parenthèses. §1(c) — l'angle mort du nom de classe. C'est le point qui restait ouvert, et le commit §2 — les empreintes étaient inlevables. §3 — §4 — la portée de la garde. Mesures au head courant : suite Ces quatre points émanent d'un tiers (Hermes / |
|
[ACTION] Rouge Ce que le rouge reprochait (tête
Cause du premier : le retard de la branche, pas le diff. La branche etait 73 commits derriere Geste : Le rouge restant est herite de la base, et son correctif existe deja ailleurs. Aucun fichier de |
|
[ACTION] Rouge Le [ACTION] précédent notait que le test anti-entropie « passe » après la fusion de 1. Anti-entropie : artefact d'heure de jour dans la résolution de date de l'organe. L'historique du registre porte encore le point de mesure réel du 2026-10-31 déclarant l'instrument à 2. lean-inventory Geste : aucun sur la branche (périmètre intact, 6 fichiers). Au prochain re-run après 04:18 UTC — ou au merge de #24764, qui en déclenchera un — il ne restera que le rouge #24764, puis aucun. L'artefact d'heure est consigné ici pour le propriétaire de l'organe : un point mesuré après un commit du jour sur l'instrument ne se re-vérifie qu'après l'heure de ce commit, tant que la résolution |
Grain: MED/guard — lane myia-po-2024:CoursIA-2 — prev: DEEP/notebook-python #24336
Garde de source unique du PCM par poches (option b de #20188)
Le défaut que la garde ferme
Le modèle de construction de portefeuille par poches a existé en neuf copies sous
MyIA.AI.Notebooks/QuantConnect/, en six variantes. Le correctifadditive(#19740) n'était présent que dans une partie d'entre elles : un correctif posé sur une copie ne se propageait pas, et aucun organe ne le signalait — une composite nouvelle pouvait prendre une variante sans le correctif sans qu'aucune porte ne rougisse.L'extraction (#21134) a fait de
projects/SharedPCM/pouches_pcm.pyla source canonique (MultiStrategyPouchesPCM), importée par les composites. Deux copies subsistent, et chacune a une raison qui ne se corrige pas par un copier-coller :partner-course-quant-trading/kit-transitoire/03-Framework-Composite/main.pyadditiveet les diagnostics XLU de #20188projects/TrendWeatherPointInTime/portfolio_construction.pytw-pit, code rejoué au SHA gelé) : #20188 interdit que l'extraction la toucheadditive: pas de paramètreadditive, lecture deactive_insights(une seule insight par symbole)La classe de défaut mesurée est donc : copie non déclarée de la famille du PCM par poches, ou copie déclarée modifiée sans re-déclaration. Elle est substantielle : c'est exactement le mode de défaillance qui a produit le
#19740non propagé.Le périmètre livré
scripts/quantconnect/check_pcm_single_source.py— l'organe : scan de l'arborescence QC, comparaison au manifeste, empreintessha256du texte normalisé (insensible aux fins de ligne, donc identique en checkout Windows et Linux), sortie humaine,--json(porte désormais l'empreinte déclarée et actuelle, pleines) ou--print-hashes(empreintes complètes, copiables dans le manifeste).scripts/quantconnect/pcm_single_source.json— le manifeste : source canonique, copies déclarées, classes, empreinte et raison de chaque déclaration.scripts/quantconnect/tests/test_check_pcm_single_source.py— le corps de tests, dont le contrôle positif exigé par [QC] MultiStrategyPCM : 9 copies, 6 variantes, le correctif #19740 dans 3 seulement — extraire une source unique #20188 et les trois sondes du contre-audit.scripts/ci/fast_lane_registry.py— la trancheTRANCHE38qui branche la garde.scripts/ci/fast_lane.py— l'énumération des tranches (l'entréeTRANCHE38).docs/qc/quantconnect.md— la section FR « Source unique du PCM par poches — la garde » : la procédure de déclaration, les copies déclarées et leur raison.Aucun fichier de
MyIA.AI.Notebooks/QuantConnect/projects/n'est touché : la règle G (backtest obligatoire) ne s'applique pas — cette PR ne modifie aucun projet QC, aucun mode par défaut, aucun comportement d'exécution.Les verdicts de la garde
UNDECLARED_COPYDECLARATION_STALECANONICAL_DRIFTCANONICAL_MISSINGDECLARED_COPY_MISSINGCLASS_MISMATCHUne spécialisation du canonique n'est pas une copie que si elle délègue la reconstruction à
super().determine_target_percent(...): une sous-classe qui redéfinit cette méthode sanssuper()remplace la reconstruction — c'est une copie, et la garde la signale (c'est exactement le mode de défaillance #19740). Les carnets qui définissent une classe de la famille sont comptés et restitués en JSON, sans bloquer — un carnet n'est pas une copie de production.Angle mort assumé
La signature d'une copie est son nom de classe (
MultiStrategy*PCM). Une copie renommée hors de cette famille échappe à la garde — c'est une limite assumée du nom-comme-signature, documentée ici plutôt que laissée implicite : la garde couvre les copies qui gardent le nom de la famille, pas celles qui le changent. (C'est la limite partagée des gardes de ce dépôt qui s'appuient sur un nom de symbole.)Câblage CI
La garde est une garde native de la voie rapide (
TRANCHE38), bloquante :absorbed=True⇒ le check-run est émis sous son nom canonique avec une conclusion réelle, donc un verdict rouge arrête la PR (et non une conclusion neutre d'ombre).Un workflow
pull_requestdédié n'a pas été retenu : un job auto-hébergé doit être enregistré dans l'allowlist decheck_self_hosted_runner_policy.py, et le cliquet#23053refuseubuntu-latestsur une PR. La voie rapide émet le même check-run sans payer un second clone du dépôt.Déclencheurs : toute modification d'un
.pysousMyIA.AI.Notebooks/QuantConnect/, plus le manifeste, plus l'organe lui-même (check_pcm_single_source.py,fast_lane.py,fast_lane_registry.py), plus son corps de tests (une révision qui change la portée de la garde doit la rejouer — leçon #11685/#12817).Contrôle positif (exigence explicite de #20188)
Le corps de tests construit un arbre temporaire dans lequel une copie déclarée est volontairement modifiée et exige un verdict rouge :
et les cas voisins : copie non déclarée (
UNDECLARED_COPY), canonique modifiée (CANONICAL_DRIFT), déclaration orpheline (DECLARED_COPY_MISSING), manifeste illisible (verdictERROR, pas un feu vert). Le cas nominal — l'arbre du dépôt — doit rester vert : c'est le testtest_arbre_du_depot_conforme.Contre-audit (2026-11-04) — cinq points fermés
Le contre-audit Hermes a rejoué la garde sur le siège (pas seulement lu le code) et mesuré trois contournements où elle rendait le feu vert. Tous traités :
determine_target_percentsanssuper()passait au vertfind_definitionspasse en AST : c'est désormais une copie, pas une spécialisation — la discrimination que la seule chaîne des bases ne permettait pas.CappedPouchesPCM(délègue àsuper()) reste une spécialisation légitime. Testé dans les deux sens.class MultiStrategyPCM:sans parenthèses était invisibleCLASS_REtolère l'absence de parenthèses ; l'AST le couvre de toute façon.CANONICAL_DRIFT/DECLARATION_STALEinlevables (aucune empreinte publiée, aucun mode de re-calcule)--print-hashesaffiche l'empreinte normalisée complète ; le rapport--jsonporte l'empreinte déclarée et actuelle, pleines (64 hex).excludeddu manifeste n'était lue par personne (2ᵉ entrée mal formée)scan_notebook_copies, les sous-classes parinherits_canonical).pathsdeTRANCHE38ne couvrait pas l'organe lui-mêmefast_lane.py+fast_lane_registry.pyajoutés, comme les 21 gardes natifs voisins.Le renommage (sonde B) reste l'angle mort assumé de la section ci-dessus.
Mesures
Empreintes du manifeste, recalculées sur l'arbre de la branche :
sha256(texte normalisé)projects/SharedPCM/pouches_pcm.py(canonique)5d0618bc480c2f7…kit-transitoire/03-Framework-Composite/main.pyf698ace1f2b62479…projects/TrendWeatherPointInTime/portfolio_construction.py6c325cd73df05ca1…Plan de remédiation (règle I — organe neuf)
scripts/quantconnect/check_pcm_single_source.py, câblé en garde bloquante de la voie rapide (TRANCHE38).myia-po-2024:CoursIA-2(cette PR). Les violations constatées se corrigent dans le dépôt même qui les introduit — la lane qui pose la copie est celle qui la déclare ou la migre.Hors périmètre
tw-pitdu registre de l'ombre n'est pas touchée.MultiStrategy*PCM(angle mort assumé, section ci-dessus) n'est pas couvert.See #20188
🤖 Generated with Claude Code