Ir al contenido
learn

Diario

  • Programa del curso: .NET 10, con referencias a GA.Business.ML, FretboardVoicingsCLI y GaChatbot.Api en un commit fijado
  • CI: la salida de cada lección se compara con su archivo esperado en tres sistemas operativos, sin modelo, sin clave de API y sin GPU
  • Lección 1: el mapa
  • Lección 2: embeddings OPTIC-K
  • Lección 3: el índice y la búsqueda
  • Lección 4: el chatbot y sus agentes
  • Lección 5: la skill de improvisación y la teoría acorde–escala
  • Lección 6: la respuesta del chatbot en el cable
  • Lección 7: nombres de acorde que el chatbot no sabe leer
  • Lección 8: el propio examen del chatbot
  • Lección 9: cada intervalo, cada tonalidad
  • Lección 10: en qué se le dice al modelo que confíe
  • Lección 11: los acordes que lee la skill de tonalidad
  • Lección 12: lo que responden las skills de progresión
  • Lección 13: lo que responde el análisis de progresiones
  • Lección 14: lo que responde la skill de sustitución
  • Lección 15: las notas de un acorde
  • Lección 16: los voicings de un acorde
  • Lección 17: la cejilla y las afinaciones
  • Lección 18: la conducción de voces
  • Lección 19: los pares de voicings
  • Lección 20: las progresiones generadas
  • Lección 21: la búsqueda de voicings
  • Lección 22: los acordes parecidos
  • Lección 23: la distancia y el camino armónicos
  • Lección 24: las clases de conjuntos y el analizador Grothendieck
  • Lección 25: lo que llega a la skill de transposición
  • Lección 26: el catálogo de modos
  • Lección 27: las notas que suenan fuera
  • Ejecutar el chatbot con Ollama y capturar lo que responden los agentes (con fecha, fuera de la CI)

Los hallazgos 1 a 22, de las lecciones 1 a 4, están numerados en la entrada del 2026-09-14, y su estado upstream en la del 2026-09-24. Esta tabla empieza en la lección 5. ImprovisationSkill.cs es idéntico en a826864 y en el main de GA en 8cd5042 (2026-09-28), así que las filas 23 a 28 describen también la skill desplegada. Las filas 29 a 32, de la lección 6, dan su estado en main en la última columna. Las filas 33 a 38, de la lección 7, valen también para main en f4f4d30: los archivos que citan no han cambiado allí desde la #749. Las filas 39 a 45, de la lección 8, citan archivos que no han cambiado en main en fc76ad6 (2026-09-29), salvo el corpus, que ha pasado de 68 prompts a 75 sin que cambien las entradas que citan. Las filas 46 a 53, de la lección 9, citan archivos que no han cambiado en main en 53b7253, salvo ScaleInfoSkill.cs y RelativeKeySkill.cs, que allí solo han cambiado en CanHandle y en un indicador Declined en un rechazo por el que no pasa ninguna de las filas. Las filas 54 a 57, de la lección 10, valen para main en 53b7253: los SKILL.md que citan no han cambiado, y tampoco las funciones de DomainClosures.fs que citan. Las filas 58 a 64, de la lección 11, dan el comportamiento de main con el servicio en 6baf32e, que no ha cambiado en main en 5c3a52a, donde el SKILL.md no ha cambiado y la herramienta y la skill solo difieren del commit fijado en una línea using y en un indicador Declined. Las filas 65 a 72, de la lección 12, valen para main en 5c3a52a, donde ProgressionMoodSkill.cs, los dos SKILL.md y el borrador no han cambiado y ProgressionCompletionSkill.cs solo difiere del commit fijado en una línea using y en un indicador Declined; las filas 67 y 68 dan el comportamiento de main con el servicio en 6baf32e. Las filas 73 a 78, de la lección 13, dan el comportamiento de main con DomainClosures.fs y el servicio en 6baf32e, ambos sin cambios en main en 5c3a52a; las filas 73 y 74 describen el commit fijado, corregido desde entonces. Las filas 79 a 86, de la lección 14, valen en main en 5c3a52a, donde la skill, sus herramientas MCP, su SKILL.md, GrothendieckDelta.cs, DslEvalMcpTools.cs y GaDslTool.cs no han cambiado y FindNearby solo difiere en la prueba que deja la fuente fuera de su lista; la closure de la fila 85 se ejecutó en el commit fijado y en 6baf32e, igual que en main. Las filas 87 a 95, de la lección 15, valen en main en 5c3a52a, donde ChordInfoSkill.cs, ChordVocabulary.cs, ChordSpelling.cs, ChordMcpTools.cs y el SKILL.md no han cambiado. Las filas 96 a 100, de la lección 16, valen en main en f4f5b4a: las filas 96 a 98 proceden de TypedMusicalQueryExtractor.cs, ChordPitchClasses y el CanHandle de la skill, idénticos en el commit fijado, y las filas 99 y 100 se ejecutaron con la cadena de los voicings de main, en GaMain. Las filas 101 a 107, de la lección 17, valen en main en f4f5b4a: en main, CapoSkill solo añade el indicador Declined a su rechazo, y las filas 106 y 107 se ejecutaron también en main, en GaMain. Las filas 108 a 113, de la lección 18, valen en main en f4f5b4a, donde VoiceLeadingSkill.cs no ha cambiado. Las filas 114 a 117, de la lección 19, valen en main en f4f5b4a, donde CompositionTools.cs y los borradores de skill en espera no han cambiado; las filas 114 a 116 se ejecutaron también en main, en GaMain. Las filas 118 a 122, de la lección 20, valen en main en f4f5b4a, donde CompositionTools.cs, ChordPitchClasses, ChordProgressions.yaml y los borradores de skill en espera no han cambiado; la fila 121 se ejecutó también en main, en GaMain. Las filas 123 a 127, de la lección 21, valen en main en f4f5b4a, donde VoicingSearchTool.cs y VoicingVocabularyTool.cs solo difieren en un comentario y en una descripción, la skill voicing-search en una línea sobre otra herramienta, y el lector, el registro de tags y el borrador en espera no han cambiado; las filas 123, 124 y 126 se ejecutaron también en main, en GaMain. Las filas 128 a 131, de la lección 22, valen en main en f4f5b4a, donde IcvNeighborsSkill e IntervalClassVectorSkill solo marcan su rechazo con Declined, FindNearby compara el conjunto de origen por valor, y DefaultRoutingHintProvider y el borrador en espera no han cambiado; las filas 128 a 130 se ejecutaron también en main, en GaMain. Las filas 132 a 135, de la lección 23, valen en main en f4f5b4a, donde GrothendieckDeltaSkill e IcvShortestPathSkill solo marcan su rechazo con Declined, FindNearby compara el conjunto de origen por valor, y GrothendieckDelta y DefaultRoutingHintProvider no han cambiado; las cuatro filas se ejecutaron también en main, en GaMain. Las filas 136 a 140, de la lección 24, valen en main en f4f5b4a, donde SetTheoryEquivalenceSkill y GrothendieckParseSkill solo marcan su rechazo con Declined y el analizador Grothendieck no ha cambiado; las cinco filas se ejecutaron también en main, en GaMain. Las filas 141 a 144, de la lección 25, se ejecutaron en el commit fijado y en main en f4f5b4a, en GaMain, que ahora arranca el host del chatbot de main; TransposeSkill, su SKILL.md, las reglas de pistas y SkillMdPlugin no han cambiado allí, así que las filas 141 a 143 valen en main tal como están escritas, y la fila 144 da las respuestas de los dos commits. Las filas 145 a 149, de la lección 26, valen en main en f4f5b4a, donde ModesSkill.cs, Modes.yaml y ModesConfig.fs son los mismos archivos; solo se ejecutaron en el commit fijado. Las filas 150 a 154, de la lección 27, valen en main en f4f5b4a, donde OutsideNotesSkill.cs solo marca su rechazo con Declined y ChordVocabulary.cs es el mismo archivo; solo se ejecutaron en el commit fijado.

Esperado Lo que pasa Dónde Medición Estado
23. Una serie de símbolos de acorde se lee tal como está escrita Cmaj7#5 se lee como Cmaj7; C7sus4 y CmMaj7 desaparecen sin aviso, aunque mMaj7 es la etiqueta de arpegio de la propia skill ImprovisationSkill.cs líneas 453-462 l5: 15 de 17 acordes leídos, 1 de ellos recortado Reproducido; comunicado en #757
24. Cm7#5 es un acorde menor Se clasifica como aumentado: arpegio Caug, un E contra el E♭ del acorde; ninguna de las dos escalas propuestas tiene el E♭ línea 343 l5, tabla acorde por acorde Reproducido; comunicado en #758
25. El arpegio de Cm6 deletrea C E♭ G A CmMaj7, que toca B en lugar de A; la escala, la menor melódica, está bien línea 346 l5, tabla acorde por acorde Reproducido; comunicado en #758
26. C7#11 empieza por una escala que contiene F♯ El mixolidio, con F natural; el lidio dominante es la segunda opción líneas 360-436 l5, tabla acorde por acorde Reproducido; comunicado en #758
27. Los acordes suspendidos y de quinta conservan sus propias notas “unknown”: la etiqueta de arpegio es la fundamental sola, una tríada mayor, E contra el F del sus4 y el D del sus2 línea 283 l5, tabla acorde por acorde Reproducido; comunicado en #758
28. Las escalas principales de una progresión se quedan en su tonalidad, o la respuesta dice que la tonalidad es ambigua Jónico en las tríadas mayores y eólico en las menores, sea cual sea su grado: B♭ en F y F♯ en G sobre Am F C G, F♯ G♯ en A sobre C A Dm G, F♯ C♯ D♯ en E sobre Am Dm E; C G no se señala como ambigua líneas 212-261 l5: de 23 acordes en 7 progresiones (sin contar el acorde prestado), 11 iguales, 10 DIFF, 2 correctos solo en una de las dos tonalidades Comunicado en #744
29. Un cliente distingue una petición fallida de una respuesta El flujo responde HTTP 200 y envía {"error": …} como un evento cualquiera, sin [DONE]. La página de GaChatbot.Api muestra ese JSON como la respuesta del asistente y lo guarda en el historial de la conversación, que la siguiente petición devuelve al servidor index.html líneas 740-809, línea 984 l6, tabla del fallo, a través de la versión de la página portada por el curso Reproducido en la versión portada, no en un navegador; comunicado en #760
30. Los fragmentos transmitidos se vuelven a unir en la respuesta SseChunker divide con (?<=[.!?])\s+, que elimina el espacio en blanco entre frases: la respuesta de improvisación pierde 6 de sus 8 saltos de línea y su lista se muestra como una sola viñeta SseChunker.cs líneas 19-29 l6, frases: 552 de 558 caracteres Corregido upstream por la #743, fusionada el 2026-09-28; el curso ejecuta la versión fijada y una copia de la corrección
31. Todas las líneas de texto sobreviven al flujo de GaApi data: {chunk} sin prefijo en las demás líneas del fragmento: una línea en blanco dentro de un fragmento termina el evento, y la línea siguiente se pierde para todos los lectores GaApi ChatbotController.cs líneas 318-322 l6, tabla de parejas: se pierden 1 de 6 líneas y 8 saltos de línea, con las dos divisiones Comunicado upstream: #746, abierta; sin cambios en main en 8621c3e. Latente: ningún componente de ga-client lee ese flujo
32. El cliente SSE de ga-client conserva todas las líneas de un evento parseSseBuffer conserva la primera línea data: de cada evento y la recorta, así que pierde una línea y todos los saltos de línea incluso con el escritor de GaChatbot.Api chatService.ts líneas 41-48 l6, tabla de parejas La mitad cliente de los criterios de aceptación de la #746; ningún llamador en a826864
El oráculo da una escala enseñada para cada acorde Para un acorde prestado, F menor en C, su regla da F G A♭ B C D E, que no es una escala enseñada; la respuesta habitual es F dórico code/ga-ai/GaAi/Lesson5.cs, Textbook l5, C Fm G C Un límite del oráculo del curso, no de GA; documentado en la lección 5
33. Una petición con nombres de acorde en minúsculas se rechaza, o la respuesta dice que no sabe leerlos which arpeggio fits hm q7 pasa la guarda de la #749, cuyas fundamentales son las mayúsculas de H a Z, y sigue hasta el modelo InvalidChordNames.cs línea 97 l7, fila 5 Comunicado en #759
34. Se señala una cualidad desconocida sobre una fundamental válida Cq7 pasa la guarda y sigue hasta el modelo InvalidChordNames.cs líneas 41-59 l7, fila 6 Fuera de alcance según la descripción de la #749; comunicado en #759
35. Un acorde no válido junto a otros válidos se nombra en la respuesta Am F Q7 G se responde para Am, F y G, y Q7 desaparece sin aviso; C and Q7 sigue hasta el modelo InvalidChordNames.cs líneas 41-59, ExtractChordRun l7, filas 13 y 14 Por diseño en la #749 (“keeps its route”, conserva su ruta); comunicado en #759, y el descarte silencioso en #757
36. Se leen los signos de bemol y de sostenido B♭ E♭ F se responde como B, E y F: B jónico para B♭. Las expresiones de la skill solo admiten [#b]; las skills de cejilla y de afinaciones alternativas de GA prevén ♭ y ♯, pero a menudo los pierden (filas 103 y 106) ImprovisationSkill.cs líneas 447-462 l7, fila 9 Comunicado en #757
37. Un cifrado que termina en #, + o ° se lee entero F# se lee como F y C+ como C: ChordTokenRegex termina en \b, y tras esos caracteres no hay límite de palabra, así que la coincidencia retrocede hasta la fundamental sola línea 461 l7, filas 10 y 11 Comunicado en #757
38. Se lee Bø7 Queda fuera de la serie sin aviso: la lista tiene °7 pero no ø7, y ø es una letra, así que ningún límite lo separa del 7 línea 461 l7, fila 12 Comunicado en #757
El reconocedor del curso lee bien todas las palabras de un mensaje Lee la interjección con la que empieza “Hm, which mode is brightest?” como un cifrado de acorde roto; la guarda de GA se la salta, que es lo correcto code/ga-ai/GaAi/Lesson7.cs, Read l7, fila 15 Un límite del reconocedor del curso, no de GA; documentado en la lección 7
39. Una respuesta errónea no supera la comprobación del corpus El #26, “modes of melodi minor”, recibe los modos de la escala mayor y pasa: la línea de sugerencia con la que termina toda respuesta sobre una familia basta para satisfacer su contains_any prompts.yaml líneas 270-276, ModesSkill.cs línea 449 l8, #26 Comunicado en #763
40. Una familia mal escrita recibe su respuesta, o la respuesta dice que no se ha reconocido “melodi minor” cae en la rama por defecto, que enumera los modos de la escala mayor sin aviso ModesSkill.cs líneas 202-207 l8, #26 Comunicado en #765
41. Un mensaje de error no supera la comprobación del corpus El #31 pasa con “I encountered an error processing your request. Please try again.”: su contains_any contiene G, que está en “processing” prompts.yaml líneas 316-322, PromptCorpusTests.cs líneas 367-379 l8, #31 Comunicado en #763
42. Una skill que no llega a su modelo se señala como backend degradado Una skill de Path B sin modelo responde con el texto de error de SkillMdDrivenSkill, que no está entre los BackendDegradedMarkers: seis fallos y un aprobado en lugar de siete veces “sin señal” SkillMdDrivenSkill.cs líneas 204-226, PromptCorpusTests.cs líneas 54-75 l8, #10 y la primera tabla Comunicado en #764; las ejecuciones diarias de GA, por verificar
43. El log de una skill dice lo que ha pasado DiatonicChordsSkill registra que el modelo “produced an answer without invoking ga_dsl_eval” cuando no se llegó a ningún modelo SkillMdDrivenWrapperBase.cs líneas 107-136 l8, #10 Comunicado en #764
44. Las comprobaciones del corpus distinguen una respuesta de la respuesta a otra pregunta Subcadenas sin distinción de mayúsculas, 84 de las 224 de un solo carácter: los prompts que pasan aceptan 169 de las otras respuestas, y 6 de 15 respuestas subidas un semitono, entre ellas Drop C# para drop C PromptCorpusTests.cs líneas 367-379 l8, primera tabla del semitono Comunicado en #763; la lectura más estricta del curso acepta 69 y 4
45. La fórmula de una escala corresponde a sus notas Las fórmulas se calculan por posición frente a C mayor: #6 para el B♭ de la escala de tonos enteros, y 1 b2 b3 b4 b5 bb6 bb7 bb8 para C D♭ E♭ E F♯ G A B♭ ModesSkill.cs líneas 779-811 l8, #38 y #39 Comunicado en #765
La prueba del semitono del curso convierte toda respuesta en errónea Solo para un prompt que nombra una altura; para los demás, la respuesta desplazada sigue siendo correcta, y la tabla dice n/a. El curso solo reconoce un nombre de nota en la pregunta cuando va en mayúscula, así que el #30, “notes in c major”, también dice n/a code/ga-ai/GaAi/Lesson8.cs, Transpose l8 Un límite de la prueba del curso, no de GA; documentado en la lección 8
46. La skill de intervalos lee un sostenido en la segunda nota El \b final de su expresión devuelve el #: de E a G# sale una tercera menor, de C a F# una cuarta justa; 147 de 441 preguntas IntervalSkill.cs líneas 62-64 l9, las columnas # de la cuadrícula Comunicado en #767; la misma causa que la #757, en otra expresión
47. La skill de intervalos lee ♯ y ♭ De C a F♯ sale una cuarta justa; B♭ a D no se puede leer IntervalSkill.cs líneas 62-64 l9, “written another way” Comunicado en #767
48. Un unísono rebajado es un unísono disminuido De C# a C sale un unísono justo de 0 semitonos: los semitonos se toman módulo 12, y una diferencia que el switch no cubre cae en su rama por defecto; 21 unísonos de 441, y otros 5 intervalos con Cb, Fb, E# o B#. Lo mismo con el dominio de main NoteExtensions.cs línea 110, líneas 13-56 l9, “the note names read right” Comunicado en #768
49. Toda cualidad de intervalo se escribe completa Doblemente aumentado y doblemente disminuido se imprimen como AA y dd: 27 de 441 respuestas IntervalNaming.cs líneas 56-64 l9, las casillas a de la cuadrícula Comunicado en #767
50. Dos skills dan la misma tonalidad relativa ScaleInfoSkill toma la primera tonalidad con las mismas clases de altura: B mayor → A♭ menor, G♯ menor → C♭ mayor, 6 de 30 tonalidades; RelativeKeySkill, corregida por esto en mayo, da G♯ menor y B mayor KeyNaming.cs líneas 55-65, RelativeKeySkill.cs líneas 119-125 l9, la tabla de tonalidades Comunicado en #769
51. La armadura de una tonalidad es correcta, o la tonalidad se rechaza D♯, G♯ y A♯ mayor y D♭ y G♭ menor tienen “no sharps or flats” (ni sostenidos ni bemoles); la homónima menor de G♯ mayor tiene “3 flats” RelativeKeySkill.cs líneas 208-212 l9, “keys past seven” Comunicado en #769
52. Una tonalidad que se lee en una pregunta se lee en las demás C♭ mayor se lee para su relativa menor y se rechaza para su armadura, con un mensaje que pide una letra seguida de # o b RelativeKeySkill.cs líneas 72-81, líneas 245-251 l9, después de la tabla de tonalidades Comunicado en #769
53. Una skill responde a sus propios prompts de ejemplo IntervalSkill no sabe leer 8 de sus 13, cinco definiciones y tres preguntas como “Minor third up from D”; ScaleInfoSkill, 3 de sus 24 IntervalSkill.cs líneas 27-52, ScaleInfoSkill.cs líneas 23-91 l9, última sección Los de IntervalSkill, comunicados en #767; los de ScaleInfoSkill, no; lo que sirve el chatbot para ellos, por verificar
54. Los acordes diatónicos de una tonalidad se escriben con una letra por grado domain.diatonicChords nombra cada acorde con un array de doce nombres con sostenidos o con bemoles, elegido según la tónica: D, G y C menor reciben A♯, D♯ y G♯, y C♭, F♭, E♯ y B♯ salen como B, E, F y C; 11 de 30 tonalidades DomainClosures.fs líneas 22-36, línea 187 l10, la tabla de tonalidades Comunicado en #770
55. El SKILL.md de diatonic-chords describe lo que devuelve la closure Promete una ortografía correcta en “Gb major, F# minor” y dice que G♭ mayor “returns Cm”; la closure devuelve B para el C♭ de G♭ mayor, y Bdim donde el SKILL.md muestra B° skills/diatonic-chords/SKILL.md línea 26, DiatonicChordsSkill.cs líneas 27-32 l10, “los ejemplos del SKILL.md” Comunicado en #770
56. Un acorde transpuesto se escribe según el intervalo domain.transposeChord recibe semitonos y nombra el resultado con el array de la fundamental de origen: una tercera menor por encima de C es D♯, “Transpose G7 to Eb” da D♯7, y B♭ subido un tono y bajado de nuevo es A♯; 70 de 252 sobre otra letra, incluso C♭ desplazado 0 semitonos, y 30 de ellas donde el manual necesita una doble alteración DomainClosures.fs líneas 159-162, skills/transpose/SKILL.md línea 42 l10, la cuadrícula de transposiciones Comunicado en #770
57. Las notas comunes se escriben como las escriben los acordes domain.commonTones nombra cada nota compartida solo por su clase de altura: A y C♯m comparten “Db”; 144 de las 630 parejas de tríadas de las 30 tonalidades DomainClosures.fs líneas 263-266, línea 523 l10, la tabla de notas comunes Comunicado en #770
58. La skill de tonalidad lee todos los acordes de la pregunta En el commit fijado, ExtractChords se salta todos los símbolos con una cifra justo detrás de una letra, porque su \b final falla entre dos caracteres de palabra: las 30 preguntas de la lección 11 con acordes de séptima los pierden todos. En main, CM7, CΔ7 y Cø7 se siguen saltando KeyIdentificationService.cs línea 211 l11, la tabla de lectura y la cuadrícula Corregido en main por la #625 para los símbolos con cifras; CM7, CΔ7 y Cø7, comunicados en #771
59. Un sostenido al final de un cifrado se conserva El \b final falla entre # y un espacio: F# y C# se leen como F y C en las dos versiones. Además, B♭ y F♯ se leen como B y F, C° como una tríada de C mayor, y C/E como dos acordes KeyIdentificationService.cs línea 211, línea 325 en main l11: 16 de 90 preguntas leen otros acordes en main Comunicado en #771; la misma causa que la #757 y la #767, en otra expresión
60. Las tonalidades con las mismas clases de altura se distinguen por la grafía de la pregunta Esas tonalidades empatan y decide el nombre: para D♭ G♭ A♭ D♭, A♯ menor va primero en el commit fijado y C♯ mayor en main, donde 13 de 90 preguntas reciben primero la gemela enarmónica de la tonalidad KeyIdentificationService.cs línea 178, líneas 224-227 en main l11, las ~ de la cuadrícula de main Comunicado en #772
61. Un acorde repetido conserva su lugar en la progresión ExtractChords descarta los acordes repetidos, así que el peso de cadencia de main nunca ve la vuelta a I y oye D G como V–I de G mayor: C D G C se lee como C D G y se responde G mayor; en las 11 tonalidades de I II V I cuyos acordes se leen, la tonalidad de la dominante, o su gemela enarmónica, va primero línea 299 en main, líneas 231-246 l11, las x de la cuadrícula Comunicado en #771
62. Las coincidencias principales son las tonalidades clasificadas primero La herramienta y la skill conservan las tonalidades cuyo recuento es igual al de la primera, mientras que main clasifica por recuento más cadencia: C♯m7b5 F♯7 Bm recibe un grupo de cabeza de seis tonalidades con 1/3, y G♯ menor, con 2/3, queda entre las coincidencias parciales; con los acordes C D G C, el grupo de cabeza deja fuera G mayor (3/3) y las coincidencias parciales repiten dos tonalidades del grupo de cabeza KeyIdentificationMcpTools.cs líneas 66-75, KeyIdentificationSkill.cs líneas 62-63 l11: 2 de 90 preguntas en main, y C D G C como lista Comunicado en #772
63. La tonalidad relativa de una tonalidad se escribe a partir de esa tonalidad El servicio toma la primera tonalidad del otro modo con las mismas clases de altura: B mayor → A♭ menor, G♯ menor → C♭ mayor; 6 de 30 tonalidades, en las dos versiones KeyIdentificationService.cs líneas 93-101 l11, las tonalidades relativas Comunicado en #772; la misma búsqueda que la de ScaleInfoSkill en la #769
64. Los ejemplos del SKILL.md de key-identification describen lo que devuelve la herramienta Su ejemplo de un solo candidato en cabeza es “The progression Dm G C is in C major (3/3 chords diatonic)”; la herramienta devuelve C mayor y A menor, empatadas, en las dos versiones. Su línea 81 dice que la herramienta “doesn’t distinguish a Cmaj7 from a C” (no los distingue); en el commit fijado, ni siquiera lee Cmaj7 skills/key-identification/SKILL.md línea 60 l11, los prompts de ejemplo Comunicado en #772
65. La skill de ambiente responde con el ambiente que pide el prompt 6 de sus 8 prompts de ejemplo que piden más luminosidad reciben las cinco maneras de oscurecer: la prueba busca “brighter”, “uplift” y “happier”, y no ve “Brighten”, “brightness” ni “lift the mood”. Son los seis prompts de luminosidad añadidos el 2026-05-12 para corregir enrutamientos erróneos ProgressionMoodSkill.cs línea 61 l12, la tabla de ambientes Comunicado en la #773
66. El texto de la skill de ambiente escribe cifrados de acorde, como su SKILL.md C bA G y C bB F: bA y bB no son ni cifrados de acorde ni números romanos. El SKILL.md escribe Ab y Bb, pide su lista de técnicas al pie de la letra y difiere del texto de C# en la segunda técnica de cada rama líneas 74 y 77, SKILL.md línea 38 l12, las progresiones de los dos textos Comunicado en la #773
67. Los acordes que ofrece la skill de continuación pertenecen a la tonalidad de la pregunta La lista sale de la primera tonalidad, y en el commit fijado los empates se resuelven por nombre: G Em C recibe los acordes de C mayor, sin D; 6 de las 15 tonalidades mayores para I vi IV ProgressionCompletionSkill.cs líneas 93-107, KeyIdentificationService.cs línea 178 l12, la cuadrícula: x 6 en el commit fijado, 0 en main Corregido en main por la #729
68. La lista se escribe como la pregunta D♭ B♭m G♭ recibe A#m, B#dim, C#, D#m, E#m, F#, G# en el commit fijado y los acordes de C♯ mayor en main ProgressionCompletionSkill.cs línea 107 l12, la cuadrícula: e 4 en el commit fijado, 5 en main Comunicado en la #774; la misma causa que la #772
69. La lista de una tonalidad menor permite al modelo construir una cadencia auténtica La lista es la de la menor natural: el V mayor no está en ninguna de las listas de las 15 tonalidades menores. El prompt permite V7 “even if only V appears” (aunque solo aparezca V), lo que en menor nunca ocurre; el SKILL.md permite V7 y prohíbe cualquier acorde que no esté en la lista líneas 117-119, SKILL.md líneas 71 y 96 l12, la tabla de la dominante Comunicado en la #774
70. El ejemplo del prompt sigue las reglas del prompt Sugiere E7 como V7–i de A menor, fuera de la lista de A menor, y G como semicadencia, “bVII-i”, aunque una semicadencia termina en V y G es el séptimo grado líneas 130-131 l12, el prompt y la tabla de la dominante Comunicado en la #774
71. El ejemplo del SKILL.md de progression-completion describe lo que devuelve la herramienta Dice C mayor primero, “also tied with A minor” (empatada también con A menor), con B°; en el commit fijado la herramienta pone primero A menor, empata también G mayor y E menor, y escribe Bdim. Su respuesta sugiere Dm → G7, en contra de su propia restricción estricta. Llama raro a un empate con otra escala: 13 de las 25 preguntas leídas tal como están escritas tienen uno SKILL.md líneas 56, 86, 92 y 96 l12, los ejemplos y la cuadrícula Comunicado en la #774
72. La prueba de palabras clave de una skill acepta sus propios prompts de ejemplo ProgressionCompletionSkill.CanHandle rechaza “What chord comes next after C G Am?” y “Help me end Am F G”; ProgressionMoodSkill.CanHandle devuelve false. En main, el enrutador recurre a estas pruebas cuando no puede calcular el embedding de una pregunta; en el commit fijado, nada las llama ProgressionCompletionSkill.cs líneas 35-45, SemanticIntentRouter.cs línea 321 en main l12, la tabla de palabras clave Comunicado en la #773 y la #774
73. La tonalidad de una progresión depende de la calidad de sus acordes En el commit fijado solo cuentan las fundamentales: Am Dm E Am está en A mayor, Dm7 G7 Cmaj7 en D menor, F G C en F mayor; 90 de las 120 preguntas de manual reciben otra tonalidad, entre ellas las 60 en tonalidad menor DomainClosures.fs líneas 268-270, líneas 308-316 l13, la cuadrícula: x 90 en el commit fijado, 0 en main Corregido en main por la #625
74. Un número romano sigue la calidad del acorde En el commit fijado, el número es el del grado en la tabla de la tonalidad, sea cual sea el acorde: D y Dm son ambos ii en C mayor, y Fm Bbm C7 Fm es I IV V I en F mayor líneas 257-260, líneas 272-276 l13, los cuatro ejemplos del borrador: 2 correctos en el commit fijado, 4 en main Corregido en main por 6baf32e
75. La tonalidad se nombra como la escribe la pregunta En el commit fijado, el nombre sale de la clase de altura: C♯, G♭ y C♭ mayor vuelven como D♭, F♯ y B mayor. En main, es el nombre que Identify pone primero, con las tonalidades de las mismas clases de altura ordenadas por nombre: C♭, G♭ y D♭ mayor vuelven como B, F♯ y C♯ mayor, y E♭, B♭ y G♯ menor como D♯, A♯ y A♭ menor líneas 262-266, KeyIdentificationService.cs líneas 224-227 en 6baf32e l13, la cuadrícula: e 6 en el commit fijado, 21 en main No comunicado; la misma causa que la #772
76. El vii° de una tonalidad menor recibe un número romano En main, romanFor busca la fundamental entre las siete notas de la escala natural: vii°7 recibe ? en las 15 tonalidades menores, igual que bIII y bVI en C mayor DomainClosures.fs líneas 353-374 en 6baf32e l13, la cuadrícula: n 15 en main; los acordes prestados Comunicado en la #775
77. Los acordes prestados dejan la tonalidad en el acorde con que la progresión empieza y termina En main, Identify cuenta los acordes diatónicos antes de mirar el acorde inicial, y después prefiere la tonalidad mayor y luego el nombre: C Bb F C está en F mayor, V IV I V, y C Ab Bb C en E♭ mayor, VI IV V VI, una tonalidad en la que el acorde de C mayor no es diatónico; solo la confianza, 2/4, lo deja ver KeyIdentificationService.cs líneas 224-227 en 6baf32e l13, los acordes prestados Comunicado en la #775
78. La confianza cuenta el ii y el vii° de una tonalidad menor como propios En main, NormalizeChord reduce Bm7b5 a Bm, una tríada menor: Bm7b5 E7 Am queda en 2/3, e iiø7 V7 i queda por debajo del número de acordes en las 15 tonalidades menores. G♯dim7 no está en la menor natural, pero F##dim7 se lee como F♯ mayor, el VII de G♯ menor, y cuenta KeyIdentificationService.cs línea 319 en 6baf32e, línea 132, líneas 145-150 l13, la cuadrícula: por debajo del número de acordes para iiø7 V7 i en 15 tonalidades, para i iv vii°7 i en 12 Comunicado en la #775
79. La lista de sustitutos depende del acorde FindNearby pone todos los acordes de la clase de conjuntos de la fuente al mismo coste, el más bajo, y la skill se queda con los cinco de máscara de bits más pequeña: las listas de las 12 tríadas mayores nombran seis acordes, Cm C Ab Dbm Fm Db; la de G7 no tiene D♭7; los acordes de séptima mayor y de séptima menor no reciben un sustituto de manual en ninguna de las 12 fundamentales; 29 de los 60 acordes propuestos para las tríadas mayores no comparten ninguna nota con su fuente ChordSubstitutionSkill.cs líneas 164-174, GrothendieckService.cs líneas 55-81 l14, un acorde: 108 acordes; ga_chord_substitutions igual en los 108 Comunicado en la #777
80. Vectores interválicos iguales están a distancia 0 GrothendieckDelta.FromIcVs escribe 1 en lugar de una diferencia nula: C y C, C y Am, G7 y D♭7 están a L1 1; cada sustituto propuesto cuesta 0.60, y cada par de una misma clase de conjuntos es “ICV Neighbor (L1 = 1)”. Los ejemplos del SKILL.md, costes de 0.50 y 0.83 y un L1 de 0, no pueden darse GrothendieckDelta.cs líneas 125-131, SKILL.md líneas 100-108 l14, las cuatro líneas de ComputeDelta Comunicado en la #776
81. La comparación nombra lo que nombra un manual Un v menor es “Secondary Dominant”, solo por las fundamentales. Am y C, que comparten dos notas, F♯m y C, que no comparten ninguna, y C consigo mismo reciben las mismas etiquetas, “Set-Class Equivalent” e “ICV Neighbor (L1 = 1)”; también Em7b5 y C7, que comparten tres ChordSubstitutionSkill.cs líneas 261-264, líneas 279-290 l14, dos acordes, en las 12 fundamentales; ga_chord_compare igual Comunicado en la #777
82. La respuesta sigue la relación que nombra la pregunta Un solo acorde recibe la lista, pregunte lo que pregunte: “Tritone substitution for G7”, “What’s the secondary dominant of Am?” y “Show me a backdoor dominant for C major” no obtienen D♭7, E7 ni B♭7. Un nombre de tonalidad y un artículo se leen como acordes: “Alternative chord for F major in C” compara F con C, “A substitute for G7?” A con G7 ChordSubstitutionSkill.cs líneas 146-160, líneas 69-71 l14, los prompts de ejemplo; lo que lee la skill Comunicado en la #777
83. La skill lee los símbolos que lista su SKILL.md Ni la skill ni ga_chord_substitutions leen Cmin7, aunque el SKILL.md lista min7; B♭7 se lee como B mayor ChordSubstitutionSkill.cs líneas 69-71, ChordSubstitutionMcpTools.cs líneas 230-232, SKILL.md línea 92 l14, lo que lee la skill Comunicado en la #777; B♭ leído como B es lo mismo que la #757
84. CanHandle acepta los prompts de ejemplo de su skill substitut\b y reharmoni\b no reconocen ninguna palabra, y “secondary dominant”, “backdoor”, “replace” y “modal interchange” no tienen disparador: acepta 4 de 12. En main, el enrutador recurre a CanHandle cuando no puede calcular el embedding de una pregunta ChordSubstitutionSkill.cs líneas 59-75, SemanticIntentRouter.cs línea 321 en main l14, los prompts de ejemplo: 4 de 12 Comunicado en la #777
85. ga_dsl_eval ejecuta una closure sin las entradas que su esquema llama opcionales domain.chordSubstitutions declara key y scale como string?, con valores por defecto, pero ga_dsl_eval exige todas las entradas: missing-required-arg. Cinco entradas de dos closures están marcadas como opcionales. Sin tonalidad, la closure toma la fundamental del acorde en mayor: Am recibe los acordes de A mayor DslEvalMcpTools.cs líneas 257-270, DomainClosures.fs líneas 557-559 l14, la closure Comunicado en la #778
86. La descripción de una herramienta coincide con su respuesta El GaChordSubstitutions de GaMcpServer promete, para Am en C mayor, “C (★★★, relative major), Em (★★, shared E/B), F (★, shared A)”; la closure da dos estrellas a C y a F, con dos notas comunes cada uno, y una a Dm y a Em GaDslTool.cs línea 212, DomainClosures.fs línea 614 l14, la closure Comunicado en la #778
87. Solo el nombre de un acorde se lee como su fundamental El artículo “a” delante de “chord” pasa a ser la fundamental A: “what makes a chord a major seventh”, “what makes a chord diminished” y “what makes a chord a dominant seventh”, tres prompts de ejemplo, reciben “A major chord contains A, C#, and E”. La expresión de los cifrados no distingue mayúsculas de minúsculas, así que “am” es A menor en “I am learning Cmaj7, what notes are in it?” y en “Am I right that G7 has an F?”; la expresión de las notas lee el artículo de “Which chord has a C, an E and a G?”: A menor 7 ChordInfoSkill.cs líneas 302-303, línea 315, línea 325 l15, los prompts de ejemplo: 3 de 3; más allá del vocabulario; las listas de notas Comunicado en la #782
88. La skill lee sus propios prompts de ejemplo “anatomy of a D7sus4 chord”, “what is a C add 9 chord” y “tones in a Bb diminished seventh” reciben “Could not parse a chord name from your question.”: la expresión de los cifrados no tiene 7sus4 ni “add 9” con espacio, y el tercer prompt no tiene ni “chord” ni cifrado. CanHandle rechaza además “Tell me the tones in F#m7b5” y “break down Gmaj13 for me”, que la skill responde; en main, el enrutador recurre a CanHandle cuando no puede calcular el embedding de una pregunta ChordInfoSkill.cs líneas 100-110, líneas 267-282, SemanticIntentRouter.cs línea 321 en main l15, los prompts de ejemplo: 26 de 29 correctos, CanHandle 27 de 32 Comunicado en la #782
89. La skill lee los sufijos que conoce su vocabulario 22 de 82 no se leen, o se leen como otra calidad: los cifrados +, 5, no3, dom7, ma7, Δ7, -7, °7, min7b5, ø y ø7, 7+5 leído como séptima de dominante, y diez palabras, entre ellas “power”, “dominant” y “diminished 7”. La fórmula del acorde de quinta queda fuera de alcance. El comentario de la expresión de los cifrados cuenta + y “power 5/no3” entre las formas que lee ChordInfoSkill.cs líneas 302-316, ChordVocabulary.cs líneas 59-104 l15, cada sufijo: 60 de 82 Comunicado en la #782
90. El Δ7 del vocabulario es una séptima mayor NormalizeQuality pasa el sufijo a minúsculas antes de su segundo switch, y ToLowerInvariant convierte Δ en δ: la rama "Δ7" no puede coincidir, y δ7, que GetFormula no conoce, recibe una tríada mayor, como toda calidad desconocida. Ninguna de las dos expresiones de la skill lee Δ ChordVocabulary.cs línea 66, línea 82, línea 140 l15, cada sufijo: NormalizeQuality("Δ7") devuelve δ7 Comunicado en la #783
91. Un cifrado leído en parte no recibe la respuesta de un acorde más pequeño Tras el sufijo, la expresión de los cifrados acepta #, (, / y +: Cmaj7#11 recibe la respuesta de Cmaj7, C7#11 y C7(b9) la de C7, Cm(maj7) la de Cm, C6/9 la de C6, C7#5#9 la de C7#5 y C7+5 la de C7, y la respuesta no dice qué ha dejado fuera. La skill de improvisación de la lección 5 hace lo mismo, fila 23 ChordInfoSkill.cs línea 315 l15, más allá del vocabulario: 6 cifrados; cada sufijo: 7+5 Comunicado en la #782
92. La skill nombra los acordes que deletrea Si se le devuelven sus propias grafías, nombra las 293 con alteraciones simples y ninguna de las 106 con una alteración doble o triple: la expresión de las notas descarta Bbb y lee C## como C♯, así que C E♭ G♭ B♭♭, su Cdim7, es C disminuido y F♯ A♯ C♯♯ es F♯ mayor. ChordVocabulary.PitchClasses tampoco tiene ningún nombre con dos alteraciones. B♭ se lee como B: C E G B♭ es C mayor 7 ChordInfoSkill.cs líneas 325-326, ChordVocabulary.cs líneas 23-32 l15, el viaje de ida y vuelta: 0 de 106 nombrados de nuevo Comunicado en la #782; B♭ leído como B es lo mismo que la #757
93. La lectura de notas conoce los acordes que la skill deletrea 7b9 y 7#9 tienen cinco notas, dentro del límite, pero no están entre sus 19 fórmulas: “What chord is C E G Bb Db” se rechaza, aunque “What is C7b9” deletrea esas notas y el corpus de GA hace las dos preguntas. “What chord is C E G# B”, el ejemplo que da el propio comentario de la lista, se rechaza: Cmaj7♯5 no está en la lista ChordInfoSkill.cs líneas 236-265, líneas 261-262 l15, el viaje de ida y vuelta: 0 de 42; las listas de notas Comunicado en la #782
94. Una nota se escribe como el intervalo que la nombra La fórmula del acorde de dominante alterado pone su “flat fifth” tres letras por encima de la fundamental: F♯ para C y F♯♯ para C♯, donde la quinta disminuida es G♭ y G ChordVocabulary.cs línea 130 l15, la grafía: los 21 acordes que difieren, todos 7alt Comunicado en la #783
95. ga_chord_info lee los cifrados que lista su SKILL.md La expresión propia de la herramienta lee 14 de los 51 cifrados del vocabulario y rechaza Cdom7, que figura en la tabla del SKILL.md. El SKILL.md hace que el modelo rechace los acordes suspendidos y de nota añadida, los de novena, oncena y trecena, las dominantes alteradas y las listas de notas, que la skill de C# responde ChordMcpTools.cs líneas 81-82, SKILL.md línea 68, líneas 95-102 l15, la herramienta: 15 de 16; cada sufijo: 14 de 51 Comunicado en la #783
96. Una cualidad escrita en palabras se lee como esa cualidad “minor” se lee como un modo y el acorde como una tríada mayor: “voicings for A minor” se lee como A mayor con el modo minor, y en main el ejemplo “open chord shape for E minor” recibe ocho voicings de E mayor. En “voicings for C …”, las 31 cualidades en palabras de la lección 15 se leen como C mayor, y solo “major” sale bien. Después, el índice descarta el modo (fila 100) TypedMusicalQueryExtractor.cs líneas 90-102, líneas 104-111, líneas 217-226 l16, las palabras: 1 de 31; l16 (main), “open chord shape for E minor”: other 8 Comunicado en la #785
97. CanHandle acepta los acordes que la skill responde Rechaza su propio ejemplo “quartal voicings in C”, todos los acordes mayores sin sufijo (“voicings for C”, “G chord shapes”, “Bb voicings please”), el acorde con barra “voicings for C/G” y, en el ejercicio 3, “voicings for C-7”: una fundamental sola, / y - no coinciden con ninguna de sus dos expresiones. Acepta 13 de las 31 cualidades en palabras, las que empiezan por “major” o “minor”: dim y aug tienen que cerrar la palabra. En main, el enrutador recurre a CanHandle cuando no puede calcular el embedding de una pregunta ChordVoicingsSkill.cs líneas 57-73, líneas 178-185, SemanticIntentRouter.cs línea 321 en main l16, los ejemplos: 11 de 12; otras formulaciones: 4 de 10; las palabras: 13 de 31 Comunicado en la #785
98. Los dos lectores de cifrados del chatbot coinciden ChordPitchClasses, que lee el acorde de una petición de voicings, lee 47 de los 51 cifrados de la lección 15 tal como los escribe un manual: en Cdom7, Cma7 y C7+5 no lee ningún acorde, y C-7 se lee como C7, porque la comprobación del residuo toma - por un separador. Lee cinco cifrados de forma distinta que ChordVocabulary, que usa ChordInfoSkill: dom7, ma7, Δ7, -7 y 7+5 MusicalQueryEncoder.cs líneas 240-336, línea 335, ChordVocabulary.cs líneas 81-87 l16, los cifrados: 47 de 51; leídos de otra forma: 5 Comunicado en la #785
99. El índice nombra un acorde de modo que el filtro de nombres lo encuentre En main, el índice guarda el nombre que el análisis de GA da a cada voicing, y el filtro compara su fundamental y su cualidad con las de la petición. C E G A se llama Am7, nunca C6; el 6/9 C D E G A se llama C6; D G A se llama Gsus2; una tríada aumentada toma el nombre de una de sus tres fundamentales, Faug para D♭ F A. El filtro corta el nombre almacenado en su primer paréntesis, así que Dbaug(maj7)/C pasa como D♭ aumentado. De una cuadrícula de 144 acordes, los 12 acordes de sexta, 8 tríadas aumentadas y 6 tríadas sus4 no reciben ningún voicing propio, aunque el corpus de la lección 3 los contiene todos OptickSearchStrategy.cs líneas 307-319 en main, líneas 348-349 l16 (main), los nombres de cinco acordes; la cuadrícula, fundamentales sin un voicing exacto: 12 de 12 para 6, 8 para aug, 6 para sus4 Comunicado en la #784
100. Una técnica que nombra el prompt se respeta, o la respuesta dice que no En main, la vía del índice descarta Tags y ModeName por diseño (ADR-0002), y VoicingAgent registra en su log los filtros descartados; ChordVoicingsSkill no registra nada, y su respuesta no dice nada. De los 48 voicings devueltos para los seis prompts de ejemplo que nombran una técnica, 5 son de esa técnica, 2 drop2 y 3 voicings con cejilla; ninguno es un shell, un A7 sin fundamental, un voicing por cuartas ni un E menor abierto, aunque el corpus de la lección 3 contiene 19, 45, 1 y 60, respectivamente OptickSearchStrategy.cs líneas 101-130 en main, VoicingAgent.cs líneas 110-126, 0002-voicing-filter-parity-cpu-gpu-only.md l16 (main), las técnicas: 5 de 48 Comunicado en la #784
101. Una skill que no necesita modelo responde cuando el enrutador no puede calcular el embedding de la pregunta CapoSkill y AlternateTuningsSkill responden sin modelo, pero su CanHandle devuelve false, “semantic-routing only”, en el commit fijado y en main. En main, el respaldo por palabras clave del enrutador, añadido para que las skills deterministas respondan cuando los embeddings están caídos, nunca llega a ellas: ninguna de las dos recibe ni uno de sus 22 prompts de ejemplo. Con el CanHandle del commit fijado, dos van a otras skills: el que nombra Em, a skill.chordinfo, y “What chord shape for B major with capo 4”, a skill.chordvoicings CapoSkill.cs línea 47, AlternateTuningsSkill.cs línea 50, SemanticIntentRouter.cs línea 321 en main l17, sin embeddings: 0 de 22 Comunicado en la #787 y la #788
102. CapoSkill responde a la pregunta que se le hace El sentido de la pregunta se lee en la formulación: salvo que la pregunta nombre una forma, una tonalidad detrás de “in” es la tonalidad que suena, y la respuesta es una forma. Su propio ejemplo “What’s the sounding key if I play in G with capo on 5” recibe la forma D en lugar de lo que suena, C, y “Playing in D with capo 2, what key does it sound in?”, la forma C. Las expresiones no distinguen mayúsculas de minúsculas, así que en “I’m in a band, capo 2, song is in G” el artículo se lee como la tonalidad A. La fila 82 lee del mismo modo un artículo como un acorde CapoSkill.cs líneas 52-64, líneas 89-104 l17, los ejemplos y otras formulaciones: sentido equivocado 2; “in a band”: acorde equivocado Comunicado en la #787
103. CapoSkill lee una tonalidad con su alteración La tonalidad termina en \b, que falla detrás de #, ♯ y ♭, así que la expresión se queda con la letra: “Capo on 2, song in F#” recibe la forma D♯ en lugar de E, “song in C#, capo 4”, G♯ en lugar de A, y “song in B♭, capo 1”, A♯ en lugar de A. Con “major” o “minor” detrás de la tonalidad, la lectura es correcta. La fila 106 es el mismo límite en la skill de afinaciones CapoSkill.cs líneas 52-56 l17, otras formulaciones: acorde equivocado para F#, C# y B♭ Comunicado en la #787
104. CapoSkill lee las tonalidades y las formas que escribe un guitarrista Rechaza su propio ejemplo “What chord shape for B major with capo 4” y “what shape for F with capo 3”: una tonalidad tiene que ir detrás de “in” o de “key”. Rechaza “song in Em”: una tonalidad menor tiene que escribirse con la palabra. Rechaza C♭ mayor, que falta en su tabla de fundamentales, y las formas C7, Cmaj7 y Dsus4: una forma es una letra, una alteración y una m opcional. Rechaza “Where should I put the capo to play in with open chords?” para las 12 tonalidades: las dos expresiones necesitan un número de traste CapoSkill.cs líneas 52-64, líneas 67-76 l17, los ejemplos: rechazos 1; la cuadrícula: rechazos 11 (Cb); otras formulaciones: rechazos 5; dónde poner la cejilla: rechazos 12 Comunicado en la #787
105. CapoSkill escribe una tonalidad como la escribe una armadura Escribe sostenidos salvo que la tonalidad o la forma que ha leído lleve un bemol o, si es una forma, que la pregunta diga “flat”. 27 formas de la cuadrícula mayor, y 3 de las 11 respuestas para cada forma abierta mayor, son A♯, D♯ o G♯ mayor: una forma de C con la cejilla en el traste 3 suena como D♯, donde el comentario de la clase dice E♭. Las tonalidades menores escritas con bemoles reciben las formas D♭m y G♭m. La fila 56 es la misma grafía en domain.transposeChord CapoSkill.cs líneas 178-191, línea 13 l17, la cuadrícula: grafía teórica en 27 mayores y 6 menores; las formas abiertas: 3 de 11 para cada forma mayor Comunicado en la #787
106. AlternateTuningsSkill lee una afinación dada por sus notas La expresión de las seis notas termina en \b, así que se pierden #, ♯ y ♭. Las notas de open D se leen como D A D F A D y no reciben ningún nombre, en ninguna notación; E♭ A♭ D♭ G♭ B♭ E♭ se lee como E A D G B E; la afinación estándar en E♭ escrita con sostenidos, D♯ G♯ C♯ F♯ A♯ D♯, recibe el nombre de Whole-step down (D standard), un semitono más grave en cada cuerda. NotesMatch compara grafías, así que G♭ en lugar de F♯ tampoco recibe ningún nombre (ejercicio 3). Sin cambios en main AlternateTuningsSkill.cs líneas 203-211, líneas 228-238 l17 y l17 (main), por las notas: 35 de 44, otra afinación nombrada 4 Comunicado en la #788
107. AlternateTuningsSkill responde con la afinación nombrada, o rechaza la pregunta En el commit fijado, “open D minor” recibe open D y “open G minor”, open G, una tercera mayor en lugar de una menor; “drop C♯” recibe drop C y “drop D♭”, drop D. En main, las dos preguntas de drop se rechazan, y las dos menores siguen recibiendo las afinaciones mayores. El comentario de la clase promete una advertencia para “What does an Em shape look like in drop-D”; la respuesta es la tabla de drop D, que no nombra Em AlternateTuningsSkill.cs líneas 53-74, línea 15, líneas 57-67 en main l17, fuera de la tabla: otra afinación 4; l17 (main): otra afinación 2; la respuesta nombra Em: no Comunicado en la #788
108. Una skill que no necesita modelo responde cuando el enrutador no puede calcular el embedding de la pregunta VoiceLeadingSkill responde sin modelo, pero su CanHandle devuelve false, “semantic-routing only”, en el commit fijado y en main. En main, el respaldo por palabras clave del enrutador nunca llega a ella: no recibe ninguno de sus 10 prompts de ejemplo. Con el CanHandle del commit fijado, los dos que dicen “voicing” van a skill.chordvoicings, que responde con digitaciones para un solo acorde. La fila 101 es lo mismo para las skills de cejilla y de afinaciones VoiceLeadingSkill.cs línea 49, SemanticIntentRouter.cs línea 321 en main l18, sin embeddings: 0 de 10 Comunicado en la #789
109. El total de VoiceLeadingSkill es el movimiento mínimo, como afirma su respuesta Entre dos acordes con el mismo número de notas, siempre lo es. Cuando el número difiere, la skill duplica la fundamental del acorde con menos notas, y 1186 de 3072 respuestas mueven más que con otra duplicación, hasta 7 semitonos más: Csus2 a Em9 recibe 11 semitonos cuando bastan 4, y su propio ejemplo “smoothest voicing from Em to A7”, 5 cuando bastan 4. Cada respuesta termina con “every other voicing of … requires more total semitone movement”, que también es falso en las 607 respuestas en que otro emparejamiento mueve igual de poco VoiceLeadingSkill.cs líneas 101-110, línea 131, líneas 185-194 l18, la cuadrícula: más que el mínimo 1186 de 3072, varios emparejamientos óptimos 607; los ejemplos: Em → A7 5, mínimo 4 Comunicado en la #789
110. VoiceLeadingSkill lee los cifrados que lista su tabla 24 de 46 cifrados se leen bien como primer acorde, y 24 como último. Δ, ø, +, -, o, “major7” y “dom7” se rechazan, salvo + y - como último acorde, que se leen como la letra sola. CM7 se lee como C menor séptima: la cualidad se pasa a minúsculas antes de la tabla, que lista M7. Se pierde un ° final, se ignoran las palabras que siguen al último acorde (“voice leading F to C minor” recibe C mayor), y se rechazan los acordes escritos con palabras antes de “to”, entre ellos su propio ejemplo “voice leading C major to G major”. add9, 7sus4, 7♭9, 7♯9, mMaj7, 11 y 13 se rechazan a propósito VoiceLeadingSkill.cs líneas 51-57, líneas 224-252 l18, los cifrados: bien 24 de 46 como primer acorde, 24 como último; los ejemplos: rechazos 1 Comunicado en la #789
111. VoiceLeadingSkill lee una fundamental con su alteración La expresión termina en \b, que falla detrás de #, ♯ y ♭, así que un último acorde se queda con su letra: “voice leading from C to F#” recibe C → F. Con una m detrás de la alteración, o con b escrita en ASCII, la lectura es correcta. Las filas 103 y 106 son el mismo límite en las skills de cejilla y de afinaciones VoiceLeadingSkill.cs líneas 55-57 l18, alteraciones: bien como último acorde 0 de 5 para #, ♯ y ♭ Comunicado en la #789
112. VoiceLeadingSkill escribe las notas como las escriben sus acordes Escribe sostenidos salvo que un cifrado lleve un bemol o que la pregunta diga “flat”. TokenHasFlats busca b sin distinguir mayúsculas de minúsculas, así que encuentra la fundamental de “Bb” en la posición 0 y no la cuenta: “F7 to Bbmaj7” da A♯ y D♯. Sin un bemol en la pregunta, D7 a Gm da A♯ en lugar de B♭. Con un nombre por clase de altura, E♯, B♯ y el F doble sostenido se escriben F, C y G. La fila 105 es la misma grafía en la skill de cejilla VoiceLeadingSkill.cs líneas 85-86, líneas 261-266 l18, grafía: como sus acordes 22 de 36; alteraciones: “Bb” como primer acorde, escrito A# Comunicado en la #789
113. VoiceLeadingSkill lee los acordes de la pregunta, o la rechaza La expresión no distingue mayúsculas de minúsculas, así que en “how do I get from G7 to a C chord” el artículo se lee como el acorde A. “voice leading Dm7 to G7 to Cmaj7” solo recibe su primer movimiento, y la respuesta no lo dice. “-” e “into” no se leen como “to”. La fila 102 lee del mismo modo un artículo como una tonalidad VoiceLeadingSkill.cs líneas 51-57 l18, otras formulaciones: acorde equivocado 4, rechazos 3, dos de tres acordes 1 Comunicado en la #789
114. ga_voice_leading_pair comprueba los voicings que empareja La herramienta ordena los pares solo por movimiento, y su búsqueda no nombra ningún acorde, así que nada compara un voicing con el acorde pedido. Con 50 candidatos por acorde, lo que su descripción llama “more exhaustive”, los primeros pares empeoran: en main, los primeros pares de 8 de los 10 ejemplos de la lección 18 tocan los dos acordes, donde 15 candidatos dan 10, y G7 → Cmaj7 y D → A sacrifican el acorde a cambio de 2 semitonos en lugar de 3. En el commit fijado, no lo hace ninguno, y C → Am empareja tres E consigo mismos a 0 semitonos CompositionTools.cs línea 195, líneas 224-235, líneas 278-298 l19 (main), 50 candidatos: correctos a ambos lados 8 de 10; l19, 50 candidatos: 0 Comunicado en la #791
115. VoiceLeadingDistance empareja el voicing con menos notas con las notas más cercanas, como dice su comentario Empareja las notas más graves del voicing con más notas. En main, 340 de los 1360 pares con distinto número de notas que la herramienta mide para los diez ejemplos reciben el movimiento mínimo, y la diferencia llega a 39 semitonos: Em x-x-2-x-0-3 a A7 0-0-2-x-2-3 cuesta 47 cuando bastan 8. Entre voicings con el mismo número de notas, el emparejamiento ordenado siempre es el mínimo, aunque la descripción lo llama “not a formal Hungarian-optimal assignment”. En estos diez ejemplos, la distancia más pequeña no cambia CompositionTools.cs líneas 180-185, líneas 312-336 l19 (main): distinto número de notas 340 de 1360, mayor diferencia 39; mismo número 890 de 890 Comunicado en la #791
116. ga_voice_leading_pair devuelve sus diagramas en el orden de los diagramas de acordes Devuelve la cadena del índice, empezando por la E aguda: en main, el primer par de C → F llega como 0-1-0-x-x-x → 1-1-2-x-x-x, que un diagrama de acordes escribe x-x-x-0-1-0 → x-x-x-2-1-1. En main, ChordVoicingsSkill pasa las mismas cadenas al orden de los diagramas de acordes; la respuesta de la herramienta no dice qué cuerda va primero CompositionTools.cs líneas 239-254, ChordVoicingsSkill.cs línea 136 en main l19 (main), el primer par de C → F tal como lo devuelve la herramienta Comunicado en la #791
117. La skill de conducción de voces en espera describe la herramienta que llamaría skills-dev/_pending-tools/voice-leading/DRAFT.md espera un argumento optimize y una respuesta con VoiceMovements, TotalSemitones y CommonTones; ga_voice_leading_pair no recibe ningún optimize y devuelve pares de voicings con una distancia. El borrador promete “a Plücker-line / minimum-displacement solution” y remite a HarmonyMcpTools.cs, que GA no tiene, y su ejemplo de respuesta anuncia 2 semitonos de Dm7 a G7 para movimientos de 0, 0, 2 y 1. Su README lo deja en espera porque a las herramientas propias del chatbot les falta ga_voice_leading_pair, que GaMcpServer sí tiene DRAFT.md líneas 29-44, líneas 54-60, línea 74, README.md líneas 19-29 l19 (main), Dm7 → G7: 3 semitonos; el borrador, leído en los dos commits Comunicado en la #791
118. ga_generate_progression escribe cada acorde como lo escribe su tonalidad Todos los acordes de las nueve plantillas, en las 15 tonalidades de cada modo, tienen las clases de altura correctas, y 712 de 750 se escriben como los escribe un manual. PrefersFlats exige una b en la fundamental o la fundamental F, así que D, G y C menor reciben sostenidos: la plantilla andalusian en C menor recibe A♯ y G♯ en lugar de B♭ y A♭. Con un nombre por clase de altura, el I y el IV de C♭ mayor se escriben B y E; el IV de G♭ mayor, B; el iii de C♯ mayor, Fm; el V de A♯ menor, F7, y el ♭VI de E♭ y A♭ menor, B y E. El ChordProgressions.yaml de GA escribe el mismo B para el IV de G♭. La fila 54 es la misma elección en domain.diatonicChords CompositionTools.cs líneas 344-380, ChordProgressions.yaml línea 685 l20, las plantillas: bien escritos 712 de 750, clases de altura correctas 750; las tablas del YAML: los mismos acordes en todas las filas Comunicado en la #792
119. ga_generate_progression lee la tonalidad que se le da La fundamental pasa por ChordPitchClasses.TryParse, un lector de cifrados. “D minor” y “Dm” se leen como D, así que I-V-vi-IV en “D minor” recibe los acordes de D mayor, sin ninguna advertencia. PrefersFlats compara la cadena entera con “F”, así que “F major” recibe sostenidos, F C Dm A#. “b” se lee como B y pasa B mayor a bemoles, B Gb Abm E, y cualquier b de la cadena decide la grafía: “C7b9” escribe la plantilla andalusian en C menor con bemoles, y “C”, no. ♭ se rechaza CompositionTools.cs línea 139, línea 379, MusicalQueryEncoder.cs líneas 166-171 l20, las fundamentales: “D minor” → D A Bm G, “b” → B Gb Abm E Comunicado en la #792
120. ga_generate_progression acota la longitud de su respuesta length repite la plantilla sin límite, mientras que limit y candidatesPerChord, en el mismo archivo, están acotados: una longitud de 100000 devuelve 100000 acordes, 17.300.216 caracteres de JSON. 0 y una longitud negativa dan la longitud propia de la plantilla, sin ninguna advertencia CompositionTools.cs líneas 148-151, líneas 202-203 l20, la longitud: 100000 acordes, 17300216 caracteres Comunicado en la #792
121. Enlazar con ga_voice_leading_pair una progresión generada da un camino de voicings, como sugiere la nota de la herramienta La nota dice “stitch with ga_voice_leading_pair”. Un primer par por movimiento, en C mayor o en A menor: en main, empalman en 17 de 32 puntos, donde el par siguiente empieza en el voicing en el que termina el anterior; en los demás, la mano salta entre dos voicings de un mismo acorde. En 7 de las 9 plantillas, un camino continuo entre los mismos candidatos mueve tan poco como la suma de los primeros pares; en rhythm-changes-a y 12-bar-blues, cualquier camino continuo mueve más, 25 semitonos en lugar de 21, y 28 en lugar de 24 CompositionTools.cs líneas 174-175, líneas 224-235 l20 (main): los primeros pares empalman en 17 de 32; l20: en 6 de 32 Comunicado en la #792
122. La skill de progresiones en espera describe la herramienta que llamaría skills-dev/_pending-tools/progression-generator/DRAFT.md espera mood, key, length con un valor por defecto de 4, style y complexity, y una respuesta con Chords, RomanNumerals, Style y Rationale; la herramienta recibe root, template y length y devuelve chords. Sus tonalidades “D minor” y “F major” se leen mal como fundamentales (fila 119), su ejemplo Dm – B♭maj7 – Gm – A7 no sale de ninguna plantilla, y remite a ProgressionMcpTools.cs, que GA no tiene. La fila 117 dice lo mismo del borrador de conducción de voces DRAFT.md líneas 32-45, líneas 49-63, línea 77 l20, las fundamentales; el borrador, leído en los dos commits Comunicado en la #792
123. ga_search_voicings busca por modo La descripción de la herramienta promete “mode names (Lydian, Dorian)”, y la skill llama a MODAL “mode flavor”. El lector encuentra los 23 modos, pero MusicalQueryEncoder.Encode nunca lee el modo: tras C, Am y G7, 19 de los 23 modos responden igual que el acorde a secas, 18 tras Dm7, y los demás leen un tag. Un modo a secas da a todos los voicings una puntuación de 0 y devuelve los diez primeros del índice, porque HasIntent cuenta el modo y la respuesta “No chord, mode, or known tag recognized” nunca llega. “lydian dominant” y “phrygian dominant” se leen como lidio y frigio más el tag “dominant”. “something jazzy in F minor”, el propio ejemplo del vocabulario, lee el acorde F y recibe voicings de F mayor VoicingSearchTool.cs línea 95, líneas 238-242, MusicalQueryEncoder.cs líneas 43-108, TypedMusicalQueryExtractor.cs líneas 104-121 l21, los modos: C, 19 de 23 iguales; modos a secas, 18 de 23 a 0.0000, los diez primeros del índice; l21 (main): lo mismo Comunicado en la #795
124. Un tag obtiene los voicings que nombra Los 188 tags activan 12 bits de SYMBOLIC, que vale 0.10 de la puntuación, y los tags de un mismo bit responden igual: jazz como rock-guitar, shell-voicing como rootless. Cmaj7 recibe 7 respuestas distintas de los 188 tags en el commit fijado, 5 en main, y los tags de los bits 3, 4, 5 y 10 no cambian nada. Tras diez acordes de séptima, “rootless” no devuelve ningún voicing rootless entre 100, ni en el commit fijado ni en main, cuando el índice contiene entre 5 y 63 para cada acorde: la STRUCTURE de la consulta contiene el acorde entero, fundamental incluida SymbolicVectorService.cs líneas 13-32, SymbolicTagRegistry.cs líneas 46-111, SemanticNomenclature.yaml líneas 129-140 l21, los tags: Cmaj7, 7 respuestas distintas, 12 de 12 bits iguales; “rootless”: voicings devueltos 100, rootless 0; l21 (main): Cmaj7 5, rootless 0 Comunicado en la #795
125. El lector toma como tags las palabras del vocabulario GetBitIndex recurre a una coincidencia por subcadena, en los dos sentidos: “for” lee normal-form, “the” pitch-axis-theory, “what” so-what-chord y “end” beginner-friendly. El lector omite “chord”, “voicing” y las palabras de menos de tres letras, pero no estas. Un segundo bit rebaja el peso del primero: “G7 shell for” puntúa 0.4932, y “G7 shell”, 0.5078. El ejemplo de la skill “something jazzy in F minor for a ballad” y el del vocabulario “shell voicing for G7” leen “for”. Dos tags de la lista no se pueden escribir: g5 tiene menos de tres letras, y schoenberg-op.16-chord se parte en su . SymbolicTagRegistry.cs líneas 196-220, TypedMusicalQueryExtractor.cs líneas 132-147 l21, las consultas de ejemplo de GA: for → normal-form; las del curso: the → pitch-axis-theory, what → so-what-chord, end → beginner-friendly Comunicado en la #795
126. La skill voicing-search describe las puntuaciones y los tags tal como los tiene la herramienta Según los pesos de la skill, las coincidencias “approach 1.0”, y su ejemplo puntúa 0.9831, pero una consulta deja MORPHOLOGY y CONTEXT a cero: ninguna consulta puede puntuar por encima de 0.70, y las 828 consultas de acordes llegan como máximo a 0.5250 en el commit fijado, y a 0.6000 en main. “drop2 does NOT match”: lee drop2voicings, la copia sin guiones del registro. Un tag de estilo “currently lowers the score”: “Cmaj7 jazz” puntúa 0.5085, y “Cmaj7”, 0.4585, sobre el índice que escribe el código del commit fijado. Sus usos “Lydian on guitar”, “jazz voicings” y “shell voicings” no nombran ningún acorde y puntúan 0, 0.0577 y 0.0707; “something warm and dreamy”, presentada como una consulta de la que el lector no saca nada, lee dreamy SKILL.md línea 19, línea 26, línea 39, línea 47, línea 81, líneas 94-96 l21, las puntuaciones: lo más alto que puede alcanzar una consulta 0.70, consultas de acordes 828, la puntuación máxima más alta 0.5250; l21 (main): 0.6000 Comunicado en la #795
127. La skill voicing-search en espera describe la herramienta que llamaría skills-dev/_pending-tools/voicing-search/DRAFT.md llama a ga_search_voicings_by_query, que está en VoicingEmbeddingTool.cs y necesita GaApi y Ollama; el borrador dice que no está implementada y remite a VoicingMcpTools.cs, que GA no tiene en ninguno de los dos commits. Espera topK, instrument y una respuesta de Results con contextTags y sourceCorpus; la herramienta recibe query y limit. Su “mellow Cm9”, x-3-5-3-3-3, no tiene tercera menor, su diagrama llama E♭ al tercer traste de la cuerda G y D al de la E aguda, cuando tocan B♭ y G, y ninguno de sus tres tags está en el vocabulario. Las filas 117 y 122 dicen lo mismo de los otros dos borradores DRAFT.md líneas 22-26, líneas 35-44, líneas 57-68, línea 83, VoicingEmbeddingTool.cs líneas 93-132 l21, el borrador: x-3-5-3-3-3 toca C G A# D G, deja fuera D#; sus tags en el vocabulario: no Comunicado en la #795
128. IcvNeighborsSkill responde a sus prompts de ejemplo La depuración del 2026-06-16 reformuló las diez anclas de enrutamiento de la skill con “resemble”, “similar” y “most like”, y quitó “close”, “nearby” e “ICV”, pero las dos expresiones que leen la pregunta siguen necesitando “neighbors”, “nearby”, “close to”, “near”, “adjacent” o “harmonically close”: la skill rechaza las diez anclas, las preguntas con las que compara el enrutador, y su regla de pistas no refuerza ninguna. Dos de las cuatro formulaciones de su comentario de documentación, “Nearby pitch-class sets to C major” y “Closest chord to G7 in ICV space”, también se rechazan, y el propio ejemplo de su rechazo, “ICV neighbors of Cmaj7”, refuerza además a skill.intervalclassvector. IntervalClassVectorSkill, depurada en la misma pasada, responde a 8 de sus 10 anclas. En main, el rechazo solo se marca con Declined IcvNeighborsSkill.cs líneas 51-89, líneas 254-260, DefaultRoutingHintProvider.cs líneas 124-139 l22, las formulaciones de GA: 10 anclas, 0 respondidas, 10 rechazadas, 0 reforzadas hacia skill.icvneighbors; las anclas de IntervalClassVectorSkill: 8 respondidas; l22 (main): lo mismo Comunicado en la #798
129. IcvNeighborsSkill construye el acorde por el que se le pregunta De 27 acordes habituales detrás de “ICV neighbors of”, la skill construye bien 10. Pasa la cualidad a minúsculas antes de leer su tabla, así que el "M7" de la línea 221 nunca coincide y CM7 se construye como C menor séptima. Una cualidad que no conoce da una tríada mayor, sin ningún aviso: Cdom7, Cadd9, C7b9, C7#9, Cm11, C13 y C5 responden como C E G. ° y + no son letras, así que el acorde termina delante de ellos: C° y C+ se convierten en C, y C°7 en la tríada C°; Cø7, C7sus4 y CmMaj7 se rechazan. “C minor” y “A minor” se leen como tríadas mayores, y la expresión no distingue mayúsculas de minúsculas, así que “a” es A mayor: el “What’s close to a half-diminished chord?” del borrador en espera recibe los vecinos de A IcvNeighborsSkill.cs líneas 82-89, líneas 196-232 l22, los acordes: 27, 10 bien construidos; CM7 construido como C D# G A#; “a Cmaj7” leído como a, o sea C# E A; l22 (main): lo mismo Comunicado en la #798
130. IcvNeighborsSkill lista los conjuntos más cercanos, “top 8 by harmonic cost” La skill se queda con los conjuntos a L1 1 o 2 y los ordena por L1, pero un acorde de tres notas o más no tiene ninguno a 1: todas las filas están a L1 2, coste 1.20, y las ocho filas son las ocho primeras por máscara de bits, en el orden de FindNearby. Las filas solo dependen del vector: los 192 acordes de 12 fundamentales y 16 cualidades reciben 10 respuestas distintas, y todas las tríadas mayores o menores reciben los mismos ocho conjuntos, cinco de ellos intervalos de dos notas. Las filas de Cdim y de Caug son todas conjuntos de dos notas. Cdim7 no recibe ninguno, con “Try a wider radius”, pero el radio es la constante DefaultMaxDistance. Las filas son números de clases de altura y vectores, sin nombre ni número de Forte, y contienen varias transposiciones de una misma clase de conjuntos: las ocho filas de C contienen cinco clases de conjuntos. En main, ga_icv_neighbors lista cada clase de conjuntos una sola vez desde 51ac3f68; la skill no IcvNeighborsSkill.cs líneas 76-77, líneas 130-175, GrothendieckService.cs líneas 45-90 l22, los vecinos: cada fila a 2, 1.20, los primeros por id: sí; 192 acordes, 10 respuestas distintas, 10 vectores distintos; Cdim7: ningún conjunto a L1 = 2 o menos; l22 (main): lo mismo Comunicado en la #798
131. La skill icv-neighbors en espera describe la herramienta que llamaría skills-dev/_pending-tools/icv-neighbors/DRAFT.md dice que ga_icv_neighbors no está implementada y remite a Common/GA.Business.ML/Agents/Mcp/AtonalMcpTools.cs, que GA no tiene; la herramienta está en GaMcpServer/Tools/ChordAtonalTool.cs. Espera chord, topK y metric, y una respuesta de Neighbours; la herramienta recibe symbol y maxDistance y devuelve texto. Su ejemplo pone Am7 a distancia 0.0 con el vector de Cmaj7, pero Am7 es 4-26, a L1 4, y Cm9 sin su fundamental a 0.6, pero es E♭ séptima mayor, 4-20, a L1 0. La skill del chatbot rechaza dos de las tres formulaciones del borrador y lee A mayor en la tercera. Las filas 117, 122 y 127 dicen lo mismo de los otros tres borradores DRAFT.md línea 18, líneas 31-58, línea 72, ChordAtonalTool.cs líneas 220-254 l22, el borrador: Am7 4-26, L1 4; Cm9 sin su fundamental 4-20, L1 0 Comunicado en la #798
132. GrothendieckDeltaSkill e IcvShortestPathSkill responden a sus prompts de ejemplo La skill delta responde a 8 de sus 10 prompts de ejemplo: “how harmonically far is Am from D7”, que también es la primera formulación de su comentario de documentación, tiene “from” entre los acordes, y “how different are C major and F major harmonically”, una palabra detrás del primer acorde. La skill de camino responde a 7 de sus 10: “shortest path from C major to F major”, que también figura en su comentario de documentación, “shortest chord path from Dm7 to Gmaj7” y “harmonic stepping stones from Cmaj7 to Fmaj7” se rechazan. La skill delta responde a 9 de los 10 de la skill de camino, así que una pregunta de camino formulada como ellos y enviada a ella recibe una distancia, no un rechazo; “harmonic cost to move from C to G” refuerza a skill.transpose. Las dos construyen sus acordes con una copia de la tabla de la lección 22: CM7 es C menor séptima, “C to A minor”, un prompt de camino, pide A mayor, y “a” es A mayor GrothendieckDeltaSkill.cs líneas 46-67, líneas 153-173, IcvShortestPathSkill.cs líneas 55-93, DefaultRoutingHintProvider.cs líneas 257-259 l23, las formulaciones de GA: GrothendieckDeltaSkill: 10 anclas, 8 respondidas; IcvShortestPathSkill: 10 anclas, 7 respondidas; la otra skill responde a 9 de ellas; 36 tokens de acorde, 36 construidos igual; l23 (main): lo mismo Comunicado en la #802
133. GrothendieckDeltaSkill da la distancia entre dos acordes GrothendieckDelta.FromIcVs convierte un delta nulo en Ic1 = 1, y la skill lo imprime: las parejas de C a G, de Am a Em, de Cmaj7 a Fmaj7 y de C a C reciben [+1, 0, 0, 0, 0, 0], un L1 de 1, un coste de 0.60 y “more chromatic color”, como las 4320 parejas ordenadas de los 192 acordes que comparten un vector. IcvNeighborsSkill vuelve a calcular el delta para evitarlo; la heurística es la que comunica la issue de GA #776. La interpretación es la primera regla que coincide, así que de Cmaj7 a G7 y de G7 a Cmaj7 reciben los dos “more chromatic color”, como les ocurre a 1440 de las 16272 parejas con vectores distintos. La flecha que la precede se imprime como →, los bytes de → leídos como Windows-1252 y guardados como UTF-8, en el commit fijado y en main GrothendieckDelta.cs líneas 113-134, línea 217, líneas 226-258, GrothendieckDeltaSkill.cs líneas 97-131 l23, los deltas: 4320 con el mismo vector, 4320 respondidas con L1 1; 32544 con vectores distintos, 32544 con el L1 correcto; 1440 con “more chromatic color” en los dos sentidos; l23 (main): lo mismo Comunicado en la #802
134. IcvShortestPathSkill encuentra un camino entre dos acordes La búsqueda solo pasa a conjuntos del mismo tamaño, así que los acordes de tamaños distintos nunca se unen: de Am a D7 y de Gmaj7 a Em, dos de los prompts de ejemplo de la skill, y “How do I get from Am to D7 harmonically”, de su comentario de documentación, reciben “No path found within 5 steps”. Antes de decirlo, expande 168 de los 220 conjuntos de tres notas, o 462 de los 495 conjuntos de cuatro, y cada expansión recorre los 4096 conjuntos, cuyos vectores se recalculan en cada lectura, salvo si una caché de FindNearby de 256 entradas, que descarta primero las más antiguas, guardó su respuesta. Cdim7 y Caug solo alcanzan sus propias transposiciones, 3 y 4 conjuntos GrothendieckService.cs líneas 117-163, línea 21, PitchClassSet.cs línea 104, IcvShortestPathSkill.cs línea 137 l23, los caminos: Am → D7 y Gmaj7 → Em, ningún camino; conjuntos expandidos: 168 de los 220 de 3 notas, 462 de los 495 de 4 notas; l23 (main): lo mismo Comunicado en la #802
135. IcvShortestPathSkill describe el camino que encuentra La respuesta cuenta los conjuntos como pasos: de Cmaj7 a G7 son “4 steps total (3 intermediate moves)” para tres movimientos a través de dos conjuntos, de C a G “2 steps total (1 intermediate move)” para un movimiento a través de ninguno, de C a C “1 step total”. Un movimiento entre dos conjuntos de un mismo vector, a un L1 de 0, cuenta como un paso: de C a G, de C a F, de C a Cm y de C a A. La respuesta da los conjuntos intermedios como números sin nombre, C D D# G y C C# E F# para el camino de Cmaj7 a G7, cuyos movimientos conservan 2 notas, después 1 y después ninguna, cuando la respuesta promete “common-tone bridges”. La skill conserva además dos comentarios sobre la depuración, el segundo escrito encima del primero IcvShortestPathSkill.cs líneas 55-66, líneas 127-162 l23, los caminos: Cmaj7 → G7, 4 pasos en total (3 movimientos intermedios), 3 movimientos, notas comunes 2,1,0; C → C, 1 paso en total; l23 (main): lo mismo Comunicado en la #802
136. SetTheoryEquivalenceSkill y GrothendieckParseSkill responden a sus prompts de ejemplo La skill de conjuntos responde a 4 de sus 5 prompts de ejemplo: “Are pitch classes 0,2,4 and 1,3,5 transpositionally equivalent” tiene una palabra entre el segundo conjunto y “equivalent”. La skill de análisis responde a 5 de sus 10: “parse Cmaj7 + Gmaj7 + Fmaj7”, “explain power(Cmaj7)” y “parse Transpose(Cmaj7)”, la forma que sugiere su propio mensaje de fallo, no contienen ninguno de los símbolos que busca su patrón de superficie, y “what is Hom(Cmaj7, Gmaj7)” no tiene palabra de anclaje; el analizador rechaza “Transpose(C ⊗ G)” y “equalizer Transpose Invert”. Ninguna regla de pistas nombra a la skill de conjuntos, y dos de sus prompts refuerzan a skill.transpose SetTheoryEquivalenceSkill.cs líneas 35-54, GrothendieckParseSkill.cs líneas 51-82, línea 177, DefaultRoutingHintProvider.cs líneas 257-259 l24, las formulaciones de GA: SetTheoryEquivalenceSkill: anchors 5, answered 4; GrothendieckParseSkill: anchors 10, answered 5; l24 (main): lo mismo Comunicado en la #806
137. SetTheoryEquivalenceSkill lee la relación que nombra una pregunta En “equivalent under transposition” y “equivalent under inversion”, la formulación de sus prompts de ejemplo, \s* se lleva el espacio que necesita el grupo opcional \s+under, así que la skill no lee ninguna relación y responde para la clase de conjuntos: {0,1,3} y {0,2,3} “under transposition”, su segundo prompt de ejemplo, reciben “Yes”, aunque solo una inversión los relaciona. Esa formulación se equivoca en 2016 de las 48400 parejas ordenadas de conjuntos de tres notas y en 4032 de las 245025 de conjuntos de cuatro notas. La relación solo se lee tras “set class”, “set” o “class”, donde todos los veredictos son correctos, así que ninguno de los prompts de ejemplo recibe el veredicto de la transposición sola escrito tras una revisión del 2026-05-13. De una pareja relacionada por transposición y preguntada “under inversion” se dice que se reduce a la misma forma prima “via either operation”, lo que es falso para 2016 de las 2608 parejas de tres notas y 4032 de las 5841 de cuatro de las que se dice SetTheoryEquivalenceSkill.cs línea 48, líneas 69-80, líneas 97-107, líneas 137-148 l24, la relación: equivalent under transposition, 0,1,3 | 0,2,3: yes, TI, wrong; todas las parejas: 3 notas wrong 2016, 4 notas wrong 4032; “via either operation”: 2016 de 2608, 4032 de 5841; l24 (main): lo mismo Comunicado en la #806
138. SetTheoryEquivalenceSkill lee los conjuntos El primer conjunto debe ir seguido de “ and”, así que empieza tras el último guion: “0-1-4” se pregunta como {4}, y el nombre de Forte “3-3” como {3}, y la respuesta los compara sin ningún aviso. 10 y 11 escritos como “t”, “T”, “A” o “0te” se rechazan, igual que los paréntesis y los corchetes angulares. Las formas primas se sostienen: 224, iguales para las 24 transposiciones e inversiones de cada conjunto, cada una el conjunto que da para su etiqueta la tabla de GA del catálogo de Forte, con 23 parejas que comparten un vector, y las respuestas sobre los conjuntos en relación Z son correctas SetTheoryEquivalenceSkill.cs líneas 47-54, líneas 218-241, PitchClassSetId.cs líneas 123-156 l24, los conjuntos: 0-1-4, answered, 4 {0}; 3-3, answered, 3 {0}; formas primas 224, estables 4096, distintas de la tabla 0, ausentes de la tabla 0, parejas Z 23; parejas en relación Z dichas 1152 de 1152; l24 (main): lo mismo Comunicado en la #806
139. El analizador Grothendieck de GA lee las formas que nombran sus comentarios 25 de las 50 formas se analizan, 21 en el caso que promete su comentario. str lee los espacios que siguen a su palabra, así que falla toda forma que pide después ws1: “limit of”, “lim”, “colimit of”, “colim”, “define functor”, “natural transformation”, “define nat_trans”, “define sheaf”, “truth_value of”, “subobjects of”, “glue”, y “transpose” seguido de un número; “restrict S to U” falla antes, ya que el analizador quiere primero el nombre del haz. Una primera alternativa que lee un objeto oculta las formas con palabra, como “C tensor G”. “P(C)”, “power(C)”, “Ω(C)” y “eta(C)” son aplicaciones de funtor. Ninguna de las 50 formas alcanza 9 de los 22 casos, a tres de los cuales llega una forma escrita de otra manera: “equalizer” necesita dos paréntesis, y ningún espacio puede seguir a su coma o a su “|”; dos operadores seguidos fallan. Solo se leen los nombres de cualidad de su lista, como min y dom7: Am, Cm, G7, C7, Dm7, CM7, C°, C+ y Cm7b5 fallan GrothendieckOperationsParser.fs línea 18, líneas 53-85, líneas 406-431, líneas 625-633 l24, las expresiones: forms 50, parsed 25, as their comment says 21; casos que ninguna forma alcanza 9; sin espacios, eq(invert,reflect) Equalizer; los acordes: Am, G7, Dm7 fallan; l24 (main): lo mismo Comunicado en la #806
140. GrothendieckParseSkill responde a una pregunta Su patrón de superficie deja pasar ⊗, ⊕, ×, ∘ y algunas palabras, pero no “+”, “^” seguido de un espacio, Ω, “=>” ni una llamada como “Invert(C)”, así que responde para 12 de las 50 formas. Solo quita una palabra de anclaje inicial seguida de un espacio y un “mean” o un “do” final: “Parse:”, “please parse”, “can you parse” y un “please” final llegan al analizador y fallan, y “explain the tensor product” se analiza como una expresión. La respuesta nombra el caso y da una glosa escrita para el caso: “parse C ⊗ G” y “parse F# ⊗ Bb” reciben la misma respuesta, salvo la expresión GrothendieckParseSkill.cs líneas 74-109, líneas 146-163, líneas 244-276 l24, las expresiones: “parse ” answered for 12; las preguntas: Parse: C ⊗ G, can’t parse; explain the tensor product, can’t parse; la misma respuesta salvo la expresión: yes; l24 (main): lo mismo Comunicado en la #806
141. La pista de transposición se activa con las preguntas de transposición Se activa con 16 de las 26 formulaciones. No se activa con 3 de los 13 prompts de ejemplo de TransposeSkill, “What’s Dm7 up a whole step?”, “raise the key by two semitones” y “lower the key by a half step”, ni con el “Cmaj7 in the key of G” del SKILL.md, ni con “Shift the song to the key of E”: necesita una palabra que empiece por “transpos”, o “shift”, “bring” o “move” seguida de “up”, “down”, o de “to” y una mayúscula. Dos prompts de ejemplo que nombran un intervalo refuerzan igual a skill.interval; “Raise Bb7 by a minor third” y “Lower G by a tritone” solo refuerzan a skill.interval, y “Play this song a whole step down” solo a skill.alternatetunings DefaultRoutingHintProvider.cs líneas 257-259, líneas 74-76, líneas 159-161, TransposeSkill.cs líneas 41-60 l25, las formulaciones de transposición: la pista de transposición 16 de 26, la de otra intención 6, 3 de ellas sin la pista de transposición, ninguna pista 7; l25 (main): lo mismo Comunicado en la #809
142. La pista de transposición y los disparadores del SKILL.md de transposición se quedan en las transposiciones La pista se activa con 10 de los 407 prompts de ejemplo de las demás intenciones: “transposition” y “transpositionally” en dos prompts de teoría de conjuntos y en “What are modes of limited transposition”, el funtor “Transpose” en cinco prompts de análisis, y “move from G7 to C” y “move from C to G”. Los disparadores, leídos como subcadenas, están en 8: “up a” en “what notes make up a G7 chord” y “Brighten up a minor key tune”, “in the key of” en “All chords in the key of D”, y “transpose” en los cinco prompts de análisis DefaultRoutingHintProvider.cs líneas 257-259, skills/transpose/SKILL.md líneas 4-11, SkillMdDrivenSkill.cs líneas 54-65 l25, las demás intenciones: 407 prompts de ejemplo de 34 intenciones, la pista de transposición 10, un disparador 8; l25 (main): 412 de 35, las mismas 13 filas Comunicado en la #809
143. La skill cuyos disparadores leen las transposiciones puede ser elegida por el enrutador Dos skills se llaman Transpose: TransposeSkill, detrás de skill.transpose, cuyo CanHandle no acepta ninguna de las 26 formulaciones, y la SkillMdDrivenSkill construida a partir de su SKILL.md, cuyos disparadores aceptan 18 pero que no está detrás de ninguna intención, como las 18 skills que construye SkillMdPlugin SkillMdDrivenWrapperBase.cs línea 85, SkillMdPlugin.cs líneas 83-92 l25, las skills: TransposeSkill 0 de 26, SkillMdDrivenSkill 18 de 26, construidas a partir de un SKILL.md 18, detrás de una intención 0; l25 (main): lo mismo Comunicado en la #809
144. Sin embeddings, una transposición recibe una transposición o un mensaje de que no se puede responder En el commit fijado, el enrutador de intenciones no enruta ninguna de las 26 formulaciones y el endpoint de chat responde HTTP 500 a todas. En main, el respaldo por palabras clave del enrutador de intenciones no puede elegir skill.transpose, cuyo CanHandle dice que no: envía 2 a ChordInfoSkill, que da las notas del acorde antes de la transposición, y “Lower G by a tritone” a ChordSubstitutionSkill, las tres etiquetadas orchestrator-skill-semantic. Las palabras clave del enrutador de agentes envían 16 al agente de voicings, que no tiene lista de palabras clave y puntúa 0,1: “Shift Am7 up a fifth” recibe voicings de Am7. 7 reciben “Our reasoning service is currently unavailable” SemanticIntentRouter.cs líneas 115-127, SemanticRouter.cs líneas 70-73; en main, SemanticIntentRouter.cs líneas 313-335, OrchestratorSkillIntent.cs línea 29, línea 54, SemanticRouter.cs líneas 341-365 l25, sin embeddings: el enrutador no elige nada 26 veces, HTTP 500 26; l25 (main): el enrutador no elige nada 23 veces, skill.chordinfo 2, skill.chordsubstitution 1; el endpoint de chat responde con voicing (keyword) 16, fallback-direct 7 Comunicado en la #809
145. Cada modo del catálogo de ModesSkill es el primer modo de su familia tocado desde el grado del modo El modo 1 es la escala de un manual en las 26 familias. De los 129 modos, 93 son el modo 1 desde su grado, 2 desde otro grado, el “Blues Minor” y el “Minor Pentatonic” de la pentatónica mayor, y 34 desde ningún grado: el Ultralocrio tiene las notas de la escala alterada, tres séptimos modos empiezan por C Dbb, y los modos 4 a 7 de la napolitana mayor, 8 modos bebop, 3 de Prometeo, 5 de la enigmática, 6 de la húngara mayor y 4 de la In Sen son otras escalas Modes.yaml líneas 242-243, líneas 659-674 l26, las familias: modos 129, desde su propio grado 93, desde otro grado 2, desde ningún grado 34, notas desordenadas 3 Comunicado en la #813
146. ModesSkill solo descarta las familias de acordes y de tríadas de Modes.yaml También descarta “All Interval Tetrachord Family”, cuyo nombre contiene “chord Family” si no se distinguen mayúsculas de minúsculas; su comentario cuenta cuatro familias ModesSkill.cs líneas 515-516, líneas 530-532 l26: familias 26, descartadas 5 Comunicado en la #813
147. Las fórmulas de ModesSkill dan a cada nota su grado Son las de un manual para 65 de los 129 modos: 60 de los 63 modos de siete notas, ya que los otros tres tienen sus notas desordenadas, 3 de los 14 modos de seis notas y 2 de los 10 de dos notas, y ninguno de los 15 modos de cinco notas, de los 26 de ocho notas ni del único modo de doce notas. Una escala de dos notas puede recibir la nota equivocada: 1 2 para C F. Leer cada número de la letra daría los grados de 52 de los 63 modos de siete notas ModesSkill.cs líneas 779-811 l26, las fórmulas: las de la skill 65 de 129; las de las letras 52 de los 63 modos de siete notas Comunicado en la #765, con los recuentos de la lección 26 en un comentario
148. What is <mode name>? recibe ese modo 119 de los 129 nombres de modos reciben su modo, y también los 68 nombres alternativos. Ocho nombres no van entre comillas y pierden todo a partir de “ #“, y “Lydian #6” se convierte en “Lydian”; después repiten un nombre que aparece antes en el catálogo; “Minor Pentatonic” y “Whole-Half Diminished” están dos veces en el catálogo. CanHandle acepta todos los nombres de modos, pero 7 de los 68 nombres alternativos Modes.yaml líneas 631-681, ModesSkill.cs líneas 244-255, líneas 137-144 l26, los nombres: escritos 165, leídos de otro modo 8; nombres de modos con su modo 119 de 129, nombres alternativos 68 de 68; CanHandle 129 y 7 Comunicado en la #813
149. Los prompts de ejemplo de ModesSkill reciben la respuesta que piden “List unnamed modal families” recibe los modos de la escala mayor, la respuesta por defecto, porque la rama atonal busca “unnamed famil”; “What modes have a major 7th” también los recibe, y “Mixolydian versus Ionian differences” recibe solo el mixolidio. CanHandle acepta 11 de los 37 ModesSkill.cs línea 606, líneas 202-207 l26, los prompts de ejemplo: 37, CanHandle 11 Comunicado en la #813
150. OutsideNotesSkill clasifica una nota como lo hace un manual Sobre cinco acordes de séptima, 42 de las 60 notas reciben el veredicto del manual, y 12 más el mismo consejo. La #9 y la b7 sobre Cmaj7, la #11 sobre Cm7 y la 13 sobre Cm7b5, que ninguna escala de acorde habitual contiene, son “an available tension”, “Safe to sustain as an extension”. La b9 y la b13 de C7 son notas a evitar: el titular de la b9 lo dice, y su explicación lo contrario OutsideNotesSkill.cs líneas 141-189 l27, la regla: casillas 60, iguales 42, notas a evitar que ninguna escala habitual contiene 12, tensiones que ninguna escala habitual contiene 4, notas a evitar que el manual hace tensiones 2 Comunicado en la #814
151. La 11 sobre un acorde extendido recibe el veredicto que recibe sobre el acorde de séptima F sobre C11, C13, Cmaj11 y Cmaj13 es “a chord tone — the perfect eleventh”, mientras que sobre C7, C9, Cmaj7 y Cmaj9 es una nota a evitar, un semitono por encima de E, que los acordes más grandes siguen conteniendo: ChordVocabulary apila terceras hasta la 11 ChordVocabulary.cs líneas 134-138 l27, F sobre C y sus acordes extendidos Comunicado en la #814
152. OutsideNotesSkill lee la nota y el acorde que nombra una pregunta Las 14 notas escritas con # o b se leen bien, las 14 escritas con ♯ o ♭ se leen como naturales, y las 7 notas en minúscula reciben el rechazo. 27 de los 40 acordes que tiene ChordVocabulary se leen bien: la serie del acorde se detiene en “-”, “o”, “(”, ♭, ♯ y en la segunda letra de ma7 y mi7, así que Cma7 queda Cm; °, Δ y Δ7 (como en la #783) se convierten en C E G, como 7sus4, mMaj7, 7#11 y maj7#11, que el vocabulario no tiene. “over a minor chord” es A mayor, “over a dominant chord” D mayor OutsideNotesSkill.cs líneas 289-299, ChordVocabulary.cs líneas 81-84, línea 140 l27, las notas: naturales, # y b 7 de 7 cada una, ♯, ♭ y minúsculas 0; los acordes: 27 de 40, y 0 de los 5 que el vocabulario no tiene Comunicado en la #814
153. La evidencia de la skill escribe las notas del acorde Las nombra a partir de dos tablas de doce nombres: bien sobre 12 fundamentales en 11 acordes mayores, 8 menores, 9 de séptima de dominante, 11 de séptima mayor, 8 de séptima menor, 6 semidisminuidos, 3 de séptima disminuida y 6 aumentados. C7 es C E G A#, F# mayor Gb Bb Db, Cdim7 C Eb Gb A OutsideNotesSkill.cs líneas 226-241 l27, las notas del acorde Comunicado en la #814
154. Los prompts de ejemplo de OutsideNotesSkill reciben una respuesta “why does that note clash over the chord”, “why does the note clash over this chord” y “why does the b9 sound so tense over C7” reciben el rechazo. CanHandle acepta 8 de los 10, no “what is F over G7”, que la skill responde OutsideNotesSkill.cs líneas 31-34, líneas 48-86 l27, los prompts de ejemplo: 10, CanHandle 8, rechazados 3 Comunicado en la #814

La petición, el 2026-09-14: un curso sobre el índice OPTIC-K, sobre todo el código de aprendizaje automático y de agentes de GA, y sobre lo que el chatbot intenta conseguir. El curso está en Aprendizaje automático, junto a IX: trata de construir y usar embeddings, un índice vectorial y un enrutador de tipo clasificador dentro de un producto, no de usar agentes de programación, que es lo que cubre Desarrollo asistido por IA.

2026-09-14 — Fijar GA y compilar contra el host del chatbot

Sección titulada «2026-09-14 — Fijar GA y compilar contra el host del chatbot»
  • GA está fijado en a826864, el commit que usa el curso de teoría musical. El clon local del autor no se usa nunca: fetch-ga.sh hace un clon parcial sin blobs y disperso en code/ga-ai/.ga, ignorado por Git, excluyendo 17 carpetas de proyecto y los PDF de investigación de GA.
  • En Windows, el primer checkout falló con rutas de más de 260 caracteres; git config core.longpaths true antes del checkout lo resuelve. Como en el curso de teoría musical, MSYS_NO_PATHCONV=1 impide que Git Bash reescriba los patrones del checkout disperso.
  • El proyecto del curso referencia directamente GaChatbot.Api y lo arranca con WebApplicationFactory<Program>. Hicieron falta dos detalles: un atributo de ensamblado, WebApplicationFactoryContentRootAttribute, que apunta a la carpeta del host dentro del clon (GaAi.csproj); y ninguna instrucción de nivel superior en el programa del curso, cuya clase Program generada chocaría con la del host.
  • La máquina del autor ejecuta Ollama. Sin intervenir, el host lo habría usado, y las salidas habrían sido distintas de las de la CI. El curso fija la dirección de Ollama en http://127.0.0.1:9, cerrada en la máquina del autor y en los runners.
  • La memoria de chat de GA usa por defecto archivos bajo ~/.ga. El curso registra su propio MemoryStore y su propio ChatTranscriptStore sobre una carpeta nueva junto al programa; se comprobó que ~/.ga no cambia tras una ejecución.
  • El primer corpus, 5 trastes y una ventana de 4, tenía 77.140 voicings y tardaba 33 segundos en calcular sus embeddings. 3 trastes y una ventana de 3 dan 15.360 voicings en unos 8 segundos, suficiente para cada punto de la lección 3.
  • Los mensajes de excepción varían entre sistemas (errores de socket). La lección 4 solo imprime el tipo de excepción y el marco de GA más interno, file:line, sin duplicados y ordenados.
  • Compilación local de los proyectos de GA y del curso: unos 23 segundos después de la primera restauración; una comprobación completa de las cuatro lecciones, 40 segundos.
  • Ejecución 34917150100, para el commit 43f009d: las lecciones 1 a 3 pasaron en todas partes, y la lección 4 pasó en Windows y falló en Linux y macOS. En esos dos sistemas, los avisos del enrutador semántico de intenciones aparecían también bajo la primera petición.
  • Causa: IntentEmbeddingWarmupService lanza en segundo plano el cálculo de los embeddings de las intenciones cuando arranca el host, y sus avisos caen en la petición que se esté ejecutando. Corrección en el commit 8e335d7: el curso espera la última línea de log del precalentamiento antes de enviar peticiones. La lección 4 cuenta la historia.
  • Ejecución 34917602262, para 8e335d7: en verde en los tres sistemas, 1 min 34 s en Linux, 1 min 50 s en macOS y 3 min 2 s en Windows, clon y compilación incluidos.

2026-09-14 — Diferencias encontradas en el código de GA (commit a826864)

Sección titulada «2026-09-14 — Diferencias encontradas en el código de GA (commit a826864)»

Cada punto indica dónde lo muestra el programa del curso. Ninguno se ha comunicado a GA.

Embeddings (lección 2):

  1. VoicingDocumentFactory asigna RootPitchClass y MidiBassNote a partir de MidiNotes[0] (líneas 37-38). GA construye los voicings empezando por la cuerda 1 (E aguda), así que esa nota es la nota más aguda. ROOT, MODAL, el bajo de MORPHOLOGY y la inversión se calculan a partir de ella; el filtro de búsqueda usa MidiNotes.Min(), el bajo real. Lo muestran l2, “From a chord shape to GA’s voicing document” (C abierto: fundamental E, inversión 1), y la búsqueda de Cmaj7 de l3.
  2. La inversión compara esa nota con el nombre de la fundamental del acorde, leído por PitchClass.Parse (líneas 43-44), que lee los nombres de nota como dígitos: "A" vale 10 y "E" vale 11. Un Em en estado fundamental, 022000, recibe Inversion = -1. Reproducido con un programa aparte que referencia GA.Business.ML, fuera de la CI del curso: PitchClass.Parse("E") = 11, y 022000 Em ChordId.RootPitchClass="E" doc.RootPitchClass=4 inversion=-1. El curso de teoría musical encontró el mismo comportamiento del parser.
  3. VoicingHarmonicAnalyzer pasa intervalSpread > 12 a IsRootless y false a IsOpenVoicing del record posicional VoicingCharacteristics (líneas 31-43). Todo voicing que abarca más de una octava es “rootless”. Lo muestra l2, “VoicingCharacteristics and PerceptualQualities”.
  4. VoicingAnalyzer construye new PerceptualQualities(curVoiceChars.Consonance, 0, 0, "Neutral", "Medium") para un record declarado (Brightness, ConsonanceScore, Roughness, ...) (línea 164). ConsonanceScore vale siempre 0, la Consonance del documento también, y la tensión de CONTEXT, 1.0 - doc.Consonance, vale siempre 1. Es la dimensión constante de la issue #616, cuyo análisis solo culpa a los literales de al lado. La misma sección de l2, y la fila CONTEXT de “Dimensions that never vary” de l3.
  5. EmbeddingSchema.AtonalModalDim vale 17 mientras que el registro da 64 posiciones a ATONAL_MODAL; ModalVectorService reserva 17 (línea 116) y WriteInto no comprueba las longitudes: 47 posiciones valen siempre cero (l3). HierarchyDim vale 8 frente a 15 (l2, “Loose constants”). Las dos particiones tienen peso 0, así que la búsqueda no se ve afectada.
  6. STRUCTURE no es invariante a la transposición (221 de 222 clases de conjuntos, l2), como dicen el propio barrido de GA y el comentario de TheoryVectorService; el resumen de RootVectorService todavía afirma “genuinely O+P+T+I-invariant” (líneas 3-7).
  7. Los pesos de similitud suman 1,15; un vector puntúa 1,15 frente a sí mismo (l2). No es un error, pero “coseno” induce a confusión en los logs y en los umbrales.
  8. Versiones en comentarios y documentos: el documento de esquema más reciente es v1.4.1, OPTIC-K_Embedding_Schema.md describe v1.3.1 (109 dimensiones), MusicalEmbeddingGenerator dice 228 (línea 13) y 216 (línea 55), el comentario de CompactDimension dice 112, OptickIndexWriter y MusicalQueryEncoder dicen 112, y el comentario de ExtensionsEnd dice que es igual a TotalDimension. El código calcula 240 y 124.

Índice y búsqueda (lección 3):

  1. Nueve de las 33 posiciones MODAL con nombre no se activan nunca en el corpus de 15.360 voicings: LocrianNatural6, DorianSharp4, LydianSharp2, AlteredDoubleFlat7, DorianFlat2, LydianAugmented, MixolydianFlat6, LocrianNatural2, Diminished. ModalVectorService busca los modos por nombres visibles como "Locrian ♮6" y vuelve en silencio cuando no encuentra nada; la causa probable es un nombre que no coincide (por verificar).
  2. 37 de las 124 dimensiones buscadas valen siempre cero y 4 son constantes en ese corpus (l3); la #616 indica 40 dimensiones muertas en el índice en producción.
  3. ApplyFilters compara la calidad como subcadena del nombre almacenado: el filtro Am7 acepta Gbm7(shell)/A, y la calidad vacía de C acepta cualquier nombre con C en el bajo, incluidos C + E (Major 3rd) y Am/C (líneas 296-329).
  4. OptickSearchStrategy.FindSimilarVoicingsAsync devuelve siempre una lista vacía (conocido, comentado en las líneas 75-92). MusicalQueryEncoder deja el vector interválico fuera de las consultas (conocido, comentado).

Diagramas y herramientas MCP:

  1. Dos órdenes para la misma cadena de diagrama: VoicingGenerator, el índice y el parser de la herramienta MCP leen primero la cuerda 1 (E aguda); PlayableNotationFormatter lee primero la E grave (líneas 31-53). La tablatura del chatbot para 3-0-x-2-3-x (Cmaj7) es 6/3 5/0 3/2 2/3, las notas G A A D (l4).
  2. La descripción de ga_generate_voicing_embedding dice “228-dim” y da 'x-3-2-0-1-0' for Cmaj7 (líneas 42-44); el parser de la herramienta lo lee como Dsus2/E (l2), y leído empezando por la E grave sería C, no Cmaj7.
  3. ga_get_embedding_schema enumera diez particiones, sin ROOT, con las constantes sueltas HierarchyDim y AtonalModalDim (líneas 69-91). Leído en el código, no ejecutado por el curso.

Chatbot (lecciones 1 y 4):

  1. Sin servidor de embeddings, todo mensaje que no captura ninguna guarda termina en HTTP 500. SemanticRouter.RouteAsync no captura la excepción de EnsureEmbeddingsInitializedAsync (líneas 68-104), así que su respaldo por palabras clave es inalcanzable; el respaldo del host, una llamada directa al modelo, también lanza una excepción. “What is the relative minor of C major?” falla aunque skill.relativekey la responde con una confianza de 1.00 (l4).
  2. La antigua vía CanHandle envía esa misma pregunta a ScaleInfo, no a la skill de tonalidad relativa (l4).
  3. skill.fretspan no tiene ningún prompt de ejemplo, y SemanticIntentRouter se salta las intenciones sin ejemplos: nunca se puede enrutar hacia ella (l1).
  4. ProductionOrchestrator.AnswerStreamingAsync (desde la línea 154) tiene la guarda de voicings pero no la vía rápida de álgebra de AnswerAsync. Leído en el código, no ejecutado.
  5. IntentEmbeddingWarmupService lanza su trabajo sin esperarlo (lanzar y olvidar); está bien para un servidor, pero entonces los logs de un host dependen de los tiempos (el fallo de CI de arriba).

Documentos:

  1. docs/architecture/chat-surfaces.md dice en su estado del 2026-05-13 que GaChatbot.Api es la superficie canónica y sirve la demo pública (líneas 16-21), mientras que secciones posteriores dicen que la página desplegada llama a SignalR en GaApi y tratan las dos como paralelas a la canónica (líneas 215-223 y 262).
  2. El CLAUDE.md de GA dice que ix produce optick.index; en el código de GA y en su skill optic-k-rebuild, lo escribe FretboardVoicingsCLI. CLAUDE.md nombra GA.Business.Core.Harmony y GA.Business.Core.Fretboard como capa 3; el generador y el analizador de voicings están en GA.Domain.Services.

Pistas no comprobadas por el curso, anotadas antes al leer los documentos de GA (por verificar): puede que GaChatbotCli no consiga resolver sus servicios; el backlog y la hoja de ruta no coinciden en algunos estados; los documentos de GA dan varios tamaños para el índice en producción (161, 168, 175, 176 y 660 MB).

La mayoría de las 22 diferencias del 2026-09-14 se corrigieron upstream en #689, fusionada el 2026-09-23, que también lleva los commits fusionados de nuevo como #686 y #688 el 2026-09-24. Las correcciones de código vienen con tests en GA. Este curso no las ha vuelto a ejecutar: sigue fijado a a826864 (por verificar).

  • Corregidas: 1 y 4 (documentos de voicing construidos a partir de la fundamental del acorde, la nota más grave y los campos con nombre del analizador), 2 (fundamentales leídas como nombres de notas), 3 (argumentos con nombre), 5 (constantes HIERARCHY y ATONAL_MODAL alineadas con las particiones), 6 (el resumen de RootVectorService), 8 (los comentarios 112/216/228 y v1.3.1), 9 (casillas MODAL buscadas con los nombres del catálogo de modos), 11 (el filtro de acordes compara fundamental, cualidad y bajo opcional), la mitad «consulta» de 12 (el vector de intervalos de la consulta se codifica), 13 (el orden de cuerdas de los diagramas es explícito), 14 y 15 (la herramienta de esquema lee EmbeddingSchema), 16 (vuelta a las palabras clave, y una respuesta «no disponible» en lugar de un HTTP 500), 17, 18, 19, 21 y 22.
  • Sin cambios: 7, que no es un error; la otra mitad de 12, FindSimilarVoicingsAsync, sigue devolviendo una lista vacía, como dice su comentario; 20, que #688 lista como encontrada y no modificada. 10 no se volvió a medir, y las correcciones 5 y 9 tocan dimensiones que contaba.

2026-09-28 — Lección 5: la skill de improvisación

Sección titulada «2026-09-28 — Lección 5: la skill de improvisación»
  • La petición, el 2026-09-28: más lecciones que ayuden al chatbot de GA. Ese mismo día, un tracer ejecutado contra el chatbot público había encontrado que “which arpeggio fits Am F C G” recibe F jónico y G jónico, registrado como la issue de GA #744. La lección 5 reproduce ese hallazgo sin conexión, en la CI del curso, y lo extiende a acordes sueltos.
  • ImprovisationSkill.cs es idéntico en a826864 y en el main de GA en 8cd5042 (git diff --stat entre los dos sale vacío), así que la skill fijada sigue siendo la que ejecuta el chatbot. Si el enrutador desplegado envía a esta skill todos los prompts de la lección no lo comprueba el curso (por verificar); el tracer vio que lo hacía con Am F C G.
  • La vía de progresión nunca llama al IMusicalQueryExtractor de la skill, la única dependencia que necesita un modelo. El curso le pasa un extractor que lanza una excepción, así que un cambio en GA que hiciera que esa vía llamara a un modelo haría fallar la ejecución.
  • Las tablas del oráculo tienen que cubrir todos los nombres de escala que la skill puede devolver; un nombre que falte lanza una excepción. Una progresión se ejecutó una sola vez y no se conservó en el programa: Bb Gm Cm F, para la solución del primer ejercicio.
  • Ejecución de CI 36425151971, para el commit c2ab348: verde en los tres sistemas, 1 min 42 s en Linux, 2 min 4 s en macOS, 2 min 59 s en Windows, con el clon y la compilación incluidos.

2026-09-28 — Lección 6: la respuesta en el cable

Sección titulada «2026-09-28 — Lección 6: la respuesta en el cable»
  • La ejecución del tracer del 2026-09-28 vio que la página pública mostraba la lista de la respuesta de improvisación como una sola viñeta. La #743 corrigió la causa, SseChunker, ese mismo día, y la #746 registró un segundo defecto, en el escritor de GaApi. La lección 6 comprueba todo el cable sin conexión, en la CI del curso: el flujo del host real, leído por un lector escrito a partir del estándar HTML, y después dos escritores y tres lectores con la división fijada y con la corregida.
  • El programa tiene copias de los dos escritores y versiones portadas de dos lectores JavaScript, el consumeSseStream de la página y el parseSseBuffer de ga-client. La copia del escritor de GaChatbot.Api se contrasta con los bytes del host en cada ejecución; el escritor de GaApi y los dos lectores no se ejecutan en su propio entorno, así que una versión portada que se apartara de su fuente pasaría desapercibida.
  • GA construye sus respuestas con StringBuilder.AppendLine, así que /chat devuelve saltos de línea CRLF en Windows. La primera ejecución de l6 imprimía “no” donde los eventos de texto y /chat solo diferían en los CR, y unos recuentos que cambiaban según el sistema. El programa compara ahora con saltos de línea LF. El flujo del host es el mismo en todos los sistemas: su escritor elimina los CR.
  • La traza del evento de enrutamiento contiene tiempos que cambian en cada ejecución; el programa imprime el evento cortado en una coma.
  • ChatStreamAsync espera la respuesta completa antes del primer evento: el flujo se muestra frase a frase, pero la primera frase sale cuando ya se conoce la última.
  • El escritor de GaApi (#746) está latente en a826864: git grep no encuentra ningún llamador de sendChatMessageStream ni de streamChat en Apps/ga-client/src, y el chat de React habla AG-UI, cuyos eventos JSON escapan los saltos de línea.
  • Ejecución de CI 36509333842, para el commit ed723b9: verde en los tres sistemas, 1 min 47 s en Linux, 1 min 13 s en macOS, 3 min 6 s en Windows, con el clon y la compilación incluidos.

2026-09-28 — Lección 7: nombres de acorde que el chatbot no sabe leer

Sección titulada «2026-09-28 — Lección 7: nombres de acorde que el chatbot no sabe leer»
  • La petición: la lección siguiente, sobre la #745. Cuando se preparó, la pull request #749 ya se había fusionado (2026-09-28, 23:32 UTC) y había cerrado la #745. Cambiar el commit fijado del curso cambiaría la salida de todas las lecciones, así que la lección 7 compila en su lugar los tres archivos de GA.Business.ML de la #749 junto al ensamblado fijado, en el proyecto GaFix749, y llega a su ImprovisationSkill mediante el extern alias fix749. fetch-ga.sh extrae los archivos del clon sin blobs con git show, y descarga el commit cuando un clon más antiguo no lo tiene.
  • La #749 cambió dos archivos de GA.Business.ML: InvalidChordNames.cs, nuevo, e ImprovisationSkill.cs; el tercer archivo que compila la lección, ChordIntentMatching.cs, es igual en los dos commits. Los demás cambios de la #749 están en ProductionOrchestrator.cs y en tests, así que la skill y la guarda se ejecutan como en main; la llamada del orquestador a la guarda se ha leído, no ejecutado.
  • El primer corpus tenía un solo caso Unicode, B♭ E♭ F. Al comprobar un ejercicio, normalizar ♭ y ♯ seguía dejando F# leído como F: la fundamental con sostenido en ASCII puro también se lee mal, por el \b final de la expresión de la skill. El corpus ganó las filas 10 a 12, con C+ y Bø7, los otros cifrados que terminan donde no puede haber un \b.
  • Las soluciones de los ejercicios 1 y 2 se comprobaron editando el programa del curso y el archivo de la #749 para una sola ejecución; fetch-ga.sh restaura el archivo una vez borrado .ga-fix/SHA.
  • Ejecución de CI 36518749257, para el commit 226fbb0: verde en los tres sistemas, 1 min 28 s en Linux, 1 min 36 s en macOS, 3 min 20 s en Windows, con el clon, la descarga de los archivos de la #749 y la compilación incluidos.
  • Cuatro issues de GA, abiertas a partir de las filas de las lecciones 5 a 7, cada una con la ejecución del curso como prueba:
    • #757: la skill lee símbolos de acorde como otros acordes, o los descarta sin aviso (filas 23 y 35 a 38);
    • #758: cualidades mal clasificadas, y arpegios que añaden una nota (filas 24 a 27);
    • #759: las peticiones que la guarda de la #749 deja pasar (filas 33 a 35);
    • #760: la página de GaChatbot.Api muestra el evento de error del flujo como la respuesta, y lo guarda en el historial (fila 29).
  • El código que citan no ha cambiado en main en fc76ad6 (2026-09-29), salvo los separadores de interjecciones de la guarda de la #749 (2d9c5e3), que no cambian sus filas.

2026-09-29 — Lección 8: el propio examen del chatbot

Sección titulada «2026-09-29 — Lección 8: el propio examen del chatbot»
  • La petición: más lecciones que ayuden al chatbot de GA. El curso todavía no había ejecutado el oráculo propio de GA, el corpus de prompts. Está fuera del checkout disperso, así que fetch-ga.sh lo copia con git show en .ga-files/.
  • El host del curso funcionaba sin la carpeta skills/ de GA desde la lección 4. SkillMdPlugin la busca en la raíz del repositorio git que contiene el programa en ejecución, aquí el repositorio del curso. Ahora fetch-ga.sh la incluye en el checkout, y el host define SKILLMD_SKILLS_PATH; las salidas de las lecciones 1 a 7 no cambian. Antes del cambio, el texto del envoltorio hacía que los siete prompts diatónicos se marcaran como backend degradado; después, fallan como respuestas corrientes, que es la fila 42.
  • Una clave en el entorno habría llegado a Anthropic: con una clave falsa en ANTHROPIC_API_KEY, el host recibió AnthropicUnauthorizedException. Ahora el host fija Anthropic:ApiKey en una cadena vacía, y la salida con la clave falsa es la misma que sin ella.
  • Las soluciones de los ejercicios 1 y 2 se comprobaron editando el programa del curso para una sola ejecución; las del 3 y el 4 se resolvieron a mano.
  • Ejecución de CI 36584340462, para el commit a305edf: verde en los tres sistemas, 1 min 58 s en Linux, 2 min 24 s en macOS, 6 min 41 s en Windows, con el clon, la extracción de skills/, la descarga del corpus y la compilación incluidos.
  • Comunicado upstream el mismo día: la #763 para las filas 39, 41 y 44, la #764 para las filas 42 y 43 y la #765 para las filas 40 y 45.

2026-09-29 — Lección 9: cada intervalo, cada tonalidad

Sección titulada «2026-09-29 — Lección 9: cada intervalo, cada tonalidad»
  • La petición: más lecciones que ayuden al chatbot de GA. Después del corpus de prompts, las tres skills que responden, sin modelo, a preguntas con una sola respuesta correcta: intervalos, escalas y tonalidades relativas. El oráculo del curso es la aritmética de letras de un manual, en Lesson9.cs.
  • Los intervalos del dominio se comprobaron una vez contra el main de GA en 53b7253, fuera del curso: GA.Core, GA.Domain.Core, GA.Business.Config e IntervalNaming.cs, extraídos con git archive en una carpeta temporal y ejecutados sobre los 441 pares con las notas bien leídas. Los 21 unísonos y los otros 5 intervalos erróneos salen igual, y también C a B#, una séptima aumentada que llama mayor.
  • La solución del ejercicio 1 se comprobó con el motor de expresiones regulares de .NET, y la del 4 haciendo sus dos preguntas en una sola ejecución; las del 2 y el 3 se resolvieron a mano.
  • Ejecución de CI 36666224042, para el commit 73fd84d: verde en los tres sistemas, 1 min 52 s en Linux, 1 min 48 s en macOS, 6 min 38 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream al día siguiente: la #767 para las filas 46, 47, 49 y 53, la #768 para la fila 48 y la #769 para las filas 50 a 52.

2026-09-30 — Lección 10: en qué se le dice al modelo que confíe

Sección titulada «2026-09-30 — Lección 10: en qué se le dice al modelo que confíe»
  • La petición: más lecciones que ayuden al chatbot de GA. Después de las skills que deletrean sin modelo, las tres que pasan la pregunta a uno y le dicen que llame a una closure a través de ga_dsl_eval: transposición, acordes diatónicos y notas comunes. El curso llama él mismo a la herramienta, DslEvalMcpTools.EvalClosure, con los argumentos de cada SKILL.md; el modelo no se ejecuta.
  • DomainClosures.fs ha cambiado en el main de GA en 53b7253, así que el código al que llama la lección se comparó función por función entre a826864 y main: los dos arrays de nombres, preferFlat, transposeChord, diatonicChords, conventionalKeyName y la línea en la que commonTones nombra una nota son idénticos. ChordParser.fs ha cambiado allí para formas que la lección no envía.
  • Las funciones auxiliares del manual de Lesson9.cs pasaron a ser internal para que la lección 10 las reutilice; la salida de l9 no cambia.
  • Las soluciones de los ejercicios se resolvieron a mano a partir del código.
  • Ejecución de CI 36668901083, para el commit 6f91f88: verde en los tres sistemas, 2 min 01 s en Linux, 2 min 19 s en macOS, 6 min 29 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream el mismo día: la #770 para las filas 54 a 57.

2026-09-30 — Lección 11: los acordes que lee la skill de tonalidad

Sección titulada «2026-09-30 — Lección 11: los acordes que lee la skill de tonalidad»
  • La petición: más lecciones que ayuden al chatbot de GA. Después de las skills que llaman a una closure, aquella cuya respuesta se calcula antes de que el modelo vea la pregunta: la identificación de la tonalidad. Las dos superficies del chatbot, KeyIdentificationSkill y el SKILL.md a través de ga_key_identify, ejecutan KeyIdentificationService; el curso llama directamente a sus pasos, y el modelo no se ejecuta.
  • La detección de la tonalidad ha cambiado en el main de GA desde el commit fijado (#625, #729), después de que el curso de teoría musical pusiera a prueba las herramientas del servidor MCP de GA, que reciben solo los acordes. La lección compila el servicio de main en 6baf32e contra el dominio fijado (proyecto GaKeysMain, extern alias keysmain) y hace la pregunta del chatbot, una frase. En main en 5c3a52a, el servicio no ha cambiado desde 6baf32e.
  • Las respuestas del commit fijado se contrastan con la propia ga_key_identify, en las 99 preguntas. El parser del servicio y el BuildPrompt de la skill son privados; el programa los llama por reflexión.
  • La solución del ejercicio 1 se comprobó con el motor de expresiones regulares de .NET sobre las 90 preguntas de la lección; las demás se resolvieron a mano a partir del código.
  • Ejecución de CI 36758614173, para el commit 8c2221d: verde en los tres sistemas, 1 min 54 s en Linux, 2 min 24 s en macOS, 6 min 41 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream el mismo día: la #771 para las filas 58, 59 y 61, la #772 para las filas 60, 62, 63 y 64.

2026-09-30 — Lección 12: lo que responden las skills de progresión

Sección titulada «2026-09-30 — Lección 12: lo que responden las skills de progresión»
  • La petición: más lecciones que ayuden al chatbot de GA, sobre el análisis de progresiones. El chatbot no tiene ninguna skill de análisis: skills-dev/_pending-tools/progression-analysis/DRAFT.md está bloqueado a la espera de una herramienta, en el commit fijado y en main. La lección trata las dos skills que reciben una progresión, ProgressionMoodSkill y ProgressionCompletionSkill. La closure domain.analyzeProgression del DSL, a la que llama GaMcpServer y ninguna skill del chatbot, queda para una lección posterior.
  • La skill de ambiente se ejecuta a través de su intención en GaChatbot.Api, sin modelo. El prompt de la skill de continuación se lee llamando por reflexión a su BuildPrompt privado; para main, sus líneas se aplican al servicio en 6baf32e (proyecto GaKeysMain de la lección 11), y para el commit fijado se contrastan con BuildPrompt en las 36 preguntas.
  • Las soluciones de los ejercicios se resolvieron a mano a partir del código y de la salida.
  • Ejecución de CI 36777958134, para el commit e002d6d: verde en los tres sistemas, 2 min 05 s en Linux, 2 min 16 s en macOS, 7 min 24 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream el mismo día: la #773 para las filas 65, 66 y 72, la #774 para las filas 68 a 72.

2026-09-30 — Lección 13: lo que responde el análisis de progresiones

Sección titulada «2026-09-30 — Lección 13: lo que responde el análisis de progresiones»
  • La petición: más lecciones que ayuden al chatbot de GA. La lección 12 dejó para más adelante la closure domain.analyzeProgression del DSL: la skill de análisis de progresiones del chatbot es un borrador bloqueado a la espera de una herramienta, y la closure que necesitaría ya responde a través de ga_dsl_eval.
  • La closure del commit fijado se llama a través de DslEvalMcpTools.EvalClosure, como la llamaría una skill. La de main se compila a partir de DomainClosures.fs en 6baf32e, sin cambios, en un proyecto F#, GaDslMain, contra el GA.Business.DSL fijado y el servicio de GaKeysMain; fetch-ga.sh deja el archivo en .ga-dsl/, y el programa llega al ensamblado a través del alias externo dslmain.
  • El analizador de acordes de main cambió después del commit fijado, en la #686 y en 3707b72, para símbolos que la lección no usa; eso sale de leer el diff, no de una ejecución.
  • Las soluciones de los ejercicios se resolvieron a mano a partir del código y de la salida.
  • Ejecución de CI 36784699663, para el commit 0ace36e: verde en los tres sistemas, 1 min 40 s en Linux, 1 min 25 s en macOS, 7 min 15 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream el mismo día: la #775 para las filas 76 a 78.

2026-09-30 — Lección 14: lo que responde la skill de sustitución

Sección titulada «2026-09-30 — Lección 14: lo que responde la skill de sustitución»
  • La petición: más lecciones que ayuden al chatbot de GA. skill.chordsubstitution responde sin modelo, así que cada una de sus respuestas se puede comprobar contra un manual; sus dos herramientas MCP y la closure domain.chordSubstitutions del DSL responden a la misma pregunta para la vía SKILL.md y para GaMcpServer.
  • El programa llega a la skill como en la lección 12, a través de los intents del host del chatbot, y construye las herramientas con el IGrothendieckService del host. La closure se llama en el commit fijado a través de DslEvalMcpTools.EvalClosure y en main a través de GaDslMain, como en la lección 13. Los proyectos del curso y fetch-ga.sh no cambian.
  • El programa relee las respuestas de la skill en su Markdown con expresiones regulares: un cambio de formato lo detendría en lugar de cambiar un recuento. Los sustitutos de manual, dos por calidad, son una elección del curso, escrita en Lesson14.cs.
  • Las soluciones de los ejercicios 1, 2 y 4 se resolvieron a mano; el recuento del ejercicio 3 se comprobó con las expresiones regulares de .NET, fuera del programa del curso.
  • Ejecución de CI 36788871032, para el commit b9aec40: verde en los tres sistemas, 2 min 11 s en Linux, 1 min 24 s en macOS, 7 min 16 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream el mismo día: la #777 para las filas 79 y 81 a 84, la #776 para la fila 80 y la #778 para las filas 85 y 86.

2026-09-30 — Lección 15: las notas de un acorde

Sección titulada «2026-09-30 — Lección 15: las notas de un acorde»
  • La petición: más lecciones que ayuden al chatbot de GA. skill.chordinfo responde sin modelo a la pregunta más básica que le hace un guitarrista, así que cada respuesta se puede comprobar contra un manual; ga_chord_info la responde para la vía SKILL.md a partir del mismo vocabulario.
  • El programa llega a la skill como en las lecciones 12 y 14, a través de los intents del host del chatbot. Lee lo que la skill entendió en sus líneas de evidencia, Root:, Quality: y Notes:, y lee por reflexión sus 19 fórmulas para listas de notas: un cambio en unas u otras se vería en la salida. Los proyectos del curso y fetch-ga.sh no cambian.
  • Las grafías de manual salen de grados escritos en Lesson15.cs. El viaje de ida y vuelta devuelve a la skill sus propias grafías y no necesita oráculo.
  • Las soluciones de los cuatro ejercicios se comprobaron llamando desde PowerShell a la skill, el vocabulario y las expresiones regulares compilados de GA, fuera del programa del curso.
  • Ejecución de CI 36793871229, para el commit 829eaea: verde en los tres sistemas, 2 min 19 s en Linux, 2 min 42 s en macOS, 7 min 12 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream al día siguiente: la #782 para las filas 87 a 89 y 91 a 93, y la #783 para las filas 90, 94 y 95.

2026-10-01 — Lección 16: los voicings de un acorde

Sección titulada «2026-10-01 — Lección 16: los voicings de un acorde»
  • La petición, el 2026-10-01: más lecciones que ayuden al chatbot de GA. Un comentario de GA presenta ChordVoicingsSkill como la skill más usada del chatbot. Responde sin modelo, y cada voicing que devuelve se puede comprobar tocando su diagrama.
  • Casi toda la cadena de los voicings cambió en el main de GA después del commit fijado; la lectura de la pregunta, no. Por eso la lección ejecuta la skill dos veces: en el commit fijado, a través del host del chatbot como en la lección 15, y en un programa nuevo, GaMain, compilado a partir de un segundo clon parcial sin blobs de GA en f4f5b4a, que descarga fetch-ga.sh. check.sh lo compila y lo ejecuta después de las demás lecciones, así que la CI clona y compila GA dos veces. Los dos programas compilan las mismas preguntas, de code/ga-ai/Shared/ChordVoicingsProbe.cs.
  • GaMain construye la skill y el índice de la lección 3 con las clases de main, como lo hace el cableado del host; el host en sí no se ejecuta en main.
  • Los voicings erróneos del commit fijado, debidos al filtro por subcadena de la diferencia 11 y al orden de los diagramas de la diferencia 13, están corregidos en main: cada voicing que devuelve la skill de main toca el acorde que ha leído.
  • Las soluciones de los cuatro ejercicios se comprobaron ejecutando la skill de GaMain y el CanHandle del commit fijado, fuera de la salida esperada del curso.
  • Ejecución de CI 36870600319, para el commit 6d647b1: verde en los tres sistemas, 3 min 14 s en Linux, 2 min 56 s en macOS, 8 min 40 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream el mismo día: la #785 para las filas 96 a 98, y la #784 para las filas 99 y 100.

2026-10-01 — Lección 17: la cejilla y las afinaciones

Sección titulada «2026-10-01 — Lección 17: la cejilla y las afinaciones»
  • La petición, el 2026-10-01: más lecciones que ayuden al chatbot de GA. CapoSkill y AlternateTuningsSkill se crearon para resolver dos “dealbreakers” del backlog de GA. Responden sin modelo, y cada respuesta se puede comprobar contra un manual: las de la cejilla, con la aritmética de semitonos y las armaduras; las de las afinaciones, con las notas de cada cuerda.
  • En main, CapoSkill solo añade el indicador Declined a su rechazo, así que la lección solo le pregunta en el commit fijado. Las expresiones de nombres de AlternateTuningsSkill cambiaron, así que GaMain gana un modo l17, que hace las preguntas de afinaciones en main. Los dos programas las compilan a partir de code/ga-ai/Shared/TuningsProbe.cs, y check.sh ejecuta GaMain l17 después de GaMain l16.
  • GaMain construye la skill de afinaciones solo con un logger, ya que su constructor no recibe nada más.
  • Una “grafía teórica” es la prueba del curso: una tonalidad o un acorde, mayor o menor, que con esa fundamental y esa cualidad no tiene armadura.
  • La lección 7 y la fila 36 decían que las skills de cejilla y de afinaciones aceptan ♭ y ♯. Sus expresiones prevén los dos signos, pero a menudo los pierden (filas 103 y 106); la frase de la lección 7 y la fila 36 ahora lo dicen.
  • Las soluciones de los cuatro ejercicios se comprobaron ejecutando las skills del commit fijado, fuera de la salida esperada del curso.
  • Ejecución de CI 36944575536, para el commit 5bbae97: verde en los tres sistemas, 2 min 45 s en Linux, 3 min 49 s en macOS, 8 min 34 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream después de la ejecución de CI: la #787 para las filas 101 a 105, y la #788 para las filas 101, 106 y 107.

2026-10-01 — Lección 18: la conducción de voces

Sección titulada «2026-10-01 — Lección 18: la conducción de voces»
  • La petición, el 2026-10-01: más lecciones que ayuden al chatbot de GA. VoiceLeadingSkill se creó el 2026-05-14, como las skills de cejilla y de afinaciones, para resolver un “dealbreaker” del backlog de GA. Responde sin modelo, y cada respuesta afirma ser óptima, algo que una búsqueda exhaustiva más lenta puede comprobar.
  • VoiceLeadingSkill.cs es idéntico en main, así que la lección solo le pregunta en el commit fijado, y GaMain no gana ningún modo.
  • El “movimiento mínimo” es la prueba del curso: tantas voces como notas tiene el acorde con más notas, todas las notas de los dos acordes sonando, y la posibilidad de duplicar cualquier nota del acorde con menos notas.
  • Lesson17.SkillOf ahora es internal, para que Lesson18 lea de la misma manera la skill de una intención.
  • Las soluciones de los cuatro ejercicios se comprobaron ejecutando la skill del commit fijado, fuera de la salida esperada del curso.
  • Ejecución de CI 36957355913, para el commit eadae1f: verde en los tres sistemas, 2 min 11 s en Linux, 4 min 43 s en macOS, 8 min 32 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #789, para las filas 108 a 113.

2026-10-02 — Lección 19: los pares de voicings

Sección titulada «2026-10-02 — Lección 19: los pares de voicings»
  • La petición, el 2026-10-01: una lección sobre ga_voice_leading_pair, la vía que la lección 18 dejó de lado. La herramienta está en GaMcpServer, al que llaman los agentes; el chatbot no la llama, y su skill de conducción de voces en espera sí la llamaría.
  • GaMcpServer queda fuera de los proyectos que compila el curso. fetch-ga.sh añade GaMcpServer/Tools/CompositionTools.cs a los dos clones dispersos, los dos programas lo compilan, y Shared/VoicingSearchTool.cs sustituye a la clase cuyo campo privado Strategy lee la herramienta por reflexión.
  • CompositionTools.cs es idéntico en main, pero la búsqueda a la que llama no. Así que GaMain gana un modo, l19, que escribe el índice de la lección 3 con el código de main y hace las mismas preguntas.
  • En el commit fijado, 80 de los 210 candidatos son exactos y 3 de los 10 primeros pares tocan los dos acordes; en main, 210 y 10. Esto no tiene fila: en main, la búsqueda solo devuelve voicings del acorde pedido, para estos 14 acordes.
  • “no fifth” es el veredicto del curso para un acorde de séptima al que solo le falta la quinta justa, y cuenta como correcto, igual que “exact”.
  • Lesson16.Corpus ahora es internal, para que Lesson19 cuente los voicings exactos de cada acorde en el corpus.
  • La solución del cuarto ejercicio se comprobó ejecutando la herramienta del commit fijado, fuera de la salida esperada del curso; las otras tres se leen en la salida esperada.
  • Ejecución de CI 36964238674, para el commit e8394cd: verde en los tres sistemas, 3 min 17 s en Linux, 2 min 29 s en macOS, 8 min 42 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #791, para las filas 114 a 117.

2026-10-02 — Lección 20: las progresiones generadas

Sección titulada «2026-10-02 — Lección 20: las progresiones generadas»
  • La petición, el 2026-10-02: ga_generate_progression para la lección 20, la compañera de la herramienta de la lección 19 en CompositionTools.cs, que los dos programas ya compilan.
  • La grafía de manual es la del curso: la letra de la fundamental sigue el grado del número romano en la tonalidad, para las 15 armaduras de cada modo.
  • El programa lee las tablas de transposición de ChordProgressions.yaml línea a línea, en el clon del commit fijado.
  • GaMain gana un modo, l20, que solo enlaza: la herramienta y su parser no han cambiado en main, la búsqueda sí.
  • El camino continuo es la búsqueda del curso sobre los mismos 15 candidatos por acorde, con la distancia de la herramienta: un voicing por acorde, elegido por programación dinámica.
  • La solución del cuarto ejercicio se comprobó ejecutando la herramienta del commit fijado, fuera de la salida esperada del curso; las otras tres se leen en la salida esperada y en el código de la herramienta.
  • Ejecución de CI 37045152172, para el commit 2db1270: verde en los tres sistemas, 3 min 14 s en Linux, 4 min 23 s en macOS, 9 min 46 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #792, para las filas 118 a 122.

2026-10-02 — Lección 21: la búsqueda de voicings

Sección titulada «2026-10-02 — Lección 21: la búsqueda de voicings»
  • La petición, el 2026-10-02: ga_search_voicings para la lección 21, la herramienta que la nota de ga_generate_progression nombra para cada acorde.
  • Los programas de las lecciones 19 y 20 compilan ahora el VoicingSearchTool.cs de GA en lugar del sustituto del curso, con la misma salida. Shared/SearchIndex.cs lo dirige al índice del curso mediante GA_OPTICK_INDEX_PATH y desactiva su telemetría mediante GA_VOICING_NO_TELEMETRY, así que el curso no escribe nada bajo el state/ de GA.
  • El voicing rootless es la prueba del curso: tres notas o más, todas del acorde y ninguna su fundamental.
  • “La misma respuesta” compara los diez voicings y sus puntuaciones; la tabla de los modos solo compara los voicings.
  • La solución del segundo ejercicio es aritmética sobre las puntuaciones impresas; las otras tres se leen en la salida esperada y en el código de las herramientas.
  • Ejecución de CI 37070292367, para el commit 92e8d13: verde en los tres sistemas, 3 min 51 s en Linux, 4 min 23 s en macOS, 9 min 3 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #795, para las filas 123 a 127.

2026-10-03 — Lección 22: los acordes parecidos

Sección titulada «2026-10-03 — Lección 22: los acordes parecidos»
  • La petición, el 2026-10-03: IcvNeighborsSkill para la lección 22, la skill de acordes parecidos del chatbot, con la skill en espera para ga_icv_neighbors.
  • El programa llama a ExecuteAsync y lee la cabecera de la respuesta, su línea de vector y sus filas; la tabla de los acordes llama a TryBuildPcSet, que es privado, mediante reflexión.
  • Las notas de cada acorde de esa tabla son las del curso, las de un manual para cada cifrado, escritas con sostenidos como las imprime GA.
  • Las pistas de enrutamiento proceden de DefaultRoutingHintProvider.GetDeltas; el propio enrutador no se ejecuta, porque necesita los embeddings.
  • Las soluciones se leen en la salida esperada y en el código de la skill; la segunda es aritmética sobre dos vectores impresos.
  • Ejecución de CI 37143011796, para el commit 627a3ca: verde en los tres sistemas, 3 min 56 s en Linux, 3 min 59 s en macOS, 8 min 54 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #798, para las filas 128 a 131.

2026-10-03 — Lección 23: la distancia y el camino armónicos

Sección titulada «2026-10-03 — Lección 23: la distancia y el camino armónicos»
  • La petición, el 2026-10-03: GrothendieckDeltaSkill e IcvShortestPathSkill para la lección 23, las dos skills, vecinas de la de la lección 22, que reciben una pareja de acordes.
  • El programa hace cada pregunta una sola vez y guarda la respuesta, ya que una pregunta que no encuentra ningún camino le cuesta a la skill de camino una búsqueda de cientos de conjuntos.
  • El recuento de conjuntos expandidos antes de “No path” procede de la propia búsqueda del curso, que sigue la regla de FindShortestPath; la skill no lo imprime, y el programa no cronometra las skills.
  • Una segunda lectura del código fijado por otro modelo, la CLI auggie de Augment con gpt-6-sol y herramientas de solo lectura, estimó las mismas 168 y 462 expansiones y leyó el recuento de pasos de la misma manera.
  • Las soluciones se leen en la salida esperada y en el código de las skills.
  • Ejecución de CI 37147833299, para el commit 12b105a: verde en los tres sistemas, 4 min 14 s en Linux, 6 min 9 s en macOS, 12 min 28 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #802, para las filas 132 a 135.

2026-10-03 — Lección 24: las clases de conjuntos y el analizador Grothendieck

Sección titulada «2026-10-03 — Lección 24: las clases de conjuntos y el analizador Grothendieck»
  • La petición, el 2026-10-03: SetTheoryEquivalenceSkill y GrothendieckParseSkill para la lección 24, dos de las skills del chatbot a las que ninguna lección había preguntado todavía.
  • El programa compara cada veredicto con sus propias pruebas de la transposición y de la inversión, sobre máscaras de 12 bits, para cada pareja ordenada de conjuntos de tres y de cuatro notas.
  • Las formas primas se comparan con la propia tabla de GA del catálogo de Forte, no con el libro de Forte.
  • Una segunda lectura del código fijado por otro modelo, la CLI auggie de Augment con gpt-6-sol y herramientas de solo lectura, leyó de la misma manera el patrón de la relación, las formas ws1 del analizador, el agrupamiento de la línea 426, el orden que hace de P(C) una aplicación de funtor y las cualidades de acorde.
  • Las soluciones se leen en la salida esperada y en el código.
  • Ejecución de CI 37166154652, para el commit 922ae7e: verde en los tres sistemas, 7 min 39 s en Linux, 6 min 7 s en macOS, 14 min 9 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #806, para las filas 136 a 140.

2026-10-04 — Lección 25: lo que llega a la skill de transposición

Sección titulada «2026-10-04 — Lección 25: lo que llega a la skill de transposición»
  • La petición, el 2026-10-04: TransposeSkill para la lección 25. La lección 10 había llamado a su closure, así que esta lección pregunta qué preguntas llegan a ella.
  • GaMain construye y arranca ahora el host del chatbot de main: fetch-ga.sh añade al segundo clon los proyectos del host y skills/, y MainChatHost configura el host como lo hace ChatHost, con el índice de la lección 3 construido con el código de main.
  • Las formulaciones son los 13 prompts de ejemplo de la skill, una formulación de su SKILL.md, los cuatro prompts del corpus de GA y ocho del propio curso.
  • Llamada directamente, TransposeSkill responde con el mensaje de error de SkillMdDrivenSkill, y su evidencia presenta la respuesta como producida solo por el LLM: el comportamiento de las filas 42 y 43, comunicado en la issue #764.
  • Las soluciones se leen en la salida esperada y en el código.
  • Comunicado upstream en la issue de GA #809, para las filas 141 a 144.
  • Ejecución de CI 37182332132, para el commit 33daa24: verde en los tres sistemas, 8 min 22 s en Linux, 8 min 7 s en macOS, 24 min 49 s en Windows, con el clon y la compilación incluidos.

2026-10-04 — Lección 26: el catálogo de modos

Sección titulada «2026-10-04 — Lección 26: el catálogo de modos»
  • La petición, el 2026-10-04: ModesSkill para la lección 26. La lección 8 había visto sus fórmulas en dos escalas, comunicadas en la #765.
  • La skill no necesita ni modelo ni host: el programa la construye con un logger nulo, la llama directamente y lee el catálogo con el propio GetTonalModalFamilies de la skill.
  • El primer modo de un manual para cada familia es el del curso, en Lesson26.cs; cada uno de los demás modos se compara con el primer modo de su propia familia.
  • Las soluciones se leen en la salida esperada y en el código.
  • Ejecución de CI 37215721850, para el commit 16dbeff: verde en los tres sistemas, 6 min 4 s en Linux, 8 min 18 s en macOS, 25 min 3 s en Windows, con el clon y la compilación incluidos.
  • Comunicado upstream en la issue de GA #813, para las filas 145, 146, 148 y 149; los recuentos de la fila 147 se añadieron a la #765 en un comentario.

2026-10-04 — Lección 27: las notas que suenan fuera

Sección titulada «2026-10-04 — Lección 27: las notas que suenan fuera»
  • La petición, el 2026-10-04: OutsideNotesSkill para la lección 27.
  • La skill no necesita ni modelo ni host: el programa la construye con un logger nulo, la llama directamente y llama a su Classify privado por reflexión para la regla.
  • Las escalas de acorde habituales de los cinco acordes de séptima son las del curso, en Lesson27.cs.
  • Las soluciones se leen en la salida esperada y en el código.
  • Comunicado upstream en la issue de GA #814, para las filas 150 a 154.
  • Ejecución de CI 37221169417, para el commit 49e7e1a: verde en los tres sistemas, 8 min 3 s en Linux, 10 min 6 s en macOS, 23 min 49 s en Windows, con el clon y la compilación incluidos.
  • Si el chatbot desplegado envía cada prompt de la lección 5 a ImprovisationSkill; el tracer del 2026-09-28 lo vio hacerlo con Am F C G.
  • Los nombres de Berklee de la lección 5, mixolidio ♭13 para V7/II y mixolidio ♭9 ♭13 para una dominante en menor, y F dórico para un iv prestado, contra Nettles y Graf, The Chord Scale Theory & Jazz Harmony, que el curso no ha leído.
  • Las soluciones de los ejercicios 2 y 3 de la lección 5, no compiladas contra GA.
  • Si el chatbot público ejecuta una compilación que incluye la #749, y qué responde un modelo a las filas 5, 6, 13 y 14 de la lección 7.
  • La solución del ejercicio 4 de la lección 7, no compilada contra GA.
  • Si las ejecuciones diarias del corpus en GA, que tienen un endpoint de Ollama y ninguna clave de Anthropic, puntúan los siete prompts diatónicos como seis fallos y un aprobado; las instantáneas del 2026-09-25 al 2026-09-29 están marcadas como degradadas y no enumeran los fallos por prompt.
  • La solución del ejercicio 4 de la lección 8, una fórmula derivada de la letra de cada nota, no compilada contra GA.
  • Qué sirve el chatbot para los ocho prompts de ejemplo que IntervalSkill no sabe leer, lo que necesita el enrutador de intenciones y su modelo de embeddings.
  • Las soluciones de los ejercicios 1 y 3 de la lección 9, no compiladas contra GA, y lo que imprimiría el cambio del ejercicio 2 para un unísono disminuido.
  • Qué envía y qué responde el modelo a las preguntas de la lección 10, y si vuelve a escribir la respuesta de una closure en contra de su SKILL.md.
  • Las soluciones de los ejercicios 1 y 2 de la lección 10, no compiladas contra GA.
  • Qué dice el modelo a las preguntas de la lección 11 cuando cuatro tonalidades están “all tied” (todas empatadas), o cuando se ha perdido un sostenido.
  • Qué responde Identify para las 16 preguntas de la lección 11 una vez leídos sus sostenidos, como en la solución del ejercicio 1.
  • Qué sugiere el modelo a partir de las listas de la lección 12, y si sigue la regla del V7 del prompt o la lista; qué hace un modelo con la regla del SKILL.md de progression-mood para elegir la luminosidad.
  • Las soluciones de los ejercicios de la lección 12, no compiladas contra GA.
  • Qué escribe un modelo a partir de las tres líneas de domain.analyzeProgression, y si llama a la closure a través de ga_dsl_eval para una pregunta que ninguna skill recoge.
  • Las soluciones de los ejercicios de la lección 13, no compiladas contra GA.
  • Qué intent elige el enrutador semántico para cada prompt de ejemplo de la lección 14, y qué escribe un modelo a partir de ga_chord_substitutions y ga_chord_compare.
  • Las soluciones de los ejercicios de la lección 14, no compiladas contra GA.
  • Qué intent elige el enrutador semántico para las preguntas de la lección 15, entre ellas “I am learning Cmaj7”, y qué escribe un modelo a partir de ga_chord_info.
  • Qué voicings devuelve el índice de producción para los prompts de la lección 16, qué intención elige el enrutador para ellos y qué lee un modelo en “voicings for am”.
  • Qué intención elige el enrutador, con embeddings, para las preguntas de cejilla y de afinaciones de la lección 17, entre ellas las formulaciones que las skills leen mal.
  • Qué intención elige el enrutador, con embeddings, para las preguntas de conducción de voces de la lección 18, entre ellas los dos prompts de ejemplo que dicen “voicing”.
  • Qué candidatos y qué pares devuelve ga_voice_leading_pair sobre el índice de producción, con más voicings que el corpus de la lección 3.
  • Qué plantillas y qué fundamentales pasan en la práctica los agentes a ga_generate_progression: el curso prueba las fundamentales que podría escribir un guitarrista, no llamadas registradas.
  • Cómo responde ga_search_voicings sobre el índice de producción de GA: el índice del curso es el de la lección 3, y allí la advertencia de la skill sobre los tags de estilo puede seguir siendo válida.
  • Qué preguntas envía el enrutador a IcvNeighborsSkill con los embeddings, y con qué frecuencia los usuarios las formulan como sus prompts de ejemplo y no como sus expresiones.
  • Cuánto tarda la skill de camino en el chatbot desplegado con dos acordes de tamaños distintos: el curso cuenta los conjuntos que expande la búsqueda, no el tiempo.
  • Si el enrutador del chatbot desplegado envía una pregunta sobre equivalencia de conjuntos a la skill de conjuntos o a la skill de transposición, que refuerzan dos de sus prompts de ejemplo: el curso no ejecuta el enrutador.
  • Qué skill elige el enrutador del chatbot desplegado, con sus embeddings, para las transposiciones que no reciben la pista de transposición o que reciben la de otra intención: el curso no calcula los embeddings.
  • Si el enrutador del chatbot desplegado envía “Tell me about Hijaz” o “List unnamed modal families” a ModesSkill: el curso no ejecuta el enrutador.
  • Si el enrutador del chatbot desplegado envía “why does F sound outside over a minor chord” o “what is F over G7” a OutsideNotesSkill: el curso no ejecuta el enrutador.
  • Cómo muestra un evento de error la página de GaChatbot.Api en un navegador: la lección 6 ejecuta una versión portada a C# de su lector, no la página. Lo mismo vale para la solución del ejercicio 3 de la lección 6.
  • ¿Qué regla de inferencia de la tonalidad debería seguir la skill de improvisación de GA? #744 la deja abierta: el recuento de notas del acorde fuera de cada escala mayor, que usa la lección 5, o los servicios de identificación de tonalidad que ya existen en GA.
  • ¿Deberían los flujos de GA marcar un error como tal, con un campo event: error o un type en el JSON, y terminar con [DONE] o con su propio evento final? En a826864, cada cliente tiene que deducirlo de la forma del JSON.
  • ¿Debería la guarda de GA rechazar también los nombres en minúsculas y las cualidades desconocidas, a costa de los falsos positivos del ejercicio 3 de la lección 7, o debería una petición que mezcla acordes válidos y no válidos recibir una respuesta que nombre los no válidos?
  • ¿Debería el corpus comprobar las notas de un acorde o de una escala como un conjunto, con un invariante estructurado, en lugar de como cadenas? La lectura más estricta de las mismas cadenas en la lección 8 sigue aceptando 69 respuestas ajenas.
  • ¿Deberían ejecutarse los prompts de ejemplo de cada skill como una prueba contra la propia skill? Las tres skills de la lección 9 no saben responder a 11 de sus 49.
  • ¿Deberían las closures de GA deletrear las notas con el Key del dominio, como hace ScaleInfoSkill, en lugar de con arrays de doce nombres? ¿Y debería transposeChord recibir un intervalo o una tonalidad de destino en lugar de un número de semitonos?
  • ¿Debería la herramienta de tonalidad pasar al modelo la clasificación de Identify con su puntuación, en lugar de las tonalidades agrupadas por recuento? ¿Y deberían distinguirse las tonalidades con las mismas clases de altura por la grafía de la pregunta?
  • ¿Debería la lista de una tonalidad menor contener el V y el V7 de la menor armónica, para que el catálogo de cadencias de la skill de continuación se pueda construir con ella? ¿Y debería generarse el texto fijo de una skill a partir de su SKILL.md, para que los dos no puedan divergir?
  • ¿Debería la identificación de tonalidades de GA pesar el acorde con que una progresión empieza y termina antes que el recuento de acordes diatónicos, y deberían sus números romanos marcar una fundamental cromática, bVI, bVII o el vii° de una tonalidad menor, en lugar de ??
  • ¿Debería la skill de sustitución de GA ordenar los sustitutos de un acorde por notas comunes y por función, como hace domain.chordSubstitutions dentro de una tonalidad, y dejar la distancia ICV para las preguntas de clases de conjuntos? ¿Y debería GrothendieckDelta devolver 0 para vectores iguales, y dejar que los llamadores que necesiten distinguir dos conjuntos comparen los conjuntos mismos?
  • ¿Deberían las skills de acordes de GA compartir un único lector de cifrados, construido sobre ChordVocabulary, que lea un cifrado entero o lo rechace? En a826864, las skills de improvisación, de sustitución y de información de acordes y ga_chord_info tienen cada una su propia expresión, y cada una lee una parte de lo que leen las demás.
  • ¿Debería el índice de voicings de GA guardar un nombre que el filtro pueda encontrar, uno por conjunto de notas y fundamental, o debería el filtro comparar clases de altura, como hace la comprobación del curso? ¿Y debería ChordVoicingsSkill decir en su respuesta qué filtros ha descartado el índice, o leer las técnicas en el diagrama, como se hace con los filtros de comodidad?
  • ¿Deberían las skills de cejilla y de afinaciones de GA leer una tonalidad o una nota con un único parser que tome la alteración junto con la letra, en lugar de cada una con su propia expresión? ¿Debería CapoSkill escribir sus respuestas como lo hacen las armaduras y responder dónde poner la cejilla? ¿Y deberían las dos skills aceptar en CanHandle las preguntas que saben leer, para que el respaldo sin conexión llegue a ellas?
  • ¿Debería la VoiceLeadingSkill de GA elegir la duplicación además del emparejamiento, o decir que duplica la fundamental, en lugar de afirmar que cualquier otro voicing mueve más? ¿Debería leer los cifrados con un único parser que acepte M7, Δ, ø y una alteración final, escribir las notas a partir de la fundamental del acorde, y aceptar en CanHandle las preguntas que sabe leer?
  • ¿Debería la herramienta ga_voice_leading_pair de GA comprobar que cada voicing toca el acorde pedido, emparejar las notas más cercanas cuando el número de notas difiere y devolver sus diagramas en el orden de los diagramas de acordes? ¿Debería reescribirse la skill de conducción de voces en espera para la herramienta que existe, o darse a la herramienta el contrato que espera el borrador?
  • ¿Debería la herramienta ga_generate_progression de GA escribir a partir de la armadura con siete letras, recibir una tonalidad con su modo, acotar length y responder con una progresión de voicings en lugar de sugerir que se enlacen pares? ¿Debería reescribirse la skill de progresiones en espera para las plantillas que tiene la herramienta?
  • ¿Debería la herramienta ga_search_voicings de GA codificar el modo o dejar de prometerlo, tratar un modo a secas como una consulta vacía, filtrar por un tag en lugar de añadir un bit y comparar palabras enteras? ¿Deberían reescribirse las puntuaciones, las advertencias y los ejemplos de la skill voicing-search a partir de la salida de la herramienta, y la skill voicing-search en espera para ga_search_voicings?
  • ¿Debería la skill IcvNeighborsSkill de GA leer las palabras de sus propios prompts de ejemplo, construir sus acordes con el parser de acordes de GA en lugar de una tabla que recurre a una tríada mayor, listar cada clase de conjuntos una sola vez con un nombre y ordenar sus vecinos por algo que los distinga entre sí? ¿Debería reescribirse la skill icv-neighbors en espera para ga_icv_neighbors tal como es?
  • ¿Debería la skill GrothendieckDeltaSkill de GA dar un delta nulo como cero, GrothendieckDelta.Explain perder su flecha corrupta, e IcvShortestPathSkill rechazar los acordes de tamaños distintos antes de buscar, contar movimientos en lugar de conjuntos y nombrar los conjuntos por los que pasa? ¿Deberían las dos skills leer las palabras de sus propios prompts de ejemplo y compartir un único parser de acordes?
  • ¿Debería la SetTheoryEquivalenceSkill de GA leer la relación en la formulación de sus propios prompts de ejemplo, rechazar un conjunto que no puede leer entero y decir “via either operation” solo de los conjuntos simétricos por inversión? ¿Debería GrothendieckOperationsParser abandonar el ws1 que sigue a str, probar sus alternativas con attempt y leer los cifrados de acordes habituales, y debería GrothendieckParseSkill decir algo de los acordes que analiza?
  • ¿Debería GA conservar una pista de transposición que no reconoce 3 de los propios prompts de ejemplo de la skill y se activa con la teoría de conjuntos, los funtores y “move from X to Y”? Sin embeddings, ¿debería una transposición recibir un mensaje de que no se puede responder en lugar del agente de voicings, que gana por defecto en las palabras clave del enrutador de agentes?
  • ¿Debería GA comprobar Modes.yaml modo por modo frente a las escalas que nombra, poner sus nombres entre comillas, dar a cada modo un solo nombre, y calcular una fórmula por grado para siete notas y por letra en los demás casos? ¿Debería ModesSkill decir que no reconoce una pregunta en lugar de listar los modos de la escala mayor?
  • ¿Debería OutsideNotesSkill clasificar una nota frente a las escalas habituales del acorde en lugar de solo frente a sus notas, dar a la b9 y la b13 de un acorde de dominante un titular de tensión, quitar la 11 de los acordes de trecena, leer el acorde con el propio vocabulario de NormalizeQuality y escribir las notas del acorde a partir de sus letras?