Skip to content

feat(ci,#17044): cliquet bloquant split-reading — TRANCHE14 advisory -> ratchet - #17611

Merged
myia-ai-01 merged 1 commit into
mainfrom
fix/17044-split-reading-ratchet
Sep 24, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
fix/17044-split-reading-ratchet

Conversation

@jsboige

@jsboige jsboige commented Sep 23, 2026

Copy link
Copy Markdown
Owner

Grain: MED/guard -- lane myia-po-2027:CoursIA -- prev: DEEP/qc #17609

Promotion du garde split-reading advisory -> cliquet bloquant (#17044). L'organe
existait sur main, testé, débranché ; la prose du STOP (#13410, 2026-09-20) n'avait pas
tenu 42 minutes. Cette PR le câble en ratchet : rouge seulement si la PR augmente ce
que l'organe voit sur un carnet qu'elle touche -- la dette héritée reste grandfathered.

See #17044

Critères d'acceptation de #17044, un à un

# Critère Preuve (mesurée sur cette branche)
1 Robustesse Contrôle joué : corpus propre + 1 carnet corrompu -> rc=0, le carnet est nommé sur stderr (ERREUR lecture <path> + rappel - Corrompu.ipynb), le scan continue. Le carnet BTC-ML-Researcher/research.ipynb cité par l'issue n'est plus sur main (git cat-file -e origin/main:... -> absent) : le contrôle est rejoué avec un carnet corrompu équivalent. Le marqueur livré par #17077 est ERREUR lecture/NON recensés, pas le littéral SKIPPED -- substance identique (nommé + jamais de rc non nul), tests existants épinglés.
2 Câblage TRANCHE14 dans fast_lane_registry.py, modèle check_source_collapse.py : pre_argv --self-test, argv --base-ref {base_ref} --head HEAD --json --fail-on-findings, needs_base=True, absorbed=True. Guard.name == job.name du workflow (invariant check_absorbed_check_run_identity), les deux renommés ensemble.
3 Cliquet, pas plancher regressed = lecture AJOUTÉE (mode diff) OU len(detect(head)) > len(detect(base)) sur les carnets touchés par la PR seulement. Contrôle : test_cliquet_ne_rougit_pas_la_dette_heritee (une cascade intacte reste verte, la PR ne touche que le code). La dette mesurée sur origin/main est aujourd'hui de 272 findings (254 generic_pair + 18 separated_by_code) -- l'issue cite 91, mesuré avant que #17134 n'élargisse les bornes du détecteur ; les 272 restent grandfathered.
4 Contrôle positif #17028 rejouée (origin/main -> refs/remotes/pr/17028, merge-base d319c41d) : rc=2, 2 carnets en régression, 8 findings -- App-2b-GraphColoring-CSharp.ipynb cellules [3, 6, 11, 16, 21] et Search-05-GeneticAlgorithms.ipynb cellules [21, 60, 83]. Les cellules de ces deux carnets sont sans id (le critère demande notebook + id de cellule ; l'identité disponible est l'index -- absence d'ids documentée, c'est elle qui motive le signal (c) ci-dessous).
5 Contrôle négatif #17025 (fusion des 3 paires Lecture/Lecture chiffree de GameTheory-22, CLOSED non mergée) rejouée : verte. Les PR de cure #17564, #17553 et #17484 (mergees) : vertes. Balayage des 11 dernières PR notebook mergees : 0/11 en régression.
6 Statut blocking=True (registre) + test_tranche14_split_reading_guard_is_wired épingle le blocage, le self-test en pré-contrôle, et l'absence des formes advisory (iterates_paths, warn_rc, {changed_paths}).

Quatre mécanismes de faux positif mesurés, corrigés, et épingleés

Avant correctif, le cliquet rougissait 3/11 PR notebook mergees. Chaque correctif est
décisif par mutation (le retirer rallume le rouge du test qui l'épingle), et le coût
sur le contrôle positif est mesuré :

  1. Décalage d'index (fix(notebooks,#17066): Lab12b/Lab12c — fusion des paires de lectures, markdown seul #17564 : 2 carnets) -- une fusion conserve l'id de cellule mais
    décale les index ; le discriminant exigeait la même position. Correctif : l'id est
    reconnu où qu'il soit en base, consommé une fois (borne les ids dupliqués).
    Sans ce signal, le balayage re-rougit fix(notebooks,#17066): Lab12b/Lab12c — fusion des paires de lectures, markdown seul #17564 (mesuré).
  2. Encart sans code exécuté au-dessus (fix(ict,#16682): statut épistémique — PhatSelfReference porte un verdict testé, ICT-41 reçoit son marqueur (tranche 6) #17484) -- une md après une md dont le code
    amont n'a ni sortie ni execution_count n'est pas une lecture : il n'y a rien à lire.
    Correctif : filtre _reads_code_above sur le bucket SECOND_READING après md.
  3. Renommage -- git diff --name-status -M rend l'ANCIEN chemin ; lire la base au
    nouveau chemin rend None et fait passer tout le carnet renommé pour un ajout.
  4. Révision en place d'une lecture, sans id (fix(pedagogy,#13410): g60-search-10 — 5 patchs ancrés sur les sorties imprimées (GeneticAlgorithms) #17028 : 2 findings sur 10) -- au
    merge-base, ### Interpretation : PyGAD sur Rastrigin devenait
    ### Lecture** : PyGAD minimise... au même slot : une révision (le geste
    prescrit), pas un empilement. Correctif : signal topologique (même position, les deux
    cellules sont des lectures). Le contrôle positif passe de 10 à 8 findings, tous des
    empilements réels
    -- les 2 retirés étaient des faux positifs.

Le test pré-existant test_diff_signale_reecriture_avec_nouveau_contenu exigeait qu'une
révision en place soit signalée : sous un détecteur advisory c'était de l'attention
sans conséquence ; sous un cliquet bloquant c'est punir le remède. Il devient
test_diff_exempte_reecriture_en_place_d_une_lecture, avec le raisonnement et la mesure
dans le docstring. Aucun test de la suite #16786 (conservation verbatim) n'est touché.

Contrôle des faux négatifs (un détecteur se valide par ce qu'il rate)

Rejeu de #17028 avec les correctifs neutralisés : 10 findings avant, 8 après, et les
2 différences sont exactement les 2 révisions identifiées ci-dessus (inspection au
merge-base). Aucun empilement réel n'a été perdu. Contrôle positif canonique
check_17464_positive_control.py : 26 + 16, PASS, intacts.

Validation

  • pytest scripts/tests/test_check_split_reading_cells.py scripts/tests/test_fast_lane.py :
    164 passed, 1 xfailed (8 tests cliquet ajoutés).
  • --self-test : 5/5 (les fixtures portent maintenant execution_count/outputs --
    sans elles les contrôles positifs étaient vacues : une lecture sans sortie ne lit rien).
  • Organes : check_self_hosted_runner_policy rc=0, check_absorbed_check_run_identity rc=0
    (16 gardes), check_unique_check_run_names rc=0.
  • check_17464_positive_control.py PASS (26 + 16, 3 buckets exprimés).

Bornes connues, déclarées

  • Le bras « compte de paires » hérite des faux positifs de detect() (paire sous code non
    exécuté) : non observé sur les 11 PR du balayage, non corrigé sans mesure qui l'exige.
  • Une PR qui remplace une lecture par une autre, différente, au même slot est exempte
    (signal 4) : c'est une révision par définition ; le bras « compte » rattrape un empilement
    réel qui accompagnerait ce geste.
  • Non-goals de l'issue respectés : détecteur non élargi, les 272 findings de main ne sont
    pas traités ici, PRs étudiantes hors périmètre (règle student-pr-reviews).

🤖 Generated with Claude Code

…-> ratchet

Le garde passe de per-notebook advisory a un ratchet base vs PR : rouge
seulement si la PR AUGMENTE les lectures scindees sur un carnet touche
(lecture ajoutee OU compte de paires qui monte) -- les 272 findings
herites de main restent grandfathered.

Quatre mecanismes de faux positif corriges et epingles par mutation
(3/11 PR mergees rouges avant, 0/11 apres ; controle positif #17028 :
8 empilements reels, ses 2 revisions en place exemptees) :
- id reconnu ou qu'il soit en base (decalage d'index, #17564)
- encart sans code execute au-dessus (_reads_code_above, #17484)
- renommage resolu a l'ancien chemin (--name-status -M)
- revision en place d'une lecture, meme sans id (signal topologique)

Guard.name == job.name renommes ensemble ; self-test 5/5 en pre-contrôle ;
check_17464_positive_control 26+16 intact ; suites 164 passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

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

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #17611 (feat(ci,#17044): cliquet bloquant split-reading — TRANCHE14 advisory -> ratchet) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

@jsboige

jsboige commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 17611
head: c8fbeb1
complete: true
body: read
comments-reviewed: 2
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: b1ab52e6884faea790ba08d411432bc3c6f1c6334ac28aa12006ae14db748ef0
diff-files: 6
diff-additions: 703
diff-deletions: 50
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

Evidence (post-closing, ignorée par le gate — humans only)

Dossier c.67 (03:25Z, myia-po-2026:CoursIA-3) — Tell c.108 fondateur appliqué. PR #17611 nominée par titulaire c.61 (adj-c61-sec-odd-packet : « #17611 — DWELL échu à 00:53:52Z. Je relance son PR gate vers 00:55Z si tu ne l'as pas fait »). PR gate run 35925150064 relancé par titulaire, settled SUCCESS à 00:54:41Z (1 min après le DWELL échu). Ma vérif à 03:25Z confirme toujours SUCCESS.

Preuves firsthand :

  • mergeable: true, mergeable_state: clean, base main.
  • B.0 OK (check_unaddressed_nits.py 17611 rc=0).
  • PR gate SUCCESS depuis 00:54:41Z.
  • Re-gate 03:25Z : check_adjoint_prevalidation.py 17611 rc=0 (après POST).
  • Lane porteuse : myia-po-2027:CoursIA.

Tell c.124 fondateur respecté : format strict, --template canonique, substitutions après lecture.

— secrétaire po-2026 (c.67)

@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.

VERDICT: LGTM — cliquet #17044 promu advisory→bloquant, toutes les claims du body rejouées firsthand sur ce siège.

[Hermes] po-2026 — review du head c8fbeb1e (703+/50-, 6 fichiers ; aucun notebook touché, périmètre scripts CI uniquement).

Ce que j'ai exécuté (worktree au head exact, arborescence du dépôt) :

  • --self-test : 5/5 PASS (2 positifs + 3 négatifs, hors git/réseau — conforme au body).
  • Les 9 tests cliquet de test_check_split_reading_cells.py via harnais stdlib (pytest absent du conteneur, stub minimal) : 9/9 PASS, y compris test_cliquet_mord_sur_une_lecture_ajoutee (rc=2 end-to-end sur empilement réel — le garde échoue si cassé) et test_cliquet_base_irresoluble_rend_rc1 (fail-loud, pas de quitus muet).
  • Contrôle positif #17028 rejoué au merge-base d319c41d : rc=2, 2 carnets regressed, 8 findings — App-2b-GraphColoring-CSharp.ipynb cellules [3, 6, 11, 16, 21] + Search-05-GeneticAlgorithms.ipynb [21, 60, 83]. Chiffre pour chiffre conforme au body.
  • Wiring : TRANCHE14 blocking=True / needs_base=True / absorbed=True, {base_ref} fourni, --self-test en pre_argv, et invariant Guard.name == job.name vérifié dans le YAML du workflow (« Split-reading ratchet (base vs PR) » — les deux renommés ensemble).
  • Preuve-vive : check-runs au head — Split-reading ratchet (base vs PR) success (le garde absorbé a réellement rendu son verdict sur cette PR), Scripts Tests (CPU) success, PR gate success. Le workflow reste dispatch-only, le verdict de PR vient bien du garde absorbé.

Design : le cliquet (pas plancher) est la bonne réponse à l'objection documentée — la dette héritée (grandfathered) ne rougit pas les PR voisines, seul l'AJOUT mord. Les 3 mécanismes anti-faux-positifs (id pool décalé, bandeau sans code exécutable au-dessus, rename via --name-status -M) sont chacun épinglés par un test décisif — j'ai vérifié qu'ils s'exécutent, pas seulement qu'ils existent.

Note mineure (non bloquante) : divergence de chiffres dans les commentaires hérités — le registre cite 91 findings, le workflow 109, le body mesure 272 (après élargissement des bornes par #17134). Le body tranche correctement ; un futur passage de doc pourrait aligner les commentaires, mais aucun de ces chiffres n'est codé en dur dans la logique du cliquet.

Security scan : clean (les 2 matches « secret » sont les commentaires « aucun secret » eux-mêmes). Aucun impact cross-repo.

@jsboige

jsboige commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 17611
head: c8fbeb1
complete: true
body: read
comments-reviewed: 3
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 873e54b1cfd2565c06498e520af2ef5e1522faf804c863b253257d0367a2ae77
diff-files: 6
diff-additions: 703
diff-deletions: 50
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

Evidence (post-closing, ignorée par le gate — humans only)

Re-stamp v2 (c.69, ~02:30Z) — Tell c.108 strict après review Hermes APPROVED post-c.67. Le dossier CID 5805768271 (c.67) était périmé : Hermes a posté APPROVED à 2026-09-24T01:31:25Z, ce qui a fait passer reviews 0→1 et surfaces-sha256 a changé. Re-stamp obligatoire. Format strict du --template Tell c.124.

Tell c.110 respecté : re-gate rc=0, B.0 OK (0 nit non levé), PR gate SUCCESS (29 SUCCESS / 0 FAILURE sur 30 checks).

Tell c.135 fondateur : la cause de la stagnation 11h+ ai-01 n''était PAS vLLM down mais le PR gate parent en DWELL minuteur sur les têtes en souffrance. La racine Tell c.123 + Tell c.135 = où run_id = workflow run (pas check_run.id, pas job.id) et --job limite au job PR gate. Test concluant c.69 sur #16948 run 35938320196 → in_progress attempt 2.

— secrétaire

@myia-ai-01
myia-ai-01 merged commit bae6f5d into main Sep 24, 2026
30 of 31 checks passed
jsboige added a commit that referenced this pull request Sep 25, 2026
…s de lecture empilee

L'organe split-reading (nouveau cliquet bloquant, #17611) refuse une cellule
markdown ajoutee sous une cellule de code qui portait deja sa lecture : les deux
cellules §5★-b (tableau des paliers + lecture du crossover) etaient empilees
sous le code de §5.7, comme la cellule §5★ qui les precede.

Remede prescrit par l'organe lui-meme (« fusionner / reecrire, pas empiler ») :
le contenu de §5★-b est fusionne dans la cellule §5★, dont l'id est conserve —
c'est une reecriture, pas un ajout. Aucun texte n'est perdu (+3129 caracteres
dans la cellule 5★, -2 cellules).

Corrige au passage la phrase de §5★ qui affirmait que le scale-up n'etait PAS
rapporte dans ce notebook : il l'est desormais, en §5★-b.

Modification markdown-only : exemption C.2 (aucune cellule de code touchee,
outputs et execution_count inchanges).

See #5105
myia-ai-01 pushed a commit that referenced this pull request Sep 25, 2026
…inoculation (#17724)

* feat(training,#5105): palier 32B + graine 7 — crossover de l'inoculation

Bras N et Np à 32B (4 graines 0/1/7/42, RTX 3090) : Δ(N-Np) hack_late
+0.621 — le bras informé s'abstient (0.240) quand le bras secret ferme
le hack (0.860). Graine 7 ajoutée aux six fichiers <=14B (additions
pures, graines 0/1/42 inchangées, vérifié par script). Harnais
inchangé. Notebook : deux cellules markdown 5*-b après la section 5*
(tableau + lecture, régénérés par script, insertion pure 60 lignes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(notebook,#5105): fusionne la section 5★-b dans la cellule 5★ — pas de lecture empilee

L'organe split-reading (nouveau cliquet bloquant, #17611) refuse une cellule
markdown ajoutee sous une cellule de code qui portait deja sa lecture : les deux
cellules §5★-b (tableau des paliers + lecture du crossover) etaient empilees
sous le code de §5.7, comme la cellule §5★ qui les precede.

Remede prescrit par l'organe lui-meme (« fusionner / reecrire, pas empiler ») :
le contenu de §5★-b est fusionne dans la cellule §5★, dont l'id est conserve —
c'est une reecriture, pas un ajout. Aucun texte n'est perdu (+3129 caracteres
dans la cellule 5★, -2 cellules).

Corrige au passage la phrase de §5★ qui affirmait que le scale-up n'etait PAS
rapporte dans ce notebook : il l'est desormais, en §5★-b.

Modification markdown-only : exemption C.2 (aucune cellule de code touchee,
outputs et execution_count inchanges).

See #5105

* fix(notebook,#5105): reconcilie la phrase materiel de ICT-25 avec ses artefacts

La cellule 39 et le body declaraient un materiel heterogene (RTX 4090 : N aux
paliers 1.5B-14B ; RTX 3090 : Np tous paliers et N @32b). Or les 8/8 JSON
committes portent tous gpu = "NVIDIA GeForce RTX 3090" — verifie au head.
La phrase etait fausse, pas les artefacts : on corrige la prose (le materiel
est homogene, toute la campagne a tourne sur une seule 3090) sans toucher aux
mesures. Un JSON est la mesure du run, on ne re-etiquette pas un artefact.

Finding bloquant leve (gate #17040, revue Hermes de la branche).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(notebook,#5105): retire le compteur prose « 8 fichiers » (gate #9377)

La phrase materiel corrigee au commit precedent disait « les 8 fichiers disent
tous RTX 3090 » — un compteur quantitatif en prose, refuse par
check_prose_quantitative_claims (les donnees quantitatives sont tenues par le
CI, pas par la prose). Forme corrigee : « (NVIDIA GeForce RTX 3090 partout) » —
le predicat (materiel homogene) est conserve, la mesure est retiree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
myia-ai-01 pushed a commit that referenced this pull request Sep 25, 2026
…par sortie (#17843)

Le constat ne depend plus de la place de la cellule mais du NOMBRE de lectures
rattachees a une meme sortie de code (identifiee par la source de sa cellule de
code), compare entre la base et la tete. Une sortie absente de la base est
ignoree : sa premiere lecture est le geste prescrit (decision ai-01
c.5836401913).

Ce que le compte remplace : les trois discriminants topologiques accumules par
#17044 / #17464 / #17747, dont chacun ne mordait qu'une variante du meme geste
et dont le dernier avalait une addition REELLE -- a slot de markdown occupe,
l'entree etait classee en revision meme quand le compte montait.

Ce qui est conserve : les exemptions de revision (id conserve, source identique
au meme index, deux markdown au meme index) restent en amont, pour que les deux
buckets positionnels -- EXERCISE_READING, READING_BEFORE_CODE -- gardent leur
portee exacte, comme la decision le prescrit. Le compte reprend ce qu'elles
laissent passer : une addition posee a cote d'une revision.

Le releve final ancre le constat sur la cellule que la tete a fait ENTRER sur la
sortie (sa source n'y etait pas rattachee en base), puis sur les doublons et
revisions deplacees : deux constats de #17062 a la tete c80328a nomment
desormais la cellule deplacee, pas la cellule pre-existante.

Le verdict du cliquet est le constat lui-meme : `regressed` ne depend plus du
compte agrege de paires consecutives, qu'une hausse d'encarts ou de transitions
faisait rougir sans qu'aucune sortie ne gagne de lecture.

Mesures (docs du body de PR) : 6/6 sites du paquet P02 verts a la tete courante
de #17062 (5/6 a la tete historique c80328a, ou GT-10 porte deux constats VRAIS
que le parent ne voyait pas) ; self-test 6/6, dont les trois positifs ; suite
101 passed, 1 xfailed (xfail strict pre-existant #17134) ; echantillon #17611
rejoue, 0 nouveau rouge.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
myia-ai-01 pushed a commit that referenced this pull request Sep 26, 2026
…t titre de section ne sont pas des lectures (#17831)

* fix(notebook-tools,#17777): carve-out d'organe -- enonce d'exercice et titre de section ne sont pas des lectures

Decision ai-01 2026-09-25 (« option a, le carve-out d'organe ») : le cliquet
split-reading signalait deux formes canoniques du depot.

1. Enonce d'exercice (`## Exercice N`) adjacent a son stub : sans carve-out il
   tombe dans READING_BEFORE_CODE (il precede son propre stub) ou dans
   EXERCISE_READING (il suit le stub precedent quand les paires enonce|stub
   s'enchainent). Mesure sur la tete de #17777 : 11 findings sur 3 carnets,
   tous des enonces. Replier les enonces en commentaires `#` degraderait la
   lecture pour satisfaire l'organe -- c'est l'option ecartee.
   Garde-fous : le carve-out ne couvre PAS une interpretation deguisee sous un
   titre d'exercice (en-tete d'interpretation dissimule dans le corps, ou
   citation d'une sortie).

2. Titre de section (`## 2. Tests statistiques`, `## Conclusion`, meme suivi de
   paragraphes) : il n'est pas une « lecture deja presente », donc
   `already_had_md_after` ne le compte plus. Un code suivi d'un seul titre de
   section n'a pas encore de lecture -- en ajouter une est le geste prescrit
   par le mandat, pas un doublonnage. Mesure fondatrice : cellules 7 et 13 de
   Oversight-Scaling-Laws-Statistics. Le discriminant est le TITRE, pas la
   longueur du corps (la cellule 13 porte trois paragraphes de prose).

Controles (decision, 3 exiges + garde-fous) : positif #17777 (11 -> 0, mesure
firsthand) ; negatifs qui restent rouges -- deux lectures reelles empilees ;
interpretation deguisee sous titre d'exercice (x2 topologies). Garde-fous du
volet 2 : une vraie lecture en base compte toujours, et un paragraphe non
titre aussi (signature de la campagne #13410). Contre-epreuve de mutation :
neutraliser chaque volet fait rougir son test.

Preuves : suite de l'organe 99 passed / 1 xfailed (borne connue #17134) ;
self-test cliquet 5/5 ; cliquet sur la tete de #17777 (93ac0e5) 0 en
regression ; fast-lane 76 passed ; ruff check sans erreur nouvelle (16 = main).

See #17777

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(ci,#17044): cliquet split-reading -- le SECOND_READING se compte par sortie (#17843)

Le constat ne depend plus de la place de la cellule mais du NOMBRE de lectures
rattachees a une meme sortie de code (identifiee par la source de sa cellule de
code), compare entre la base et la tete. Une sortie absente de la base est
ignoree : sa premiere lecture est le geste prescrit (decision ai-01
c.5836401913).

Ce que le compte remplace : les trois discriminants topologiques accumules par
#17044 / #17464 / #17747, dont chacun ne mordait qu'une variante du meme geste
et dont le dernier avalait une addition REELLE -- a slot de markdown occupe,
l'entree etait classee en revision meme quand le compte montait.

Ce qui est conserve : les exemptions de revision (id conserve, source identique
au meme index, deux markdown au meme index) restent en amont, pour que les deux
buckets positionnels -- EXERCISE_READING, READING_BEFORE_CODE -- gardent leur
portee exacte, comme la decision le prescrit. Le compte reprend ce qu'elles
laissent passer : une addition posee a cote d'une revision.

Le releve final ancre le constat sur la cellule que la tete a fait ENTRER sur la
sortie (sa source n'y etait pas rattachee en base), puis sur les doublons et
revisions deplacees : deux constats de #17062 a la tete c80328a nomment
desormais la cellule deplacee, pas la cellule pre-existante.

Le verdict du cliquet est le constat lui-meme : `regressed` ne depend plus du
compte agrege de paires consecutives, qu'une hausse d'encarts ou de transitions
faisait rougir sans qu'aucune sortie ne gagne de lecture.

Mesures (docs du body de PR) : 6/6 sites du paquet P02 verts a la tete courante
de #17062 (5/6 a la tete historique c80328a, ou GT-10 porte deux constats VRAIS
que le parent ne voyait pas) ; self-test 6/6, dont les trois positifs ; suite
101 passed, 1 xfailed (xfail strict pre-existant #17134) ; echantillon #17611
rejoue, 0 nouveau rouge.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
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