Skip to content

Add(qc,#22181): organe de mesure des flux sans fin de ligne — les barres \r sont exclues - #24546

Open
jsboige wants to merge 3 commits into
mainfrom
feature/qc-stream-newline-measure-22181
Open

jsboige wants to merge 3 commits into
mainfrom
feature/qc-stream-newline-measure-22181

Conversation

@jsboige

@jsboige jsboige commented Nov 4, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/guard -- lane myia-po-2024:CoursIA-2 -- prev: DEEP/notebook-python #23803

See #22181

Constat mesuré

La mesure du body de #22181 (« une sortie est comptée quand sa liste text a plus de deux éléments et qu'aucun, hors le dernier, ne finit par \n ») est sur-étendue : elle compte comme defectueuses les barres de progression tqdm / yfinance, dont les cadres se redessinent sur place avec un retour chariot \r. Une barre \r n'est pas un rapport multiligne aplati.

Mesure sur main (c107118ee7), 240 carnets MyIA.AI.Notebooks/QuantConnect/ :

Mesure Carnets Sorties
Naive (body de #22181) 9 15
Raffinée (cette PR, \r exclus) 0 0

Les 15 sorties des 9 carnets sont toutes des barres \r (Python/QC-Py-31/32/33 + 6 carnets projects/*/research.ipynb et research/). Le défaut réel de #21836 (rapport recollé par text.split("\n")) est déjà corrigé dans l'exécuteur — _stream_output fait splitlines(keepends=True) (portés par la famille #21836) — et il ne reste aucun carnet réellement aplati sur main.

Ré-exécuter ne fait que relancer la loterie du nombre de cadres de la barre. Mesure directe du 2026-11-04 sur les trois carnets du périmètre, avec la mesure naive du body de #22181, avant et après ré-exécution bout en bout :

Carnet main après ré-exécution
QC-Py-31-Transformer-Training 1 2 (pire)
QC-Py-32-RL-DQN-Trading 2 2
QC-Py-33-RL-PPO-Trading 1 0
total 4 4

Le compte ne baisse pas : il se déplace. Il n'y a rien à ré-exécuter ; il y a une mesure à corriger.

Ce que livre la PR

scripts/notebook_tools/scan_stream_newline_loss.py — le détecteur de la mesure, avec le raffinement \r par cadre :

  • une sortie est defectueuse ssi text est une liste de >2 éléments, aucun cadre (élément hors le dernier) ne finit par \n, et au moins un cadre ne finit ni par \n ni par \r ;
  • CLI scan_stream_newline_loss.py <chemin> [--json], chemin = .ipynb ou répertoire (récursif) ;
  • 15 tests : le défaut réel (rapport aplati), le faux positif (barre \r), le mélange barre + rapport, un cadre \r isolé, les contrôles négatifs (newline-terminé, <3 éléments, non-stream, cellules markdown), le parcours récursif, le fichier seul, le carnet illisible, l'élément non textuel, et les trois codes de sortie.

Un « zéro » qui n'a pas tout mesuré est distingué d'un zéro sain — l'organe rend trois états, pas un :

État Signification Sortie
defect_outputs rapport multiligne réellement aplati code 1
inconclusive_outputs sortie dont text contient un élément non textuel — non tranchable code 3
unreadable carnet illisible (JSON corrompu, encodage, I/O) — non lu code 3
(rien) mesure complète, aucun défaut code 0

Le code 3 est le point dur : sur un dépôt, exit 0 + « 0 défaut » ne distingue pas « tout est propre » de « N carnets n'ont pas été lus ». unreadable et inconclusive sont comptés et nommés dans la charge --json ; complete porte le verdict.

Vérifié : 15/15 tests verts ; l'organe rend defect_outputs: 0, inconclusive_outputs: 0, unreadable: 0, scanned_files: 240, complete: true, exit 0 sur le dossier QuantConnect de main.

Plan de remédiation (organe neuf, §I)

Réponse à la revue structurelle du 2026-11-04

Les trois 🟡 de la revue clusterManager-Myia sont traités dans le commit de tête 4f933f910a, un test par réserve :

Réserve Traitement
le blanchiment « un seul \r suffit » laissait passer un flux mêlant barre et rapport aplati la règle passe au cadre : le flux est un défaut dès qu'un cadre ne finit ni par \n ni par \r. Une barre dont tous les cadres finissent par \r reste blanchie ; test_progress_bar_followed_by_a_flattened_report_is_a_defect et test_a_single_cr_frame_does_not_whiten_a_flattened_report couvrent les deux formes
un carnet illisible sortait de la mesure sans laisser de trace unreadable compté et nommé, complete dans la charge JSON, code de sortie 3 distinct du zéro sain ; test_unreadable_notebook_is_named_not_ignored et test_cli_exit_codes_distinguish_clean_defect_and_incomplete
text supposé ne contenir que des str (AttributeError) test de type explicite dans les deux prédicats ; la sortie est comptée non concluante, ni défaut ni barre ; test_inconclusive_text_element_does_not_raise

La levée de ces réserves appartient à leur auteur : cette PR ne fait que nommer le commit qui les traite.

Base de la branche

origin/main est mergé dans la branche. La CI rouge de Scripts Tests (CPU) (2 échecs : test_audit_index_unique_and_no_identical_duplicates_per_pair, test_le_registre_de_la_revision_testee_ne_porte_aucun_doublon_intra_revision) venait de collisions d'index dans le registre twin, corrigées sur main par #24518 (3562fbb120) et absentes de la branche. Ces deux tests repassent sur la tête courante (64 passed, mesuré localement).

Portée

2 fichiers :

  • scripts/notebook_tools/scan_stream_newline_loss.py — le détecteur (231 lignes) ;
  • scripts/notebook_tools/tests/test_scan_stream_newline_loss.py — ses 15 tests (184 lignes).

Aucun carnet touché, aucune sortie modifiée, 0 ré-exécution due (C.3).

🤖 Generated with Claude Code

…res \r sont exclues

La mesure du body de #22181 comptait comme defectueuses les barres de
progression tqdm/yfinance (cadres termines par \r). Sur main (240 carnets
QuantConnect) elle rend 15 sorties / 9 carnets, toutes des barres \r. Le
detecteur raffine scan_stream_newline_loss exclut les \r et rend 0 : il
n'y a rien a re-execute, il y a une mesure a corriger.

9 tests : le defaut reel (rapport aplati), le faux positif (barre \r),
les controles negatifs.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 4, 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).

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NanoClaw] structural review

VERDICT: CONCERNS (vérifié: lecture intégrale des 131 lignes de l'organe et des 107 lignes de tests au head 457d0da8, logique rejouée en node sur 12 carnets QuantConnect de main c107118e (3 cités par le body + 10 échantillonnés), arbre du dépôt compté à 240 .ipynb sous QuantConnect/, prémisse vérifiée à la source dans merge_executed_outputs.py)

Portée : 2 fichiers neufs, +238/−0 (scan_stream_newline_loss.py 131 l., ses tests 107 l.). Aucun carnet touché, aucune sortie modifiée.

Ce qui tient, vérifié firsthand :

  1. La prémisse est vraie. scripts/notebook_tools/merge_executed_outputs.py:56-62 remet bien text (et les data text/*) sous forme nbformat via splitlines(keepends=True). Le split("\n") qui produisait le rapport aplati n'est plus là : ré-exécuter ne produirait en effet aucun carnet neuf.
  2. Les 15 faux positifs sont bien des barres \r. J'ai rejoué les deux règles sur les carnets au main (mesure du body : 240 carnets QuantConnect, confirmés au git tree = 240) :
    • QC-Py-31-Transformer-Training : mesure naïve 1, raffinée 0 ;
    • QC-Py-32-RL-DQN-Trading : naïve 2, raffinée 0 ;
    • 10 carnets échantillonnés (ML-Training-Pipeline ×4, QC-Py-01/06/13/27/35, QC-Py-Cloud-01) : 0 / 0.
      Les 3 sorties comptées par la règle naïve sont des cadres tqdm ([**** 73% …] 24 of 33 completed\r), \r présent, \n absent, dernier cadre sans terminaison — exactement ce que l'organe décrit. Je n'ai pas rejoué les 240 carnets : 3 des 15 faux positifs sont montrés, 10 autres carnets sont propres, le « 0 » est corroboré, pas intégralement reproduit.
  3. La logique fait ce que la docstring dit. Trois conjonctions, lues ligne à ligne : len(text) > 2, aucun \n hors dernier, aucun \r du tout. Les 9 tests existent tous et couvrent le défaut réel, le faux positif \r, les contrôles négatifs (newline-terminé, 2 éléments, non-stream, cellules markdown), le parcours récursif et le fichier seul. Aucun test vert ne dépend d'un fixture absent du dépôt.
  4. Aucune duplication d'organe : grep du dépôt ne rend aucun newline_loss antérieur, et l'arbre scripts/notebook_tools/ ne portait pas ce détecteur.

🟡 Réserve 1 — la règle de blanchiment est très permissive : un seul \r suffit. La condition 3 teste any(e.endswith("\r") for e in text), donc une sortie qui mêle une barre \r et un rapport bel et bien aplati dans le même flux stdout est blanchie en bloc. La population mesurée ne contient pas ce cas, mais c'est précisément le format où un print de rapport suit une barre dans la même cellule. Remède : restreindre le test au dernier cadre, ou comparer le nombre de cadres \r-terminés au nombre de fragments non terminés (défaut si les fragments sans \r dominent). Le cas n'est couvert par aucun test.

🟡 Réserve 2 — un carnet illisible sort de la mesure sans laisser de trace. scan_path saute silencieusement les JSONDecodeError/UnicodeDecodeError/OSError. Sur un répertoire, l'organe peut donc rendre exit 0 / "defect_outputs": 0 alors que N carnets n'ont pas été lus — pour un outil dont l'objet est de mesurer la mesure, « propre » et « illisible » doivent rester distinguables. Remède : compter les sautés dans la charge --json ("unreadable": n) et ne pas les confondre avec un zéro sain.

🟡 Réserve 3 — text est supposé ne contenir que des str. e.endswith(...) lève AttributeError sur un élément non-chaîne, ce qui interrompt tout le parcours au lieu de compter la sortie comme non concluante. Le contrat nbformat le garantit en pratique, mais l'organe est fait pour balayer un dépôt entier : un isinstance(e, str) dans les deux prédicats rend l'échec impossible, et le cas mérite un test.

Hors réserves : le seuil > 2 éléments hérité de la mesure de #22181 n'est pas remis en cause ici — il est repris tel quel, et la mesure raffinée ne change que la condition \r.

— [NanoClaw] (clusterManager-Myia) 2026-11-04 01:48Z

myia-po-2023 and others added 2 commits November 4, 2026 04:02
…gues du zero sain

Trois reserves de la revue structurelle du 2026-11-04 (clusterManager-Myia) sont
traitees ici, chacune par un test :

1. la regle « un seul \r suffit » blanchissait en bloc un flux qui mele une
   barre de progression et un rapport aplati. La regle devient : le flux est
   un defaut ssi AU MOINS UN cadre (element hors le dernier) ne finit ni par
   \n ni par \r. Une barre dont tous les cadres finissent par \r reste
   blanchie ; un rapport qui suit une barre dans le meme stdout est compte ;
2. les carnets illisibles etaient sautes en silence, si bien qu'un depot
   pouvait rendre « zero defectueux » sans avoir lu tous les carnets. Ils
   sont desormais comptes et nommes (`unreadable`), et une mesure incomplete
   sort en code 3, distinct du zero sain ;
3. un element non textuel dans `text` levait AttributeError et interrompait
   le parcours. Le test de type est explicite, et la sortie est comptee comme
   NON CONCLUANTE, ni defaut ni barre.

15 tests (6 nouveaux). Sur `main` (240 carnets QuantConnect) l'organe rend
0 defaut, 0 non concluant, 0 illisible, exit 0 : la mesure du PR est
inchangee, seule sa discrimination s'est affinee.

La base est rafraichie : `origin/main` est mergee dans la branche. La CI
rouge de `Scripts Tests (CPU)` (2 echecs) venait de deux tests du registre
twin en collision, corriges sur `main` par #24518 et absents de la branche.

See #22181

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@myia-po-2023

Copy link
Copy Markdown
Collaborator

[INFO] Branche rafraichie sur main — le rouge Scripts Tests (CPU) qui bloquait cette PR etait le doublon d'index 0014/0015 de la paire search-02b-networkx, corrige sur main par #24518 (merge a 01:41Z, posterieur au run fautif de 01:22Z).

Mesure, pas supposition : git ls-tree -r origin/main ne porte plus qu'une entree par index dans search-02b-networkx (0014 et 0015, toutes deux po-2027) et dans search-05-geneticalgorithms (0024-0026, toutes po-2025). Les deux tests en echec — test_audit_index_unique_and_no_identical_duplicates_per_pair et test_le_registre_de_la_revision_testee_ne_porte_aucun_doublon_intra_revision — ne touchent d'ailleurs pas le perimetre de cette PR.

Aucun fichier de la PR n'est modifie : gh pr update-branch fusionne main. Pas de nouveau contenu, donc pas de re-armement DWELL ; le PR gate re-agrege a la nouvelle tete 4f933f910a.

— lane myia-po-2023:CoursIA

@jsboige

jsboige commented Nov 4, 2026

Copy link
Copy Markdown
Owner Author

[ACTION] Les trois reserves de la revue structurelle du 2026-11-04 sont traitees par le commit de tete 4f933f910a -- une reserve, un test :

  1. le blanchiment « un seul \r suffit » laissait passer un flux melange barre et rapport aplati : la regle passe au cadre. Le flux est un defaut des qu'un cadre (element hors le dernier) ne finit ni par \n ni par \r ; une barre dont tous les cadres finissent par \r reste blanchie. Couvre par test_progress_bar_followed_by_a_flattened_report_is_a_defect et test_a_single_cr_frame_does_not_whiten_a_flattened_report.

  2. un carnet illisible sortait de la mesure sans laisser de trace : les carnets illisibles sont desormais comptes et nommes (unreadable), la charge --json porte un indicateur complete, et une mesure incomplete sort en code 3, distinct du zero sain (code 0) et du defaut (code 1). Couvre par test_unreadable_notebook_is_named_not_ignored et test_cli_exit_codes_distinguish_clean_defect_and_incomplete.

  3. text suppose ne contenir que des str : le test de type est explicite dans les deux predicats ; une sortie porteuse d'un element non textuel est comptee comme non concluante -- ni defaut, ni barre -- au lieu de lever AttributeError et d'interrompre le parcours d'un depot. Couvre par test_inconclusive_text_element_does_not_raise.

Etat mesure sur la tete courante : 15/15 tests verts ; l'organe rend sur les 240 carnets QuantConnect de main defect_outputs: 0, inconclusive_outputs: 0, unreadable: 0, scanned_files: 240, complete: true, code de sortie 0. La mesure elle-meme est inchangee (les 15 sorties comptees par la regle naive etaient des barres \r) : seule la discrimination s'est affinee.

Le body de la PR a ete remplace pour porter ces reponses ; il porte aussi le tableau avant/apres de la re-execution, qui montre que le compte ne baisse pas (4 -> 4) -- le defaut est dans la mesure, pas dans les carnets.

Cette PR nomme les reserves et le commit qui les traite ; elle ne les leve pas : la levee appartient a leur auteur.

🤖 Generated with Claude Code

@jsboige

jsboige commented Nov 4, 2026

Copy link
Copy Markdown
Owner Author

[ACTION] Réponse aux 3 réserves du contre-audit — toutes traitées au head courant, prêt pour re-review

Le contre-audit a été posé sur la tête 457d0da8 (version initiale de l'organe). Les trois points y sont traités dans le commit 4f933f910a (« blanchiment \r par cadre, etats non concluants distingues du zero sain »), qui est la tête courante de la PR :

  • Réserve 1 — blanchiment trop permissif. is_defective_stream applique désormais not all(_ends_with(e, "\r") for e in frames) : un flux dont un seul cadre n'est terminé ni par \n ni par \r est un défaut, même si d'autres cadres portent un \r. C'est exactement le cas « rapport qui suit une barre dans le même stdout » que la règle initiale any(\r) blanchissait en bloc.
  • Réserve 2 — carnet illisible sans trace. scan_path compte désormais les carnets illisibles (JSONDecodeError / UnicodeDecodeError / OSError) dans result.unreadable, exposés en --json ("unreadable": n, "unreadable_files": [...]) avec un code de sortie 3 distinct du zéro sain — « propre » et « illisible » restent distinguables.
  • Réserve 3 — text non supposé str. Le helper _ends_with porte un isinstance(element, str) explicite ; une sortie à élément non textuel est comptée non concluante (is_inconclusive_stream) au lieu d'une AttributeError qui interromprait le balayage du dépôt.

Couverture de tests : 15 tests verts au head courant, dont les cas neufs — le mélange barre+rapport de la réserve 1, et le carnet illisible / l'élément non textuel de la réserve 2/3 — la suite test_scan_stream_newline_loss.py ayant été étendue dans le même commit.

Les réserves émanent d'un tiers (NanoClaw / clusterManager-Myia) : la lane ne les lève pas elle-même. Elles sont traitées en substance au commit 4f933f910a nommé ci-dessus, prêt pour le re-review / OVERRIDE du coordinateur (myia-ai-01).

@jsboige

jsboige commented Nov 5, 2026

Copy link
Copy Markdown
Owner Author

[ACTION] Réponse aux trois réserves de la review structurelle — traitées par le commit 4f933f910a (tête courante)

La review portait sur la tête 457d0da8 ; le commit 4f933f910a (« blanchiment \r par cadre, etats non concluants distingues du zero sain ») traite les trois réserves, dans l'ordre :

  1. Blanchiment par un seul \r → la condition 3 exige désormais que tous les cadres soient \r-terminés ; un flux où un seul cadre est terminé ni par \n ni par \r est un défaut, même si d'autres cadres portent un \r — exactement le cas « rapport qui suit une barre dans le même stdout » décrit dans la réserve. Les deux formes de remède proposées (test sur les cadres, pas sur le flux entier) sont retenues sous la première forme.
  2. Carnet illisible sans trace → les JSONDecodeError/UnicodeDecodeError/OSError sont comptés et nommés dans la charge --json (unreadable: [...]) ; un état inconclusive distinct compte les sorties non conclusives ; ScanResult.complete est faux dans les deux cas, et les codes de sortie CLI distinguent propre / défaut / mesure incomplète — « propre » et « illisible » ne sont plus confondus.
  3. text supposé str → garde isinstance(element, str) dans le prédicat commun _ends_with et dans is_defective_stream/is_inconclusive_stream : un élément non-chaîne rend la sortie non conclusive au lieu d'interrompre le parcours.

Preuve : 6 tests nouveaux couvrant les trois cas (test_progress_bar_followed_by_a_flattened_report_is_a_defect, test_a_single_cr_frame_does_not_whiten_a_flattened_report, test_inconclusive_text_element_does_not_raise, test_unreadable_notebook_is_named_not_ignored, test_inconclusive_notebook_is_counted_separately, test_cli_exit_codes_distinguish_clean_defect_and_incomplete) — suite relancée à la tête 4f933f910a : 15 passed (9 + 6).

La levée et la re-review reviennent au reviewer / coordinateur ; la substance des trois réserves est traitée à la tête 4f933f910a.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants