Aller au contenu
learn

Journal

  • Mission et plan
  • Code du cours : rendu sans navigateur, check.sh, CI sous Linux, Windows et macOS
  • Leçon 1 : première portée, première tablature
  • Leçon 2 : techniques de guitare
  • Leçon 3 : armures, chiffrages, clés et accordages
  • Leçon 4 : étude de cas, le chatbot de GA écrit du VexTab
  • Leçon 5 : les objets de VexFlow lui-même, une voix stricte
  • Leçon 6 : TabStave et TabNote
  • Leçon 7 : rendre en React, tester avec Playwright
  • Leçon 8 : passer GA de VexFlow 4 à 5

Ce que le cours a trouvé dans les logiciels qu’il enseigne, et dans le code de Guitar Alchemist qui les utilise. Les liens VexTab pointent sur 3a5e00d, le commit à partir duquel la 4.0.5 de npm a été construite ; les liens VexFlow sur 0ca6f88, la 5.0.0 qu’elle embarque ; les liens GA sur 17ccee6. Chaque mesure est une sortie de check.sh, comparée en CI. Rien n’a encore été signalé en amont ; une recherche dans les issues de VexTab et de VexFlow n’a trouvé aucun signalement existant de ces constats.

Attendu Ce qui se passe Où Mesure Statut
strings=4 dimensionne le dessin pour quatre lignes de tablature L’option reste une chaîne ; VexFlow calcule la hauteur de la portée comme ("4" + 4) * 13 StaveBuilder.ts:141, VexTabParser.ts:86-89, VexFlow stave.ts:142 Dessin de 712 px de haut pour strings=4, 842 pour 5, 1102 pour 7, contre 270 pour six cordes ; pareil dans Chrome Reproduit sous Node et dans Chrome (leçon 3)
$G$ après un accord dessine le texte G Tout texte qui correspond à un nom de note remplace le numéro de frette de la corde la plus grave de l’accord, et aucune annotation n’est dessinée ArticulationBuilder.ts:362, :461 $G$ $C$ $D$ sur trois accords : 0 annotation, 3 numéros de frette remplacés ; $.big.G$ et $D $ sont dessinés comme du texte Reproduit. Documenté comme une fonctionnalité pour les notes seules ; un piège pour les noms d’accords (leçon 2)
$.italic.let ring$ est en italique VexTab passe le style comme troisième argument de VexFlow 5, la graisse ArticulationBuilder.ts:298-302, VexFlow element.ts:392 Le SVG dit font-weight="italic", sans font-style Reproduit
Le logo vexflow.com est centré et en italique Mesuré avant que sa police soit fixée, il est placé avec la largeur de la mauvaise police, et composé droit pour la même raison que ci-dessus ArtistRenderer.ts:262-266 x = 187,78 sur un dessin de 600 px avec notation (Chrome : 188,52) Reproduit sous Node et dans Chrome (H2)
X/6 est une note étouffée sur la corde 6 L’analyseur lexical lit X comme un nom de note, donc 6 devient une octave : la notation dessine une tête de note en x là où serait si6, à y = 0, à moitié hors du dessin vextab.jison:84, NoteBuilder.ts:264-266 Même position dans Chrome, à 0,67 px près Reproduit sous Node et dans Chrome (H3). La tablature est juste
L’accordage eb de VexFlow est l’accordage standard un demi-ton plus bas La corde 6 est Db/3, un ton plus bas VexFlow tuning.ts:16 Corde 6 à vide dessinée comme do♯3 (écrit), là où mi♭3 était voulu ; la ligne est inchangée sur la branche main de VexFlow Reproduit (leçon 3)
V dessine un vibrato dur VexTab n’appelle setHarsh que s’il existe, et le Vibrato de VexFlow 5 n’en a pas ArticulationBuilder.ts:635-640, VexFlow vibrato.ts 7v et 8V dessinent les trois mêmes glyphes U+EAB0 Reproduit
Cinq noires dans une mesure à 4/4 sont refusées Elles sont dessinées : les voix de VexTab sont en mode souple ArtistRenderer.ts:67 l01-overfull se rend Reproduit. Voulu, pour autant que le code le dise (leçon 1)
Les blocs vextab du chatbot de GA sont du VexTab Ils utilisent un format de jetons propre à GA, corde/frette, sans tabstave ni notes GA PlayableNotationFormatter.cs:15-25, :59-71 12 blocs sur 12 (8 accords pour débutants, l’exemple du prompt, 3 tests de bout en bout) rejetés par VexTab 4.0.5 et par l’analyseur F# de GA Corrigé en amont par #736, fusionnée le 2026-09-25 : les blocs sont du vrai VexTab, et les 10 blocs du formateur sont dessinés par VexTab 4.0.5 2026-09-25
Le client de chat de GA dessine les blocs vextab, comme l’affirme son test de bout en bout MemoizedVexTab les affiche dans un <pre> GA MemoizedVexTab.tsx:11-28, vextab-rendering.spec.ts:94-99 Lu, pas exécuté ; le test unitaire est en it.skip Corrigé par #736 : le client analyse le bloc et dessine une portée de tablature avec VexFlow 4.2.5. La spec de bout en bout ne tourne dans aucun workflow de GA, et ne pouvait pas passer telle qu’écrite 2026-09-25
Le champ de trace notation.renderer de GA dit ce qui a dessiné la notation C’est la constante "vexflow" GA OrchestratedChatApplicationService.cs:336 45 traces de référence : 44 avec added_count 0, une avec 8 Retiré par #736 : les traces comptent maintenant les blocs et ceux que lit l’analyseur de GA ; les 45 traces de référence fixent encore l’ancien champ tant qu’elles ne sont pas réenregistrées 2026-09-25
L’analyseur F# de GA lit ce qu’écrit son générateur, et les exemples de sa grammaire str, ch et pint mangent les blancs qui les suivent, y compris l’espace qui commence l’option de tabstave suivante GA VexTabParser.fs:22-29, :330 L’aller-retour échoue à la colonne 51 ou 52 pour 6 textes analysables sur 6 ; 0 exemple de l’EBNF sur 4 s’analyse Corrigé par #736 : les séparateurs sont explicites, et un test d’aller-retour et les exemples de la grammaire passent 2026-09-25
L’analyseur F# de GA accepte le VexTab Il diffère sur les techniques (après la corde), les bémols (b), les durées en milieu de ligne, les suites de frettes, les taps, les annotations et les tonalités mineures GA VexTabParser.fs:85, :239-244, :413-420 Sur 32 textes, l’analyseur de GA en accepte 6 et VexTab 17 ; ils s’accordent sur « ok » pour 4 Corrigé pour l’essentiel par #736 : les sept différences listées ont disparu ; manquent encore les lignes stave et voice, les liaisons, les legatos, les n-olets et quelques durées 2026-09-25
Question Hypothèse, écrite avant de mesurer Résultat Verdict
Le rendu sans navigateur (jsdom, texte mesuré avec opentype.js) place-t-il les glyphes là où Chrome les place ? H1 : à 1,0 px près en x et en y pour chaque élément de texte de l01-notation, l02-chords et l03-keys, si Chrome charge Bravura et Academico (hypotheses.md, commité dans 284eb7e avant tout passage dans un navigateur) 157 éléments de texte sur cinq dessins : |dx| max 0,74 px, |dy| max 0,67 px, tailles égales (browser-2026-09-24.txt). Les deux premiers essais étaient faux, voir l’entrée Confirmée
Le logo décentré est-il un artefact du rendu sans navigateur ? H2 : Chrome le dessine à x à 1 px près de 187,78. Pas à l’aveugle Chrome : 188,52 Confirmée
Chrome dessine-t-il lui aussi X/6 à l’octave 6 ? H3 : oui, au même y. Pas à l’aveugle Même position, à 0,67 px près comme ci-dessus Confirmée
Le dessin de 712 px de strings=4 est-il un artefact de jsdom ? H4 : le SVG de Chrome fait 712 px de haut. Pas à l’aveugle 600 × 712 Confirmée

Le vextab 4.0.5 de npm a été publié le 2026-01-18 ; ses sources sont identiques au commit 3a5e00d de 0xfe/vextab (vérifié fichier par fichier avec SHA-1). Son dist/main.prod.js embarque VexFlow 5.0.0, Vex.Flow.BUILD.ID 0ca6f889…, et recrée par-dessus l’espace de noms Vex.Flow de VexFlow 4. Installer vexflow à côté ne change rien pour VexTab ; le cours épingle quand même vexflow 5.0.0, pour la leçon 5. GA, de son côté, utilise VexFlow ^4.2.5, et embarque un vexflow.js 4.2.5 pour l’API de son chatbot.

Le bundle veut window, self, document et getComputedStyle ; jsdom les fournit. Ce qu’il ne fournit pas, c’est la mesure du texte : VexFlow mesure chaque glyphe avec un canvas. Premier essai, node-canvas 3.2.3 avec registerFont sur les fichiers OTF de Bravura et d’Academico : sous Windows, il ne charge pas ces polices à contours CFF et mesure en silence avec une police sans empattement de repli. Remplacé par un petit contexte qui mesure avec opentype.js à partir des mêmes fichiers OTF (lib/env.cjs), passé à VexFlow avec Element.setTextMeasurementCanvas. La sortie est la même sur les trois OS de la CI, donc les SVG peuvent être comparés octet par octet après renumérotation des identifiants et arrondi à deux décimales.

Hypothèses écrites et commitées d’abord (284eb7e). Puis les cinq mêmes fichiers passés par le bundle navigateur dans Chrome 153 sans interface, en relisant chaque <text> (browser/).

Le premier essai a donné un écart de 204 px sur le logo et des glyphes illisibles : la page de test n’avait pas de <meta charset="utf-8">, Chrome a décodé le bundle en Windows-1252, et chaque point de code SMuFL qu’il contient est devenu du mojibake. Une erreur de mesure, pas un résultat. Le deuxième essai était décalé d’un élément sur l02-vibrato-mute : compare.mjs ignorait les éléments <text> sans attribut y, et VexFlow n’en écrit pas quand y vaut 0, ce qui est le cas pour le glyphe de la note étouffée. Corrigé en lisant chaque attribut séparément, un attribut absent valant 0. Le troisième essai est celui du tableau : 0,74 px au plus, sur le logo.

Clone partiel sans blobs de GA à 17ccee6, neuf fichiers. Le formateur C# se compile seul ; les trois fichiers F# se compilent tels quels avec FParsec 1.1.1 sur .NET 10, comme GA le référence. Résultats dans la leçon 4. Ce que j’attendais en commençant : que les blocs du chatbot utilisent peut-être un ancien dialecte de VexTab. Ce qui en est sorti : ils n’utilisent aucun dialecte de VexTab, le client ne les dessine pas, et l’analyseur de GA rejette la sortie de son propre générateur. VexTab, lui, lit sans difficulté la sortie du générateur de GA. Rien n’a été envoyé à GA : les constats sont dans le rapport à l’utilisateur, qui décide.

  • #736, fusionnée le 2026-09-25, corrige les cinq lignes GA. Chaque changement a un test qui échoue sur l’ancien code : 51 des 57 tests d’aller-retour, 22 des 35 tests du formateur, le test de trace et 4 tests de dessin du client.
  • L’analyseur. str, ch et pint ne consomment plus les blancs qui les suivent. Le même défaut faisait lire à key=G suivi d’un saut de ligne le n du notes de la ligne suivante comme un bécarre. L’analyseur et le générateur suivent maintenant VexTab là où le tutoriel et vextab.jison sont clairs : techniques entre les cases (5h7/3), @ pour les bémols dans les notes, key=Am, durées en milieu de ligne, suites de cases, taps, annotations comme éléments de note, ordre des drapeaux de durée de VexTab. Passés dans le banc de ce cours sur 25 textes, GA et VexTab 4.0.5 sont maintenant d’accord sur chacun ; pour les 20 que les deux acceptent, le texte que GA réécrit dessine un SVG identique octet pour octet à celui de l’original. Pas fait, et listé dans la PR : les lignes stave et voice, les liaisons, les legatos, les n-olets, les durées :1 :2 :4 :64, et X comme nom de note.
  • Le chatbot. Ses blocs sont maintenant du VexTab : do ouvert s’écrit tabstave / notes :w (3/5.2/4.0/3.1/2.0/1), et le prompt demande cette forme. MemoizedVexTab analyse un bloc et dessine une portée de tablature avec VexFlow 4.2.5 ; un bloc qu’il ne peut pas dessiner en entier reste du texte, et data-renderer sur le bloc dit ce que voit le lecteur. La constante notation.renderer a disparu : le serveur ne dessine rien, donc les traces donnent maintenant notation.vextab.block_count et valid_count.
  • Ce que le cours laissait à vérifier. Aucun workflow de GA n’exécute les specs Playwright de ga-client : ci.yml ne fait que linter et construire le client. Et vextab-rendering.spec.ts ne pouvait pas passer telle qu’écrite, parce que son beforeEach clique sur un onglet « AI Chat Assistant » qui n’existe plus. Lu dans les workflows et la spec de GA, pas exécuté.
  • Les 45 traces de référence fixent l’ancien champ notation.renderer ; elles viennent d’exécutions réelles et doivent être réenregistrées sur une machine qui a le modèle. En lisant le client de chat, la même session a trouvé que /ai-copilot plantait dès son premier rendu ; c’est corrigé par #737.
  • L’accordage eb dans un navigateur : la valeur est dans la table de VexFlow et le dessin sans navigateur montre do♯3, mais la comparaison avec le navigateur n’incluait pas l03-tuning.
  • Firefox et Safari : la comparaison avec le navigateur n’a tourné que dans Chrome sans interface, sous Windows.
  • Si VexFlow 4, tel que GA l’utilise, a l’ordre d’arguments de setFont qui faisait d’italic un style : pas vérifié, puisque le cours épingle VexFlow 5.
  • Le remplacement de frette par les annotations en forme de nom de note est-il censé s’appliquer aux accords, ou seulement aux notes seules ? Le code l’applique à la corde la plus grave de n’importe quel groupe de notes.
  • VexTab devrait-il convertir strings= en nombre et passer ce nombre ? Un parseInt existe déjà, une ligne au-dessus de celle qui l’oublie.