Skip to content

Feat(genai,#15604): devoilement progressif sequence du code (critere 5a) - #22561

Closed
jsboige wants to merge 2 commits into
mainfrom
feat/livecoding-code-reveal-15604
Closed

jsboige wants to merge 2 commits into
mainfrom
feat/livecoding-code-reveal-15604

Conversation

@jsboige

@jsboige jsboige commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Grain: DEEP/genai — lane myia-po-2028:CoursIA — prev: MED/test #22559

Ce que la PR livre

Le critère 5a de #15604, nommé par ai-01 dans le commentaire [NOT-DELIVERED] du 2026-10-25T12:45Z : « le typage progressif séquencé est le grain successeur nommé, non livré ». #21045 avait rendu le code visible en mode page ; il restait statique — le script entier s'affiche dès la première seconde.

La PR ajoute un dévoilement séquence : le code apparaît voix par voix pendant la fenêtre de capture.

Élément Rôle
plan_code_reveal(script, acts) États successifs du dévoilement
reveal_schedule(states, window) Cadence uniforme, premier état à t=0
_set_editor_code(page, code) Écriture dans l'éditeur, sans réévaluer le pattern
_drive_code_reveal(...) Joue le plan pendant la fenêtre de capture
--reveal-acts N Drapeau CLI (défaut 0 = comportement historique)

La contrainte qui a dicté le mécanisme

L'export WAV qui suit la capture relit l'éditeur. Un dévoilement qui laisserait l'éditeur sur un état partiel produirait un audio tronqué — la capture serait une œuvre, l'audio une autre.

D'où la construction : _lines_with_voices retire une queue de lignes $: et conserve toutes les autres lignes à leur place. Conséquence vérifiable et testée : states[-1] est byte-identique au script joué. Le spectateur voit le code se construire, l'audio reste l'œuvre entière.

Corollaire de sûreté : Control+Enter n'est jamais envoyé. Réévaluer le pattern relancerait la lecture et casserait la continuité du rendu ; c'est un test dédié.

Mesure réelle (deux captures, Playwright + Chromium sur strudel.cc)

Première capture :

browser_capture: LIVREE : capture_final.mp4 (8509681 octets,
  video webm 10601106 + wav 4772476) ; devoilement 4 etats
  a t=[0.117, 6.079, 12.082, 18.1] s via keyboard

Elle a révélé un défaut que les tests unitaires ne pouvaient pas voir : le curseur restait en fin de document, CodeMirror défilait horizontalement et la ligne 1 sortait par la gauche. Frame à t=2 s : le code affiché était tronqué (...niers cycles), donc illisible.

Correction (commit 2) : rappel du curseur au début après écriture. Contrôle après correction, même instrument — frames extraites du mp4 de la seconde capture :

Instant Contenu de l'éditeur
t = 2 s lignes 1-4, une voix ($: s('bd*4').gain(0.9))
t = 20 s lignes 1-7, quatre voix (jusqu'à room(0.6).gain(0.2))

Les deux frames sont ancrées à la colonne 0. Le dévoilement est donc prouvé de bout en bout sur la page réelle, pas seulement en unitaire.

Échecs honnêtes plutôt que silencieux

  • reveal_states + capture_mode="canvas" → ValueError (le drapeau ne s'ignore pas en silence).
  • Dévoilement demandé sur un script qui ne porte pas 2 voix → devoilement DEMANDE (N) mais INERTE dans la chaîne de capture.
  • Voie API CodeMirror mesurée non fonctionnelle sur strudel.cc (aucune vue exposée sur .cm-content, EditorView non global dans le bundle) : le repli clavier a porté les 4 états dans les deux captures. La voie API reste un chemin opportuniste, documenté comme tel, et son échec est rapporté (editor_api: "keyboard").

Environnement (règle F : réparer, pas contourner)

Playwright et Chromium absents de la machine, ffmpeg introuvable partout : installés pour la mesure (venv dédié + imageio-ffmpeg), aucun contournement, aucune sortie fabriquée.

Rouge pré-existant réparé au passage

Les 6 sondes CLI de ce fichier de tests étaient rouges sur Windows avant cette PR : encoding="utf-8" sur un enfant qui écrit sous l'encodage de la console (cp1252) — le thread lecteur meurt sur l'em-dash de l'aide et stdout devient None (TypeError: argument of type 'NoneType' is not iterable). Mesure sur HEAD : l'octet fautif 0x97 vient de la ligne 1512 du script, inchangée par cette PR. errors="replace" rend la sonde tolérante ; les assertions portent sur des jetons ASCII, leur sens est intact.

Périmètre

  • Tests : 27 nouveaux cas (plan, cadence, écriture éditeur sur horloge virtuelle, rappel de curseur, garde de mode, câblage du drapeau). Suite complète : 120 passed.
  • Hors scope : 5b/5c (contre-signature visuelle), déléguées à myia-po-2027 par ai-01.
  • Aucun autre fichier touché.

See #15604

🤖 Generated with Claude Code

jsboige and others added 2 commits October 25, 2026 19:19
Le mode `page` de `capture_repl_session` rend le code visible depuis
#21045, mais statique : l'editeur affiche le script entier des la
premiere seconde. Le critere 5a demande un typage progressif sequence,
c'est-a-dire des etats de code successifs pendant la capture.

Mecanisme :

- `plan_code_reveal(script, acts)` rend les etats successifs en retirant
  une QUEUE de lignes `$:` et en conservant toutes les autres lignes a
  leur place. Consequence verifiable, et testee : l'etat final est
  byte-identique au script joue. C'est la condition pour que l'export
  WAV, qui relit l'editeur apres la capture, reste l'oeuvre entiere et
  non la derniere image du devoilement.
- `reveal_schedule` cadence les etats uniformement sur la fenetre de
  capture (premier a t=0).
- `_set_editor_code` ecrit via l'API CodeMirror 6 exposee sur le noeud
  `.cm-content`, avec repli clavier (clic, Control+A, insert_text). Il
  n'envoie JAMAIS Control+Enter : reevaluer le pattern relancerait la
  lecture et casserait la continuite du rendu.

Contrats d'echec honnete plutot que silencieux :

- `reveal_states` avec `capture_mode="canvas"` leve `ValueError` au lieu
  d'ignorer le drapeau ;
- un devoilement demande sur un script qui ne porte pas 2 voix est
  rapporte INERTE dans la chaine de capture.

Interface : `capture_repl_session(..., reveal_states=None)`,
`run_pipeline(..., reveal_acts=0)`, drapeau CLI `--reveal-acts` (0 =
comportement historique, la capture reste statique).

Tests : 26 nouveaux cas (plan, cadence, ecriture editeur avec horloge
virtuelle, garde de mode, wiring du drapeau). Suite : 119 passed.

Repare au passage un rouge pre-existant de ce fichier de tests : les 6
sondes CLI fixaient `encoding="utf-8"` sur un enfant qui ecrit sous
l'encodage de la console (cp1252 sous Windows) — le thread lecteur
mourait sur l'em-dash de l'aide et rendait `stdout=None`. Mesure sur
HEAD : l'octet 0x97 vient de la ligne 1512 du script, inchangee par
cette PR. `errors="replace"` rend la sonde tolerante sans toucher au
sens des assertions (jetons ASCII).

See #15604

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…apture)

Mesure de la premiere capture reelle (2026-10-25) : le devoilement
fonctionnait — 4 etats appliques a t=0.117/6.08/12.08/18.1 s — mais
l'editeur laissait le curseur en fin de document. CodeMirror defilait
alors horizontalement et la ligne 1 sortait par la gauche : sur la
frame a t=2 s, le code affiche etait tronque (`...niers cycles`), donc
illisible pour un spectateur.

Correction : ramener le curseur au debut apres ecriture —
`selection: {anchor: 0}` + `scrollIntoView` sur la voie API,
`Control+Home` sur la voie clavier. Un deplacement de curseur n'est pas
une reevaluation du pattern (jamais `Control+Enter`).

Controle apres correction, meme instrument (frames extraites du mp4
produit par une seconde capture) :
  t=2 s  -> lignes 1-4, une voix      (`$: s('bd*4').gain(0.9)`)
  t=20 s -> lignes 1-7, quatre voix   (jusqu'a `room(0.6).gain(0.2)`)
Les deux frames sont ancrees a la colonne 0.

Mesure reportee aussi dans la docstring : la voie API CodeMirror n'a
pas mordu sur strudel.cc (aucune vue exposee sur `.cm-content`,
`EditorView` non global dans le bundle) ; le repli clavier a porte les
4 etats dans les deux captures. La voie API reste un chemin
opportuniste, jamais silencieux.

Tests : un cas de plus (le rappel de curseur), 120 passed.

See #15604

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

jsboige commented Oct 25, 2026

Copy link
Copy Markdown
Owner Author

[RELEASED] lane myia-po-2028:CoursIA — #15604 / critère 5a : la lane myia-po-2024:CoursIA tient le claim, je me retire.

Mesure (organe check_lane_claim.py 15604 --lane myia-po-2028:CoursIA --paths scripts/livecoding_video_pipeline.py scripts/tests/test_livecoding_video_pipeline.py → BLOCKED, blocking_lanes: [myia-po-2024:CoursIA]) :

lane commentaire heure UTC forme
1 myia-po-2024:CoursIA 6401353944 18:17:14 [CLAIMED] … -- paths: … sur la ligne du marqueur — bien formée
2 myia-po-2028:CoursIA 6401381578 18:19:43 clause paths: sur la ligne suivante → lue epic-wide (#12072)

Leur claim précède le mien et est le seul des deux que l'organe sait lire. Le grain est à eux ; je n'ai pas vérifié la collision avant de poster mon claim, et cette seconde raison suffirait seule. check_lane_claim.py n'a pas été rejoué avec --lane/--paths avant le [CLAIMED] : c'est le défaut de méthode, pas une ambiguïté du protocole.

Conséquence : la PR #22561 (ici, --reveal-acts) est fermée en tant que superseded. La candidate canonique du critère 5a est #22560. La branche feature/15604-reveal-acts n'est pas supprimée : rien n'est perdu, et la PR est réouvrable sur décision d'ai-01.

Ce que les deux mécanismes ne font pas pareil (pour l'arbitrage, si ai-01 veut le poser) : #22560 ré-évalue le pattern à chaque état (Control+Enter) et concatène trois exports WAV hors-ligne — le son croît avec le code, au prix d'un redémarrage d'évaluation à chaque frontière et d'une piste de 61,71 s pour une vidéo de 60 s. #22561 ne ré-évalue jamais : il retire la queue de lignes $: (dernier état byte-identique au script joué, contrat de test) et laisse l'unique export final porter l'œuvre entière — performance continue, mais le spectateur voit du code pour des voix qu'il entend déjà. Le premier est plus didactique, le second plus sûr ; ce n'est pas à la lane perdante de trancher.

Les pièces additives de #22561 qui valent pour #22560 sont proposées en commentaire là-bas (invariant du dernier état, remise à zéro du curseur après écriture DOM, mesure du rendu à la frame).

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

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.

1 participant