Diario
Secciones
Ajustes de lectura
Ninguna voz para este idioma en este navegador.
Más voces
Código y términos técnicos en inglés
Desactivado: la voz de la página lo lee todo, sin pausa entre dos voces.
Ninguna voz para este idioma en este navegador.
Más voces
Más voces: Microsoft Edge ofrece voces naturales en línea, y Windows (Configuración › Hora e idioma › Voz), macOS y Android instalan otras.
Progreso
Sección titulada «Progreso»- Código del curso: aplicaciones basadas en archivos, fragmentos rechazados y soluciones de ejercicios, comparados con su salida esperada por
check.sh - CI en Linux, Windows y macOS
- Lección 1: instalar .NET y ejecutar tu primer programa
- Lección 2: variables, tipos y entrada
- Lección 3: condiciones y bucles
- Lección 4: métodos, arrays y listas
- Lección 5: clases y objetos
- Lección 6: records, structs y enums
- Lección 7: interfaces y herencia
- Lección 8: excepciones y seguridad frente a null
- Lección 9: colecciones y LINQ
- Lección 10: archivos y texto
- Lección 11: pruebas unitarias
- Lección 12: un pequeño proyecto
| Esperado | Qué ocurre | Dónde | Medición | Estado |
|---|---|---|---|---|
Mostrar una plantilla de acorde de GA muestra su Name, como pretende el ToString() => Name del record base |
Los records derivados TonalModal y Analytical sintetizan cada uno su propio ToString, que enumera todas las propiedades: TonalModal { Name = Major 7th, PitchClassSet = 0 4 7 E, … }. Un record derivado solo conserva el ToString de la base si es sealed (records, formato integrado) |
ChordTemplate.cs:84; un llamador, ContextualChordsController.cs:301, pasa template.ToString() a un servicio que lo registra (FretboardServices.cs:536) |
Una sonda de consola que referencia GA.Domain.Core en el commit 5c3a52a, SDK 10.0.112: el volcado para ToString() y $"{template}" en los dos records; una réplica con sealed mostró maj7 (entrada) |
Reproducido; corrección propuesta en la PR 816 de GA, aún sin fusionar (2026-10-04); sigue abierta el 2026-10-06, con el defecto sin cambios en main 40d33747 (2026-10-06) |
Las advertencias de nulabilidad aparecen en el código de GA: GA.Domain.Core y GA.Core activan <Nullable>enable</Nullable> |
Directory.Build.props pone 15 advertencias de nulabilidad (CS8600, CS8602, CS8618, CS8625…) en NoWarn «to achieve a clean baseline», y Directory.Build.targets las repite. La base está limpia sin ellas: las listas solo ocultan los errores nuevos |
Directory.Build.props:21, Directory.Build.targets:7 | Un archivo con siete errores de nulabilidad, añadido a GA.Domain.Core en el commit 5c3a52a: 0 advertencias con la configuración de GA, 7 sin las dos listas; sin ese archivo, 0 en GA.Domain.Core y GA.Core (entrada, ga-probes) |
Reproducido; no comunicado a GA |
Los servicios de conocimiento musical de GA cargan ChordProgressions.yaml, GuitarTechniques.yaml y SpecializedTunings.yaml |
Ninguno de los tres se deserializa: una cadena donde la clase tiene una List<string>, cadenas donde espera objetos, una línea que no es YAML válido. Cada cargador captura la excepción, muestra Error loading … y sigue con un solo elemento por defecto |
ChordProgressions.yaml:93 frente a ChordProgressionsConfigLoader.cs:16; GuitarTechniques.yaml:23 frente a GuitarTechniquesConfigLoader.cs:20; SpecializedTunings.yaml:95; el catch de ChordProgressionsConfigLoader.cs:137, y el mismo en los otros dos cargadores |
artists.cs en el commit 5c3a52a, SDK 10.0.112: 17 acordes emblemáticos, luego 1 elemento para cada uno de los tres archivos, y 16 artistas distintos (entrada). Las tres líneas siguen igual en el main de GA, ae196bf |
Reproducido; comunicado en la issue 797 de GA el 2026-10-03; corrección propuesta en la PR 808 de GA, aún sin fusionar (2026-10-04) |
GetArtistBreakdown devuelve los 20 artistas con más entradas, de más a menos, como dice su comentario // Top 20 artists |
Take(20) corta la lista alfabética antes de ordenar por número de entradas, y el resultado ordenado va a un Dictionary, cuyo orden la documentación deja sin definir |
MusicalKnowledgeService.cs:226 y :235; GetAllArtists ordena por nombre en :125 |
La misma sonda: con 16 artistas no queda ninguno fuera, y el diccionario sale por número de entradas, los empates en orden alfabético. El corte solo actúa con más de 20 artistas, una vez corregida la fila anterior | Latente, leído en el código; corrección propuesta en la PR 811 de GA, aún sin fusionar (2026-10-04) |
PitchClassSet.ScaleVideoUrl da la URL del vídeo de una escala listada en scale_video_urls.json, que contiene 1490 |
El archivo no está incrustado en la biblioteca ni se copia junto a ella: GA.Domain.Core.csproj no tiene ninguna regla para él. El nombre de recurso GA.Domain.Core.Scales.Data.scale_video_urls.json y la ruta de repliegue Scales/Data/ no aciertan con su carpeta, Theory/Tonal/Scales/Data/, y LoadVideoUrls devuelve un diccionario vacío sin mensaje |
ScaleVideoUrlById.cs:30, :36-38; PitchClassSet.cs:350, ScaleMetadataRegistry.cs:36 | files.cs en el commit 5c3a52a, SDK 10.0.112: 0 recursos en GA.Domain.Core, ningún archivo de repliegue, 0 escalas con URL (entrada). El nombre de recurso y la ruta de repliegue siguen igual en el main de GA el 2026-10-03 |
Reproducido; corrección propuesta en la PR 817 de GA, aún sin fusionar (2026-10-04); sigue abierta el 2026-10-06, con el defecto sin cambios en main 40d33747 (2026-10-06) |
IconicChordsConfigLoader.ReloadConfiguration() vuelve a leer IconicChords.yaml tras un cambio |
Asigna el campo static readonly _configuration con FieldInfo.SetValue, que lanza FieldAccessException desde .NET Core 3.0 (cambio importante) |
IconicChordsConfigLoader.cs:107-111, :12 | files.cs: FieldAccessException: Cannot set initonly static field '_configuration' after type 'GA.Domain.Services.IconicChordsConfigLoader' is initialized. (entrada). Sigue igual en el main de GA el 2026-10-03 |
Reproducido; corrección propuesta en la PR 811 de GA, aún sin fusionar (2026-10-04) |
Un IconicChords.yaml que falta se comunica |
FindYamlFile prueba cuatro rutas, dos de ellas relativas al directorio actual. Cuando no existe ninguna, un catch vacío se traga su FileNotFoundException, y el cargador devuelve un solo acorde por defecto, sin mensaje |
IconicChordsConfigLoader.cs:94-104, :25-28 | files.cs, tras borrar los archivos YAML junto a él: 1 acorde, «C Major Triad», lanzado desde ga-probes; 17 desde la raíz del código de GA, por <directorio actual>/Common/GA.Business.Config; nada impreso (entrada) |
Reproducido; una decisión de diseño, no comunicada a GA |
GaCLI lee el appsettings.yaml que su compilación copia junto al programa |
SetBasePath(Directory.GetCurrentDirectory()) lo lee en el directorio actual, como archivo opcional: lanzado desde otra carpeta, GaCLI funcionaría sin su configuración, en silencio |
Program.cs:17-19, GaCLI.csproj:59-61 | Compilado en 5c3a52a y lanzado desde otra carpeta: imprime su lista de comandos. Las dos secciones del archivo, EmbeddingService y LmStudio, se leen en un solo sitio, sync-mongodb, en una configuración que ningún servicio resuelve (entrada) |
Verificado: el archivo no cambia nada en este commit; no comunicado a GA |
| Cada fila del CSV de naturalidad de GA tiene los 6 valores de su encabezado | :F2 y {deltaStretch} usan la cultura de la máquina: con fr-FR, 2.50 se escribe 2,50, y una fila recibe 8 valores; el lector corta por las , |
NaturalnessTrainingDataGenerator.cs:160, :21; TrainNaturalnessModelCommand.cs:51-54 | l10_culture.cs con la cadena de formato de GA: 6 valores con en-CA, 8 con fr-FR. El generador de GA no se ejecutó: necesita un corpus de tablaturas (entrada) |
Reproducido con la cadena de formato; corrección propuesta en la PR 811 de GA, aún sin fusionar (2026-10-04) |
| El comando de GA imprime el número de filas de datos que escribió | csvContent.Split('\n').Length - 1 quita el elemento vacío tras el último salto de línea pero cuenta el encabezado: una fila de más |
GenerateNaturalnessDataCommand.cs:38 | La aritmética de Split('\n'), medida por l10_line_endings.cs: 3 líneas dan 4 elementos. El comando de GA no se ejecutó |
Latente, leído en el código; corrección propuesta en la PR 811 de GA, aún sin fusionar (2026-10-04) |
| Una prueba de los servicios de conocimiento musical de GA falla cuando sus archivos YAML no se cargan | Tres de las ocho pruebas se omiten con [Ignore("Configuration files not loaded in test environment")]. De las cinco restantes, tres solo comprueban que un número es mayor que cero o que una lista no está vacía, lo que cumple el único elemento por defecto de cada cargador que falla |
MusicalKnowledgeServiceTests.cs:108-110, :141-143, :207-209; :16, :31-33, :179-183 | Sonda knowledge-tests, archivo de pruebas de GA compilado sin cambios, SDK 10.0.112: 5 superadas, 3 omitidas, 0 fallidas, mientras tres de los cuatro archivos YAML no se cargan. La búsqueda de «jazz» pasó con 1 resultado, la progresión de acordes por defecto (entrada). Sigue igual en el main de GA, 0843879 |
Reproducido; relacionado con la issue 797 de GA; corrección propuesta en la PR 808 de GA, aún sin fusionar (2026-10-04) |
El [SetUpFixture] TestEnvironment de GA se ejecuta antes de las pruebas de configuración: define GA_TEST_MODE=1 y lleva el directorio actual a la raíz del repositorio |
Está solo en el namespace GA.Business.Core.Tests.TestBootstrap, y NUnit solo ejecuta un setup fixture para las pruebas de su namespace y de los namespaces que contiene (NUnit): nunca se ejecuta |
TestEnvironment.cs:1, :7-14 | Sonda knowledge-tests: una prueba en GA.Business.Core.Tests.Configuration imprimió GA_TEST_MODE: (not set) y Current directory is the test's bin folder: True (entrada). En main, 0843879, el namespace sigue conteniendo solo este archivo |
Reproducido; corrección propuesta en la PR 816 de GA, aún sin fusionar (2026-10-04); sigue abierta el 2026-10-06, con el defecto sin cambios en main 40d33747 (2026-10-06) |
| Los archivos de prueba de GA.Business.Core.Tests se compilan y se ejecutan | El archivo de proyecto quita 35 archivos de la compilación, «Exclude test files with missing service implementations»: 5 de los nombres no corresponden a ningún archivo, y los otros 30 contienen 333 líneas que empiezan por [Test] o [TestCase] |
GA.Business.Core.Tests.csproj:39-75 | git ls-tree y un recuento en el commit 5c3a52a; el proyecto tiene 136 archivos .cs. Las 35 entradas siguen igual en main, 0843879 |
Contado en el código; no comunicado a GA |
| La CI de GA ejecuta las pruebas de cada proyecto de pruebas | Sus jobs compilan y prueban AllProjects.slnx, que lista 75 de los 111 archivos de proyecto. Seis proyectos de pruebas quedan fuera y ningún workflow los nombra; sus archivos tienen 102 líneas con un atributo de prueba. Uno de ellos, GA.Business.Core.Graphiti.Tests, no compila: usa GA.Business.Graphiti y no referencia ningún proyecto |
AllProjects.slnx, ci.yml:43, :103, GA.Business.Core.Graphiti.Tests.csproj | lesson12_counts.py en 5c3a52a; la compilación de las pruebas Graphiti se detiene con 5 errores, CS0234 en sus dos líneas using GA.Business.Graphiti... y CS0246 |
Contado y compilado; corrección propuesta en la PR 812 de GA, aún sin fusionar (2026-10-04) |
Los elementos PackageReference Update del Directory.Build.props de GA alinean las versiones de los paquetes, bajo «Centralized package version alignment and vulnerability remediation» |
Directory.Build.props se importa antes que los elementos propios del proyecto, así que Update no encuentra nada que actualizar. 23 declaraciones de los seis paquetes afectados mantienen otra versión, 13 de ellas en proyectos de la solución |
Directory.Build.props:32-58 | Restauración de GA.Business.Core.Graphiti.Tests: Microsoft.Extensions.Http 9.0.10, como pide su archivo de proyecto. Con la misma línea Update en Directory.Build.targets: 10.0.0 |
Reproducido, con un control; corrección propuesta en la PR 812 de GA, aún sin fusionar (2026-10-04) |
| El job de análisis de seguridad de GA informa de los paquetes vulnerables | Directory.Build.props y Directory.Build.targets desactivan NU1902, NU1903 y NU1904 para todos los proyectos. El paso de análisis tiene continue-on-error: true, y dotnet list package --vulnerable termina con el código 0 cuando lista un paquete vulnerable: el job no puede fallar |
Directory.Build.props:16-17, Directory.Build.targets:5-11, ci.yml:398-401 | Código de salida 0 con un paquete vulnerable, medido en un proyecto de prueba (tabla de experimentos); el análisis de GA no se ejecutó | Leído en el código; corrección propuesta en la PR 812 de GA, aún sin fusionar (2026-10-04) |
| El workflow Quality Check de GA ejecuta un benchmark de calidad de GaCLI | benchmark-quality lanza NotImplementedException, como 12 de los 28 comandos de GaCLI, incluido analyze-chord, el primer ejemplo de su ayuda. El paso tiene continue-on-error: true |
quality_check.yml:26-29, Program.cs:179-182 | Compilación local en 5c3a52a: NotImplementedException no controlada. Ejecución 37167745677 de GA, en un commit posterior cuyo workflow y Program.cs son los mismos archivos: código de salida 134, ejecución terminada con éxito |
Reproducido; no comunicado a GA |
| Un comando de GaCLI que falla se lo dice a quien lo llama | sync-mongodb captura su excepción, imprime Error during sync: Unable to resolve service for type 'GA.Data.MongoDB.Services.MusicalObjectsService' while attempting to activate 'GaCLI.Commands.Runner'. y termina con el código 0: Runner necesita un servicio que el comando no registra |
Program.cs:356, :364-368 | Lanzado desde bin/Debug/net10.0 y desde otra carpeta: el mismo mensaje, código de salida 0 |
Reproducido; corrección propuesta en la PR 811 de GA, aún sin fusionar (2026-10-04) |
Experimentos
Sección titulada «Experimentos»| Pregunta | Hipótesis, escrita antes de medir | Resultado | Veredicto | Entrada y código |
|---|---|---|---|---|
¿Cuántas advertencias de nulabilidad oculta el NoWarn de GA en GA.Domain.Core? |
Más de 100 | 0 en GA.Domain.Core y GA.Core sin las dos listas; un archivo de prueba con siete errores recibe 7 advertencias sin las listas, 0 con ellas | Refutada | entrada, ZzNullableCanary.cs |
¿Qué hace el Fret de GA con 50? |
new Fret(50), Fret.FromValue(50) y Fret f = 50; lanzan una ArgumentOutOfRangeException; Fret.TryCreate(50) devuelve el fallo Fret number must be between -1 (muted) and 36, got 50 |
Las tres lanzan la excepción, para 50 y para -2; el mensaje de TryCreate coincide palabra por palabra |
Confirmada | entrada, probe.cs, results.txt |
¿Compila sin aviso new PositionLocation(5, 3), con la cuerda y el traste intercambiados como simples números? |
Los dos órdenes compilan sin advertencia; la llamada intercambiada construye la cuerda 5, traste 3 | 0 advertencias en las líneas de la sonda; muestra 5,3 |
Confirmada | entrada, probe.cs |
¿En qué orden lee un foreach un diccionario después de un Remove y un Add? |
Claves C, D, E, G, A, luego Remove("D") y Add("F#"): F# ocupa el lugar de D, C F# E G A, no el último lugar |
C F# E G A |
Confirmada | entrada, l09_dictionary_order.cs |
¿Modificar un diccionario dentro de su propio foreach lanza una excepción, como con una lista? |
Remove no lanza nada en .NET 10; añadir una clave lanza una excepción; List<T>.Remove lanza una InvalidOperationException |
Remove deja C E sin excepción; añadir B, y el Remove de la lista, lanzan ambos Collection was modified; enumeration operation may not execute. |
Confirmada | entrada, l09_modify_dictionary.cs, l09_modify_while_looping.cs |
¿Qué artistas deja fuera el GetArtistBreakdown de GA con Take(20)? |
Más de 20 artistas distintos: se quedan los 20 primeros del alfabeto, y al menos un artista excluido tiene más entradas que el menor número conservado; el diccionario sale por número de entradas descendente | 16 artistas, ninguno fuera, porque tres de los cuatro archivos YAML no se cargan (tabla QA). El diccionario sí sale por número de entradas, los empates en orden alfabético | Refutada | entrada, artists.cs, artists-results.txt |
En un archivo de 3 líneas que termina con un salto de línea, ¿qué devuelven ReadAllText(path).Split('\n') y ReadAllLines, con LF y con CRLF? |
Split da 4 elementos, el último vacío, y con CRLF los tres primeros terminan en \r; ReadAllLines da 3 líneas sin \r en los dos casos |
Longitudes LF 2 2 2 0 y 2 2 2, CRLF 3 3 3 0 y 2 2 2; con CRLF, split[0] == "E2" es False |
Confirmada | entrada, l10_line_endings.cs |
¿Cuántos bytes escriben WriteAllText(path, "Ré") y WriteAllText(path, "Ré", Encoding.UTF8)? |
3 sin codificación, 6 con Encoding.UTF8, empezando por EF BB BF; ReadAllText devuelve Ré en los dos casos |
52C3A9, luego EFBBBF52C3A9; Ré, 2 caracteres |
Confirmada | entrada, l10_bom.cs |
¿Depende File.Exists("data/ga-projects.csv") de la carpeta desde la que arranca dotnet run? |
True desde code/csharp-beginner, False desde la raíz del repositorio; una ruta construida a partir de EntryPointFileDirectoryPath existe desde las dos |
Como se predijo, y False también desde examples; check.sh ejecuta ahora los dos casos en tres sistemas. EntryPointFileDirectoryPath se conocía antes de la hipótesis |
Confirmada | entrada, l10_where.cs |
Con los archivos YAML borrados junto a la sonda, ¿cuántos acordes emblemáticos carga GA, lanzado desde la raíz de GA y desde ga-probes? |
17 desde la raíz de GA, por la tercera ruta; 1 acorde por defecto desde ga-probes, sin excepción ni mensaje |
17, «Hendrix Chord» primero, y 1, «C Major Triad»; nada impreso | Confirmada | entrada, files.cs, files-without-yaml.txt, files-from-ga-root.txt |
¿Qué hace IconicChordsConfigLoader.ReloadConfiguration() de GA en .NET 10? |
Lanza FieldAccessException: SetValue sobre un campo static readonly se rechaza desde .NET Core 3.0 |
FieldAccessException: Cannot set initonly static field '_configuration' … |
Confirmada | entrada, files.cs, files-results.txt |
¿Cuántos valores separados por comas tiene una fila del CSV de naturalidad de GA con en-CA y con fr-FR? |
6 con en-CA, 1,2.50,2.50,2,1,4; 8 con fr-FR, 1,2,50,2,50,2,1,4. Conocido antes de la hipótesis: $"{2.5}" da 2,5 con fr-FR |
Exactamente esas dos filas | Confirmada | entrada, l10_culture.cs |
¿Qué tamaño tiene un archivo tras StreamWriter.Write("E2 A2 D3"), antes y después de Dispose? |
0 bytes antes, 8 después | 0, luego 8 | Confirmada | entrada, l10_dispose.cs |
¿Encuentra ScaleVideoUrlById de GA sus datos? |
Ningún recurso llamado …scale_video_urls.json en GA.Domain.Core, ningún archivo de repliegue junto a la sonda, un resultado vacío, ninguna excepción. La lectura de un subagente lo sugirió antes de que yo leyera el código |
0 recursos en total, ningún archivo de repliegue, 0 escalas con URL | Confirmada | entrada, files.cs |
¿Qué crea dotnet new xunit con el SDK 10.0.112, y qué imprime dotnet test? |
xUnit v2, paquete xunit 2.9.x, con xunit.runner.visualstudio, Microsoft.NET.Test.Sdk y coverlet.collector; ejecutado por VSTest, con una línea Passed! al final |
xunit 2.9.3, xunit.runner.visualstudio 3.1.4, Microsoft.NET.Test.Sdk 17.14.1, coverlet.collector 6.0.4; VSTest 18.0.2; Passed! - Failed: 0, Passed: 1, … |
Confirmada | entrada, Fretboard.Tests.csproj |
¿Una [Theory] con cuatro filas [InlineData] cuenta como 4 pruebas o como 1? |
4 | 15 pruebas en el proyecto: contando la teoría una sola vez habrían sido 12 | Confirmada | entrada, GuitarTests.cs |
¿Qué hacen Assert.Equal(0.3, 0.1 + 0.2) y Assert.Equal(0.3, 0.1 + 0.2, 10)? |
La primera falla y muestra el valor obtenido 0.30000000000000004; la segunda pasa |
Como se predijo. No previsto: el valor esperado se muestra como 0.29999999999999999 |
Confirmada | entrada, PitfallTests.cs |
Cuando el método lanza ArgumentOutOfRangeException, ¿qué hacen Assert.Throws<ArgumentException> y Assert.ThrowsAny<ArgumentException>? |
Throws falla, quiere el tipo exacto; ThrowsAny pasa |
Assert.Throws() Failure: Exception type was not an exact match; ThrowsAny pasa |
Confirmada | entrada, PitfallTests.cs, GuitarTests.cs |
| ¿Crea xUnit una instancia nueva de la clase de prueba para cada prueba? | Sí: un campo incrementado por cada una de dos pruebas vale 1 en las dos | Las dos pruebas pasan | Confirmada | entrada, InstanceTests.cs |
Ejecutadas sin cambios contra los servicios de GA en el commit 5c3a52a, ¿qué dan las MusicalKnowledgeServiceTests de GA? |
0 fallidas, 3 omitidas, 5 superadas, incluida la de las afinaciones especiales, porque la única afinación por defecto hace que su lista no esté vacía. Escrita tras leer el archivo de pruebas, antes de ejecutarlo | 5 superadas, 3 omitidas, 0 fallidas; 1 afinación especial, «Overall Valid: True» | Confirmada | entrada, knowledge-tests, knowledge-results.txt |
¿Se ejecuta el [SetUpFixture] TestEnvironment de GA antes de las pruebas de GA.Business.Core.Tests.Configuration? |
No: está solo en su namespace. Una prueba de la sonda junto a las de GA ve GA_TEST_MODE sin definir y su carpeta bin como directorio actual. Escrita tras leer el bootstrap, antes de ejecutarlo |
GA_TEST_MODE: (not set), Current directory is the test's bin folder: True |
Confirmada | entrada, knowledge-tests, knowledge-results.txt |
¿Qué crea dotnet new sln con el SDK 10.0.112? |
Un archivo .slnx, no un .sln |
Fretboard.slnx: <Solution> y </Solution>, ningún proyecto |
Confirmada | entrada, l12-project |
En la carpeta de una solución con una biblioteca, una aplicación de consola y un proyecto de pruebas, ¿qué compilan y ejecutan dotnet build y dotnet test? |
dotnet build compila los tres proyectos; dotnet test ejecuta solo las pruebas del proyecto de pruebas |
dotnet build: Fretboard, Fretboard.App, Fretboard.Tests. dotnet test: un ensamblado de pruebas, 6 superadas. No previsto: tras dotnet clean, dotnet test deja Fretboard.App sin compilar |
Confirmada | entrada, l12-project |
Con un error de compilación en la aplicación de consola, ¿qué hacen dotnet test y dotnet build en la carpeta de la solución? Escrita tras ver la aplicación sin compilar, antes de esta ejecución |
dotnet test pasa y termina con el código 0; dotnet build falla |
dotnet test: superado, código de salida 0. dotnet build: compilación fallida, código de salida 1 |
Confirmada | entrada |
¿Qué escribe dotnet add package CsvHelper, y lee CsvHelper un valor entre comillas que contiene una coma como un solo campo? |
La última versión estable; sí, donde Split(',') da un campo de más |
Version="33.1.0" el 3 de octubre de 2026; Split: 4 campos, CsvHelper: 3 |
Confirmada | entrada, l12_csvhelper.cs |
¿Funciona #:package en una aplicación basada en archivos, con y sin versión? |
#:package CsvHelper@33.1.0 restaura y se ejecuta; sin @version la restauración lo rechaza |
3 campos; sin la versión, error NU1015: The following PackageReference item(s) do not have a version specified: CsvHelper, código de salida 1 |
Confirmada | entrada, l12_package_no_version.cs |
¿Puede GetRecords<Project>() de CsvHelper rellenar un record posicional que también tiene una propiedad calculada? |
Sí, por su constructor, según los nombres del encabezado, ignorando SourceFiles |
12 records y 632 archivos fuente; su lista es igual a una lista construida a mano | Confirmada | entrada, ProjectFileTests.cs |
¿Qué hace dotnet pack sin opciones con una biblioteca que referencia CsvHelper? |
Una compilación Release, bin/Release/Fretboard.1.0.0.nupkg, un zip con lib/net10.0/Fretboard.dll y un .nuspec que lista CsvHelper «>= 33.1.0» |
Como se predijo; el .nuspec escribe version="33.1.0", la notación de NuGet para 33.1.0 o posterior, con exclude="Build,Analyzers". No previsto: el mensaje sobre el readme, el commit de HEAD en el .nuspec, y un segundo dotnet pack sin cambios que no imprime ninguna de las dos líneas |
Confirmada | entrada, l12_ex_package.cs |
¿Un paquete con un aviso de seguridad conocido provoca una advertencia, y falla dotnet list package --vulnerable? |
Newtonsoft.Json 12.0.1 da NU1903 al restaurar; el comando lo lista y termina con el código 0 | NU1903 con GHSA-5crp-9r3c-p9vr, impreso dos veces por una aplicación basada en archivos; dotnet list package --vulnerable y dotnet package list --vulnerable imprimen la tabla y terminan con el código 0 |
Confirmada | entrada, l12_audit.cs |
¿Cuánto tardan dos Task.Delay(500), esperados uno tras otro y con Task.WhenAll? |
Al menos 1000 ms; menos de 900 ms | Cinco ejecuciones: de 1014 a 1023 ms, y después de 508 a 514 ms | Confirmada | entrada, l12_async.cs |
¿Qué pasa con una llamada async sin await en un programa de instrucciones de nivel superior? |
Advertencia CS4014, y la línea escrita tras su espera nunca aparece | CS4014 en (2,1); Before, After, código de salida 0 |
Confirmada | entrada, l12_forgotten_await.cs |
¿Qué dice el compilador de un await en un constructor, y de un constructor async? |
CS4033; CS0106, modificador no válido | CS4033, como se predijo. public async VoicingIndex() da CS0246 por un tipo async y CS0542, un miembro con el nombre de su tipo: el analizador lee un método |
Refutada en parte | entrada, l12_constructor_await.cs |
¿Lista AllProjects.slnx de GA todos los archivos de proyecto del repositorio? |
No: faltan al menos 5 .csproj o .fsproj |
Faltan 36 de los 111; ninguno se lista sin existir | Confirmada | entrada, lesson12_counts.py, lesson12-results.txt |
| ¿Se ejecutan en la CI los proyectos de pruebas de GA fuera de la solución, y se compilan de todos modos proyectos que están fuera? Escrita tras el recuento anterior | Al menos un proyecto de pruebas no lo nombra ningún workflow; al menos un proyecto de fuera lo referencia uno listado | Seis proyectos de pruebas, 102 líneas con un atributo de prueba, sin workflow que los nombre; 7 proyectos de fuera referenciados, GA.Business.Core por 4 |
Confirmada | entrada, lesson12_counts.py, lesson12-results.txt |
¿Compila GA.Business.Core.Graphiti.Tests? Escrita tras leer su archivo de proyecto y su prueba |
No: usa GA.Business.Graphiti sin ProjectReference, así que CS0246 |
5 errores: CS0234 en las líneas 7 y 8, después CS0246 | Confirmada | entrada, ga-probes |
| ¿Se declara algún paquete con varias versiones en los archivos de proyecto de GA? | Sí, al menos uno | 35 paquetes; Microsoft.Extensions.Hosting y MongoDB.Driver con cinco versiones cada uno |
Confirmada | entrada, lesson12_counts.py, lesson12-results.txt |
¿Cambian una versión los elementos PackageReference Update del Directory.Build.props de GA? Escrita tras leer el archivo |
No: Microsoft.Extensions.Http se queda en la 9.0.10 del archivo de proyecto de las pruebas Graphiti |
9.0.10; con la misma línea en Directory.Build.targets, 10.0.0, mientras que Microsoft.Extensions.Options, actualizado solo en el archivo props, se queda en 9.0.10 |
Confirmada | entrada, ga-probes |
| ¿Bloquea el código de GA fuera de las pruebas sobre tareas en al menos 20 sitios? | Sí | 27 coincidencias de .Result, .Wait() y GetAwaiter().GetResult(): 4 son SemaphoreSlim.Wait(), 7 leen tareas tras await Task.WhenAll, 5 están en archivos excluidos de la compilación; quedan 11, 3 de ellas en constructores |
Refutada | entrada, lesson12_counts.py, lesson12-results.txt |
¿Tiene GA un método async void que no sea un manejador de eventos? |
Sí, al menos uno | Ninguno | Refutada | entrada, lesson12_counts.py |
¿Funciona GaCLI desde otra carpeta sin appsettings.yaml, y arranca sync-mongodb? Escrita tras leer Program.cs |
Imprime su ayuda; sync-mongodb se detiene por un MusicalObjectsService que falta, desde las dos carpetas |
Ayuda impresa; Error during sync: Unable to resolve service for type 'GA.Data.MongoDB.Services.MusicalObjectsService'... desde las dos carpetas, código de salida 0 |
Confirmada | entrada, ga-probes |
2026-09-14 — El SDK y las aplicaciones basadas en archivos
Sección titulada «2026-09-14 — El SDK y las aplicaciones basadas en archivos»- Mi máquina tiene dos SDK: 10.0.112 y 11.0.100-preview.3.26207.106. Sin un
global.json,dotnetelige la preview. La carpeta del curso fija10.0.100conrollForward: latestFeature, lo que selecciona 10.0.112 aquí. - WinGet ofrece
Microsoft.DotNet.SDK.10en la versión 10.0.401 ese mismo día: una banda de características más reciente que la mía. La página de aplicaciones basadas en archivos indica que#:includeestá disponible desde el SDK 10.0.300, así que la lección 1 dice que una aplicación basada en archivos es un solo archivo por defecto, y que#:includeañade otros a partir de ese SDK. No he probado#:include: mi SDK es anterior. - Los ejemplos son aplicaciones basadas en archivos en lugar de un proyecto por lección: un principiante escribe un archivo y lo ejecuta, sin nada que configurar. Un único
dotnet run app.cstardó 0.9 s la primera vez y 0.2 s la siguiente. - Los demás archivos
.csde la misma carpeta no se compilan con la aplicación:hello.csse ejecutó sin problemas junto a un archivo lleno de errores. - Las advertencias solo se imprimen cuando el SDK compila. Un segundo
dotnet runde un archivo sin cambios no imprime ninguna advertencia, ydotnet run --no-cachetampoco ayuda: se salta la comprobación de actualización de la aplicación basada en archivos, pero MSBuild sigue viendo la salida compilada al día y se salta el compilador.dotnet clean app.csantes de cada ejecución devuelve las advertencias;check.shlo hace, y la lección 3 se lo cuenta al lector. - Los errores del compilador van a la salida estándar, con la ruta completa del archivo;
The build failed. Fix the build errors and run again.va a la salida de error.check.shjunta ambas y conserva solo el nombre del archivo, para que los archivos esperados sean iguales en todas las máquinas. - Los errores de sintaxis ocultan los demás: en el programa roto del ejercicio 2 de la lección 1, el
Writelinemal escrito (CS0117) solo se señala una vez corregidos el;y las comillas que faltan. El ejercicio se basa en eso. - Entrada estándar: cuando la entrada viene de un archivo, el texto tecleado no aparece en la salida, así que los archivos esperados contienen las preguntas seguidas directamente de las respuestas. Las lecciones muestran la terminal tal como la ve una persona, con las líneas tecleadas, y lo dicen.
- Cultura: la cultura de mi Windows es
en-CA. Cones-ES,double.TryParse("1.5")devuelvetruey 15, ya que el punto es el separador de miles en español; confr-FR, devuelvefalse. El ejemplo fija cada cultura explícitamente, así que la salida es la misma en todos los sistemas operativos. Los demás ejemplos solo usan formatos que se imprimen igual enen-CA,en-USy la cultura invariable del runner Linux.
2026-09-14 — CI
Sección titulada «2026-09-14 — CI»- Commit
b19a296, ejecución 34914488934: en verde en los tres sistemas operativos.actions/setup-dotnetcon elglobal.jsondel curso instaló el SDK 10.0.401 en los tres runners, mientras que las salidas se capturaron con 10.0.112: todos los mensajes del compilador son idénticos. Los jobs tardaron 54 s en Linux, 1 min 36 s en macOS y 2 min 18 s en Windows, con undotnet cleany una compilación para cada una de las 58 aplicaciones basadas en archivos. Math.Pow(2, 7 / 12.0)impreso con todos sus dígitos,164.81377845643496, es igual en los tres sistemas operativos.- La línea shebang
#!/usr/bin/env -S dotnet --funciona en los runners Linux y macOS después dechmod +x, ydotnet runla ignora en Windows. - Los códigos de salida de una excepción no controlada difieren, así que
check.shlos imprime y solo comparaexit crash:- Linux y macOS: 134 (el proceso aborta,
SIGABRT) para los tres ejemplos que fallan; - Windows, visto desde Git Bash: 127 para
IndexOutOfRangeExceptionySwitchExpressionException, y 139 con un mensaje «Segmentation fault» paraNullReferenceException; - Windows, visto desde PowerShell:
0xE0434352(-532462766), el código de una excepción .NET, paraIndexOutOfRangeException, pero0xC0000005(-1073741819), una violación de acceso, paraNullReferenceException.
- Linux y macOS: 134 (el proceso aborta,
2026-09-14 — Dogfooding
Sección titulada «2026-09-14 — Dogfooding»- Los ejemplos usan Guitar Alchemist como datos pequeños: la afinación estándar de
Tuning.Defaulten el commita826864, y doce nombres de proyectos decode/ladybugdb/data/ga/projects.csv, extraídos en el commita26a7893. Nada en estas lecciones reveló un problema en GA.
2026-09-29 — Clases y objetos
Sección titulada «2026-09-29 — Clases y objetos»- La lección 5 presenta la construcción, la identidad de las instancias, los campos privados, las propiedades públicas, los métodos y un contador
staticcompartido; después propone crear una clasePracticeSession. Las páginas inglesa, francesa y española comparten los mismos fragmentos C# probados y las mismas salidas del compilador. - En Windows, con el SDK 10.0.112,
C:/Program Files/Git/bin/bash.exe check.shpasó para los ejemplos, soluciones y fragmentos rechazados del curso, incluidos los nuevos archivosl05_*. Los dos nuevos fragmentos rechazados produjeron CS0122 y CS0200, respectivamente. Elbashpredeterminado del equipo era WSL y no encontraba eldotnetde Windows: aquel primer fallo era del entorno de pruebas, no del código. - Este resultado local no sustituye una nueva CI en tres sistemas ni demuestra que la lección esté publicada. Las lecciones 6–12 siguen solo en el plan.
2026-09-30 — La lección 5 en la CI de tres sistemas
Sección titulada «2026-09-30 — La lección 5 en la CI de tres sistemas»- La ejecución 36664604662 del workflow C# for beginners examples, sobre el commit
669d42ade la PR #60, pasó enubuntu-latest,windows-latestymacos-latest. En la salida de cada job,check.shimprimeokparal05_objects,l05_ex_practice,l05_get_only_propertyyl05_private_field: las salidas y los diagnósticos CS0122 y CS0200 coinciden conexpected/en los tres sistemas.
2026-10-01 — Records, structs y enums
Sección titulada «2026-10-01 — Records, structs y enums»- La lección 6 compara una estructura con una clase (copia al asignar, copia como argumento,
Equals), y después presenta los records (==sobre los datos,ToString,with,readonly record struct) y las enumeraciones (numeradas desde 0, valor predeterminado, casts,Enum.IsDefined,Enum.Parse). Tiene cuatro ejemplos, tres ejercicios y cinco fragmentos rechazados, cuyos diagnósticos son CS0019, CS1612, CS8852 (tres veces en dos archivos) y CS0266. Un script comprobó que los tres idiomas comparten los mismos bloques de código, sin contar los comentarios, y que cada bloque coincide con su archivo encode/csharp-beginneryexpected/. - En Windows, con el SDK 10.0.112 y Git Bash,
check.shterminó con código 0 y 75 líneasok, incluidos los 12 archivosl06_*. Todavía no es una ejecución de la CI en tres sistemas. - Después, en la CI: la ejecución 36865237779 del workflow C# for beginners examples, sobre el commit
114b5edde la PR #93, pasó enubuntu-latest,windows-latestymacos-latest. Cada job imprimeokpara los 12 archivosl06_*; los jobs cuentan 76 líneasoken Linux y macOS y 75 en Windows, porquecheck.shsolo ejecuta el ejemplo con shebang mediante./en Linux y macOS. - Sorpresas, todas recogidas en la lección: CS8524 avisa de una expresión
switchque tiene un brazo por nombre, y su ejemplo es(ChordQuality)5mientras el programa falla con 7; el literal0se convierte en una enumeración sin cast, mientras que2da CS0266; unaList<T>de estructuras modificables rechazashape[0].Fret = 5con CS1612. - Un borrador del ejercicio 3 decía que
shape[i].Fret += 2sobre una lista dereadonly record structda el mismo CS1612. Una sonda compilada antes de publicar dio CS8852; el texto se corrigió, ycompile_fail/l06_readonly_position.csguarda ahora las dos líneas CS8852. Otras dos frases se apoyan en sondas que quedaron fuera del código del curso: guardar una copia modificada conshape[0] = position;mostró 5, yList<T>.Containssobre una clase sin igualdad propia respondióFalse. - Dogfooding: en el commit
5c3a52ade GA,ChordQualityempieza porOther, yPositionLocation,StryFretson tiposreadonly record struct. Nada en esta lección reveló un problema en GA.
2026-10-01 — Interfaces y herencia
Sección titulada «2026-10-01 — Interfaces y herencia»- La lección 7 construye
GuitaryUkulelesobre una clase baseStringInstrument(base(...),virtual,override,base.Describe(),ToString), después una clase abstractaInstrumentcon un método abstractoPlay, y después una interfazIHasRangeque implementan tanto una clase como un record. Tiene cuatro ejemplos, uno de los cuales compila con la advertencia CS0114, tres ejercicios y cinco fragmentos rechazados, cuyos diagnósticos son CS0506, CS0509, CS0144, CS0534 y CS0535. El script usado para la lección 6 comprobó los 20 bloques de código de los tres idiomas contracode/csharp-beginneryexpected/. - En Windows, con el SDK 10.0.112 y Git Bash,
check.shterminó con código 0 y 87 líneasok, incluidos los 12 archivosl07_*. Todavía no es una ejecución de la CI en tres sistemas. - Después, en la CI: la ejecución 36893689911 del workflow C# for beginners examples, sobre el commit
b347f7dde la PR #95, pasó enubuntu-latest,windows-latestymacos-latest. Cada job imprimeokpara los 12 archivosl07_*; los jobs cuentan 88 líneasoken Linux y macOS y 87 en Windows, por la misma razón que en la lección 6. - Dos frases del borrador no se apoyaban en ninguna ejecución y cambiaron antes de publicar. Que solo una variable de tipo
Ukuleleencuentre un método que oculta es ahora una línea deexamples/l07_hiding_warning.cs, que muestraa ukulele. «Los números MIDI son los de la lección 4, donde do4 vale 60» era falso, ya que la lección 4 no da ningún número MIDI; la frase dice ahora que los números MIDI cuentan semitonos, 12 por octava. - Dogfooding: en el commit
5c3a52ade GA,ChordTemplatees un record abstracto cuyos records derivadosTonalModalyAnalyticalredefinenName, y cuyo propioToString() => Nameno essealed. La página de los records dice que unToStringsealedimpide que el compilador sintetice uno en los records derivados (formato integrado para la presentación); este debía quedar, pues, oculto. Una sonda lo confirmó: un proyecto de consola que referencia GA.Domain.Core y GA.Domain.Services en el commit5c3a52a, compilado con el SDK 10.0.112, mostróTonalModal { Name = Major 7th, PitchClassSet = 0 4 7 E, … }paraToString()y para$"{template}"en unTonalModal, en unAnalyticaly enChordTemplateFactory.CreateModalChords(...).First(), y la reflexión señaló el record derivado como el tipo que declaraToString. Una réplica de la misma forma conpublic sealed override string ToString() => Namemostrómaj7. Un solo punto de llamada depende de ello: ContextualChordsController.cs:301 pasatemplate.ToString()aGetVoicingsForChordAsync, que lo registra (FretboardServices.cs:536); la respuesta HTTP toma el nombre del acorde de la ruta, no de esta cadena. El hallazgo está en la tabla QA; no se ha comunicado a GA.
2026-10-02 — Excepciones y seguridad frente a null
Sección titulada «2026-10-02 — Excepciones y seguridad frente a null»- La lección 8 captura excepciones con
tryycatch, con un diagrama de las clases de excepción; ejecutafinallydespués de unreturn, después de uncatchy antes de que una excepción salga del método; lanza unaArgumentOutOfRangeExceptionconnameof; y después vuelve sobrenull: CS8600 y CS8618,required, el operador!, yWarningsAsErrors=nullabledefinido con#:property. Tiene seis ejemplos, cuatro archivos de ejercicio (uno de ellos el punto de partida del ejercicio 3, con cuatro advertencias) y cinco fragmentos rechazados, cuyos diagnósticos son CS0160, CS0165, CS0029, CS9035 y CS8602 como error. El script usado para las lecciones 6 y 7 comprobó los 28 bloques de código de los tres idiomas contracode/csharp-beginneryexpected/. - En Windows, con el SDK 10.0.112 y Git Bash,
check.shterminó con código 0 y 102 líneasok, incluidos los 15 archivosl08_*. Todavía no es una ejecución de la CI en tres sistemas. - La primera ejecución de la CI de la PR #109 falló solo en Linux (ejecución 36968274101): el runner de Linux mostró las advertencias de
l08_null_warnings.csyl08_ex_null_start.csen el orden de las líneas, mientras que Windows, en local y en la CI, y macOS mostraban CS8618 primero. Los mensajes eran idénticos.check.shcoloca ahora los mensajes del compilador primero, los errores antes que las advertencias, cada grupo ordenado por línea y columna, y la lección muestra ese orden. Ningún archivo esperado de las lecciones 1 a 7 cambió: sus mensajes ya venían en ese orden. - Después, con esa corrección: la ejecución 37009963497 del workflow C# for beginners examples, sobre el commit
e2a95efde la PR #109, pasó enubuntu-latest,windows-latestymacos-latest. Cada job imprimeokpara los 15 archivosl08_*; los jobs cuentan 103 líneasoken Linux y macOS y 102 en Windows, por la misma razón que en la lección 6. - Sorpresas, todas recogidas en la lección:
throw "fret out of range";da CS0029, un error de conversión, donde esperaba CS0155 (The type caught or thrown must be derived from System.Exception);string capo = null;sobre una variable local da CS8600, no CS8625, mientras que el archivo de prueba de GA de más abajo recibió CS8625 por un argumentonull; enl08_null_warnings.cs, CS8618 está en la declaración de la propiedad y la línea que falla no tiene ninguna advertencia;tuner offse muestra antes que el valor que devuelveTune. - Una frase se apoya en una sonda que quedó fuera del código del curso: sin su comprobación,
NoteOfString(standard, 7)falla con unaIndexOutOfRangeException. - Dogfooding en el commit
5c3a52ade GA, con las hipótesis escritas antes de medir en la tabla de experimentos, y las sondas y sus instrucciones encode/csharp-beginner/ga-probes:NoWarnenumera quince advertencias de nulabilidad en Directory.Build.props:21, y otra vez en Directory.Build.targets:7. Esperaba más de 100 advertencias ocultas en GA.Domain.Core; sin las dos listas, GA.Domain.Core y GA.Core no tienen ninguna.ZzNullableCanary.cs, siete errores de nulabilidad añadidos a GA.Domain.Core, compiló sin advertencias con las listas, y con sus siete advertencias (CS8600 ×2, CS8602 ×3, CS8618, CS8625) sin ellas. La hipótesis queda refutada, y la tabla QA guarda el hallazgo: las listas solo ocultan los errores que están por venir.new Fret(50),Fret.FromValue(50)yFret f = 50;lanzan todos unaArgumentOutOfRangeException, para 50 y para -2, como se esperaba, yFret.TryCreate(50)devuelveFailure(Fret number must be between -1 (muted) and 36, got 50). El mensaje de la excepción nombra una constante privada,GA.Domain.Core.Instruments.Primitives.Fret value (50) cannot be greater than _maxValue (36). (Parameter 'value'), porque IRangeValueObject.cs lo construye a partir de las expresiones del llamador, y suActualValuequeda vacío.- La pregunta abierta del 2026-10-01 tiene respuesta:
new PositionLocation(5, 3), con la cuerda y el traste intercambiados como simples números, compila sin advertencia y construye la cuerda 5, traste 3. Una compilación con todos los analizadores (AnalysisLevel=latest-all) solo pidió, en esas líneas, tipos explícitos en lugar devar. Las conversiones implícitas desdeint(Str.cs:45, Fret.cs:72) dejan pasar el intercambio.
2026-10-02 — Colecciones y LINQ
Sección titulada «2026-10-02 — Colecciones y LINQ»- La lección 9 cubre
Dictionary<TKey, TValue>: el indexador,Add,TryGetValue, contar conGetValueOrDefaulty el orden de unforeach. CubreHashSet<T>, con sus operaciones de conjunto sobre copias ySetEquals. Presenta las lambdas y luego LINQ sobre los proyectos de GA de la lección 4, ahora records:Count,Where,Select,OrderBy,ThenBy,First,FirstOrDefault,Any,All,TakeyToList. Termina con la ejecución diferida y con la modificación de una colección dentro de su propioforeach. Tiene diez ejemplos, cuatro ejercicios y cuatro fragmentos rechazados: CS1503, CS0021, CS0266, y CS0029 con CS1662 en la misma columna. El comprobador de bloques hizo corresponder los 37 bloques de código de cada idioma concode/csharp-beginneryexpected/. - La lección 4 anunciaba que la lección 5 sustituiría sus dos arrays de proyectos por una sola lista; la lección 5 no lo hizo. La lección 9 lo hace, y la lección 4 remite ahora a ella.
- En Windows, con el SDK 10.0.112 y Git Bash,
check.shterminó con código 0 y 120 líneasok, incluidos los 18 archivosl09_*. Todavía no es una ejecución de la CI en tres sistemas. - Después, en la CI: la ejecución 37061776660 del workflow C# for beginners examples, sobre el commit
690201dde la PR #113, pasó enubuntu-latest,windows-latestymacos-latest. Cada job imprimeokpara los 18 archivosl09_*; los jobs cuentan 121 líneasoken Linux y macOS y 120 en Windows, por la misma razón que en la lección 6. - Medido antes de escribir:
- C# 14 no tiene expresiones de diccionario.
Dictionary<string, int> d = ["C": 0, "E": 4];da CS1003 y otros ocho errores de sintaxis, así que la lección usa un inicializador de índice,{ ["C"] = 0 }. Firstsin coincidencia lanzaSequence contains no matching element. Esta sonda quedó fuera del código del curso.- Los dos experimentos de diccionarios de la tabla. La documentación respalda ambos: «The order in which the items are returned is undefined», y
Remove«may be safely called without invalidating active enumerators» desde .NET Core 3.0.
- C# 14 no tiene expresiones de diccionario.
- Dogfooding en el commit
5c3a52ade GA, con la hipótesis escrita antes de medir en la tabla de experimentos:- Un repaso de las colecciones en el código de GA, leído en ese commit, dio los ejemplos de la lección:
ChordVocabulary.PitchClasses(ChordVocabulary.cs:23), un diccionario que no distingue mayúsculas, leído conTryGetValue, donde"C#"y"Db"dan ambos 1. Sus observaciones dicen que dos copias anteriores «had drifted» (se habían separado); ungit grepde["Db"] = 1o{ "Db", 1 }encuentra 18 archivos con su propia tabla, este incluido.PitchClassSet, unIReadOnlySet<PitchClass>construido sobre unImmutableSortedSet(PitchClassSet.cs:37), igual a otro cuando susId, calculados a partir de las notas, lo son.
MusicalKnowledgeService.GetArtistBreakdownse queda conGetAllArtists().Take(20), los 20 primeros por nombre, y luego los ordena por número de entradas en unDictionary. Esperaba más de 20 artistas, y algunos excluidos con más entradas que uno conservado.artists.cs, compilado conGA.Domain.Servicesextraído congit archiveen la carpeta.gaignorada, encontró 16: ninguno queda fuera. Dos ejecuciones dieron la misma salida.- La razón es la primera fila QA del día: tres de los cuatro archivos YAML no se deserializan, y cada cargador captura la excepción y conserva un elemento por defecto. La sonda muestra los mensajes de los cargadores. Una prueba de deserialización, fuera del código del curso, localizó las tres líneas, y leí cada una frente a la clase que llena. Las tres líneas siguen igual en el
mainde GA,ae196bf, el más reciente que conoce el clon local. MusicalKnowledgeServiceTestsmuestraArtistBreakdown.Take(5)bajo=== Top Artists ===(MusicalKnowledgeServiceTests.cs:51), lo que también depende del orden del diccionario.
- Un repaso de las colecciones en el código de GA, leído en ese commit, dio los ejemplos de la lección:
2026-10-03 — Un diagrama del mástil dibujado en C#
Sección titulada «2026-10-03 — Un diagrama del mástil dibujado en C#»- La lección 3 muestra ahora las notas de los trastes 0 a 5 en un diagrama, debajo de la salida de
l03_fretboard.cs. La pregunta era si ComfyUI o Blender debían dibujar algunas imágenes del curso. Una imagen generada puede equivocarse en el número de cuerdas o de trastes, y este diagrama debe mostrar exactamente las notas que imprime el programa, así que lo dibuja un programa C#:tools/fretboard.cs, con las mismas cuerdas al aire y los mismos nombres de notas que la lección. - El SVG no contiene palabras, solo nombres de notas y números, así que los tres idiomas comparten un único archivo,
src/assets/csharp-beginner/l03-fretboard.svg. La lección lo importa como un componente, como el curso de teoría musical, para que siga el tema claro u oscuro. Para eso la lección 3 pasó a ser un archivo.mdx; su dirección no cambia. La descripción para lectores de pantalla está traducida. check.shejecutatools/fretboard.cs -- --check, que falla si el SVG del repositorio difiere de lo que dibuja el programa. Antes de fiarme, cambié a mano una nota del archivo: la comprobación imprimióis not up to datey terminó con el código 1. Una copia con finales de línea de Windows pasa. En Windows,check.shimprime ahora 121 líneasok.- La herramienta encuentra el repositorio a partir de su propia carpeta,
AppContext.GetData("EntryPointFileDirectoryPath"), y no de la carpeta actual, y escribe cada coordenada como unint: con la culturafr-FR,$"{2.5}"da2,5. Los dos puntos importan para los archivos, el tema de la lección 10. - Renderizado con Edge sin ventana en una página clara, una oscura y a 343 píxeles de ancho, el de un teléfono: las 36 notas coinciden línea por línea con la salida del programa. Ese día, Chrome sin ventana y la captura por DevTools superaron su tiempo de espera en esta máquina.
- Después, en la CI: la ejecución 37142282699 del workflow C# for beginners examples, sobre el commit
9229f15de la PR #126, pasó enubuntu-latest,windows-latestymacos-latest. Cada job imprimeok fretboard svg; los jobs cuentan 122 líneasoken Linux y macOS y 121 en Windows, por la misma razón que en la lección 6.
2026-10-03 — Archivos y texto
Sección titulada «2026-10-03 — Archivos y texto»- La lección 10 está escrita en tres idiomas:
File,Path, el directorio actual, los saltos de línea, un archivo CSV, los números y las culturas, los flujos yusing, las codificaciones, y lo que Guitar Alchemist hace con sus archivos. Tiene 11 ejemplos, 4 ejercicios y 3 fragmentos rechazados, cada uno comparado conexpected/porcheck.sh. La lección es un archivo.mdx, por las pestañas que muestran una ruta en cada sistema. data/ga-projects.csves nuevo: los doce proyectos de la lección 4 con sus números de archivos.csy.fsen el commit5c3a52ade GA, contados congit ls-treeen la carpeta de cada proyecto. Trae dos sorpresas.GA.Business.Config, un proyecto F#, contiene 8 archivos C#, los servicios que vio la lección 9.GA.Presentationno tiene ningún archivo fuente, solo su.csproj..gitattributesda a*.csvfinales de línea LF, para que el archivo sea el mismo en cada sistema.- Se escribieron ocho hipótesis antes de medir, y las ocho se confirman (tabla de experimentos). Dos no eran a ciegas: al escribir
tools/fretboard.cs, ese mismo día, ya había vistoEntryPointFileDirectoryPath, y$"{2.5}"confr-FR. La hipótesis E14 viene de la lectura de GA por un subagente, antes de que yo leyeraScaleVideoUrlById. check.shejecutal10_where.csuna segunda vez desde la raíz del repositorio y compara su salida conexpected/l10_where_root.txt: así la CI comprueba en tres sistemas que el mismo programa no encuentra su archivo desde otra carpeta. La raíz no tieneglobal.json: allí, en mi máquina,dotnetelige el SDK 11.0.100 preliminar en lugar del 10.0.112, otra decisión que toma el directorio actual. La salida es la misma.TextFieldParsercompiló conusing Microsoft.VisualBasic.FileIO;y sin paquete: viene con .NET.- La sonda
files.csejecuta los cargadores de GA tres veces, como describe su README: tal como se compila, tras borrar los archivos YAML junto a ella, y desde la raíz del código de GA extraído. Su compilación imprime IL3000 por su propio uso deAssembly.Location, la llamada de la que depende el repliegue deScaleVideoUrlById: en una aplicación de archivo único devuelve una cadena vacía. - Seis filas QA nuevas vienen de la sonda y de la lectura del código de GA que maneja sus archivos. Un subagente listó los candidatos; releí las líneas de cada uno en el commit
5c3a52aantes de escribirla. Dos de esas filas solo se leyeron en el código, no se ejecutaron. - El fallo de carga de los YAML de la lección 9 es ahora GuitarAlchemist/ga#797, abierta el 2026-10-03 con enlaces fijados al
mainde GA,ba3b9ac, donde las tres líneas siguen igual. - En Windows con el SDK 10.0.112,
check.shtermina con el código 0 y 140 líneasok, incluidas las 19 de la lección 10. Todavía no es una ejecución de la CI en tres sistemas. - Después, en la CI: la ejecución 37145323198 del workflow C# for beginners examples, sobre el commit
8b9fc03de la PR #129, pasó enubuntu-latest,windows-latestymacos-latest. Cada job imprimeokpara las 19 comprobacionesl10_*, incluida la ejecución desde la raíz del repositorio; los jobs cuentan 141 líneasoken Linux y macOS y 140 en Windows, por la misma razón que en la lección 6.
2026-10-03 — Pruebas unitarias
Sección titulada «2026-10-03 — Pruebas unitarias»- La lección 11 está escrita en tres idiomas: una prueba a mano, una biblioteca y un proyecto de pruebas,
[Fact]ydotnet test,[Theory], cuatro pruebas que fallan a propósito, un objeto por prueba, la superficie pública, y las pruebas de Guitar Alchemist. El código está enl11-tests: la bibliotecaFretboard, con métodos de las lecciones 4, 8 y 10 sin cambios;Fretboard.Tests, 26 pruebas con las soluciones de los ejercicios;Pitfalls.Tests, 6 pruebas de las que 4 fallan a propósito.examples/l11_by_hand.csycompile_fail/l11_private.csse ejecutan con los demás archivos. - Los proyectos vienen de
dotnet new classlib,dotnet new xunitydotnet add reference, ejecutados en la carpeta del curso; la lección cita sus mensajes. La plantilla crea un proyecto xUnit v2, mientras que el sitio de xUnit dice que la v2 está en mantenimiento y anima a usar la v3. check.shejecutadotnet testen los dos proyectos de pruebas trasdotnet clean, para que las advertencias de la compilación se impriman siempre, y guarda un resumen: las advertencias, cada prueba fallida y su mensaje, la última línea. Quita las rutas, las duraciones y las pilas de llamadas, y ordena las pruebas fallidas por nombre: xUnit comunicó los cuatro fallos en otro orden que el del archivo. Las flechas↓y↑de un fallo en una colección atravesaron Git Bash en Windows; la CI dirá si pasa lo mismo en los tres sistemas.- Se escribieron siete hipótesis antes de medir, y las siete se confirman (tabla de experimentos). Las dos últimas se escribieron tras leer el archivo de pruebas de GA y su bootstrap, antes de ejecutarlos.
- Observado sin hipótesis: desde un proyecto de pruebas, un miembro de la biblioteca marcado
internalda CS0117, «does not contain a definition», y no CS0122, en un par de proyectos de prueba; el analizador del paquetexunitavisa de los argumentos invertidos (xUnit2000) antes de que se ejecuten las pruebas. - El primer fallo de la lección es una comprobación a mano:
FretFrequency(246.94, 1)da 261.62, y una tabla da 261.63 para el do central, porque la cuerda Si al aire ya está redondeada. El programa termina igualmente con el código 0, lo que motiva un framework. - La sonda
knowledge-testses un proyecto NUnit que compila sin cambios cuatro archivos de GA.Business.Core.Tests extraídos del código:MusicalKnowledgeServiceTests.cs,TestEnvironment.cs,GlobalUsings.csyAssemblyInfo.cs, con las versiones de paquetes de ese proyecto.ProbeTests.cses su único archivo propio. Su compilación solo imprime IDE0028 enScaleMetadataRegistry.csde GA. Su ejecución: 9 pruebas, 6 superadas (las 5 de GA y la de la sonda), 3 omitidas. - Esto responde a la pregunta abierta del diario: ninguna prueba de GA falla cuando un archivo YAML de
GA.Business.Configdeja de cargarse. La pregunta se quita de la lista de abajo. - En Windows con el SDK 10.0.112,
check.shtermina con el código 0 y 144 líneasok, incluidas las 4 de la lección 11. Todavía no es una ejecución de la CI en tres sistemas. - Después, en la CI: la ejecución 37170066128 del workflow C# for beginners examples, sobre el commit
c3427a9de la PR #135, pasó enubuntu-latest,windows-latestymacos-latest. Cada job imprimeokpara las 4 comprobacionesl11_*; los jobs cuentan 145 líneasoken Linux y macOS y 144 en Windows, por la misma razón que en la lección 6.l11_Pitfalls.Teststambién pasa en Windows: las flechas↓y↑del fallo en una colección atraviesan Git Bash sin cambios.
2026-10-03 — Un pequeño proyecto
Sección titulada «2026-10-03 — Un pequeño proyecto»- La lección 12 está escrita en tres idiomas: una solución con la biblioteca de la lección 11, una aplicación de consola y un proyecto de pruebas; los códigos de salida; un paquete de NuGet en una aplicación basada en archivos y en la biblioteca; un paquete con una vulnerabilidad conocida;
dotnet pack; un primer vistazo aasync; y la solución, las versiones de paquetes, la herramienta de línea de comandos y las esperas bloqueantes de Guitar Alchemist. El código está enl12-project:Fretboard, la biblioteca de la lección 11 conGuitarsin cambios,ProjectsinParse, yProjectFile, que lee el archivo CSV con CsvHelper 33.1.0;Fretboard.App, con tres comandos;Fretboard.Tests, 6 pruebas. Cuatro ejemplos, dos fragmentos rechazados y cuatro soluciones de ejercicios son aplicaciones basadas en archivos. check.shempaqueta la biblioteca antes del bucle, porqueexercises/l12_ex_package.cslee el paquete, y borra antes el paquete viejo: sin cambios,dotnet packlo conserva y no imprime ninguna de sus dos líneas. Ejecutadotnet testsobre la solución trasdotnet cleany comprueba que la aplicación de consola sigue sin compilar, y despuésdotnet build, cuya salida reduce a los nombres de los proyectos, ordenados, y a los totales. Ejecuta la aplicación con seis comandos e imprime cada código de salida. Una nueva reglasedquita la carpeta de los mensajes de NuGet de una línea#:package,file.csproj : warning NUxxxx.- Doce hipótesis sobre el SDK y nueve sobre GA se escribieron antes de medir, algunas tras leer el código que prueban (tabla de experimentos): 16 confirmadas, 1 refutada en parte, 2 refutadas. Las refutadas tratan de las esperas de GA: 11 esperas bloqueantes compiladas, no 20 o más, y ningún
async void. - Observado sin hipótesis:
dotnet testsobre una solución no compila la aplicación de consola, lo que llevó a la hipótesis sobre un error de compilación; la advertencia de la auditoría de NuGet sale dos veces en una aplicación basada en archivos; el.nuspecguarda el commit deHEAD; 12 de los 28 comandos de GaCLI lanzanNotImplementedException, y la ejecución 37167745677 de Quality Check de GA está en verde con un paso que terminó con el código de salida 134. - Las sondas están en
ga-probes:lesson12_counts.pylee el commit solo congit, ylesson12-results.txtguarda su salida; la compilación deGA.Business.Core.Graphiti.Testsy su restauración, con una copia de control cuya líneaUpdateestá enDirectory.Build.targets; GaCLI, compilado a partir de los 18 proyectos de sus referencias en 28 s con 21 advertencias, y lanzado desde dos carpetas. - Esto resuelve el punto por verificar sobre GaCLI lanzado desde otra carpeta: funciona, y en este commit
appsettings.yamlno cambia nada. El punto se retira de la lista de abajo, y la fila de la tabla QA se actualiza. - En Windows con el SDK 10.0.112,
check.shtermina con el código 0 y 158 líneasok, incluidas las 14 de la lección 12. Todavía no es una ejecución de la CI en tres sistemas. - La primera ejecución de la CI de la PR, 37174610693, falló en
l12_audityl12_package_no_versionen los tres sistemas, y pasó las otras 12 comprobaciones de la lección 12. La CI usa el SDK 10.0.401, queglobal.jsonpermite (rollForward: latestFeature), y ese SDK llamal12_audit.cs.csprojal proyecto que hay detrás de una aplicación basada en archivos, donde el 10.0.112 dicel12_audit.csproj. La reglasedno esperaba un punto en el nombre y dejaba la carpeta.check.shescribe ahorafile.csprojpara los dos, y la lección da los dos nombres. - Después, en la CI: la ejecución 37175088215 del workflow C# for beginners examples, sobre el commit
87dbafdde la PR #137, pasó enubuntu-latest,windows-latestymacos-latest, los tres con el SDK 10.0.401. Cada job imprimeokpara las 14 comprobacionesl12_*; los jobs cuentan 159 líneasoken Linux y macOS y 158 en Windows, por la misma razón que en la lección 6. La advertencia de la auditoría de NuGet del12_audit.cssale en las tres máquinas, y la salida ordenada de la compilación es la misma.
2026-10-04 — Correcciones propuestas a Guitar Alchemist
Sección titulada «2026-10-04 — Correcciones propuestas a Guitar Alchemist»Trece filas de la tabla QA volvieron a GA como cinco pull requests, abiertas desde un clon aparte en main 75959835. Cada una mide el defecto antes y después de la corrección, y la CI de GA pasa en las cinco. Ninguna está fusionada todavía: GA deja la revisión y la fusión a alguien distinto del autor.
| PR | Filas QA | Cambio | Antes → después |
|---|---|---|---|
| 808 | Los tres archivos YAML (issue 797); las pruebas que no ven un valor de repliegue | Los tres archivos se cargan; las tres pruebas [Ignore] se ejecutan, y una prueba nueva falla cuando un archivo recurre a su elemento por defecto |
Con los archivos antiguos fallan 5 de las 9 pruebas, la nueva con Expected: greater than 1 But was: 1 para cada archivo roto |
| 811 | ReloadConfiguration, GetArtistBreakdown, la cultura del CSV, su número de filas, sync-mongodb |
Un Lazy nuevo en lugar de FieldInfo.SetValue; el orden antes de Take(20); FormattableString.Invariant; la cabecera fuera de la cuenta; Environment.Exit(1) |
FieldAccessException → los cuatro archivos se recargan; < 6, 8, 8, … > valores por fila con fr-FR → 6; 3 filas contadas para una cabecera y dos filas → 2; sync-mongodb sale con 0 → 1 |
| 812 | Los proyectos de pruebas fuera de AllProjects.slnx, los elementos PackageReference Update, el escaneo de seguridad |
Los elementos pasan a Directory.Build.targets; tres proyectos de pruebas entran en la solución; el escaneo falla con un aviso que una línea base no lista |
Degradaciones NU1605 ocultas por NoWarn: 80 → 40; 56 pruebas más en la CI; 21 avisos en la línea base |
| 816 | El ToString de una plantilla de acorde, el [SetUpFixture] |
ChordTemplate.ToString pasa a ser sealed; TestEnvironment pasa al espacio de nombres raíz del proyecto |
Un volcado de 442 o 475 caracteres → el nombre; GA_TEST_MODE sin definir → 1, con la raíz del repositorio como directorio actual |
| 817 | ScaleVideoUrl |
GA.Domain.Core.csproj incrusta scale_video_urls.json, y ScaleVideoUrlById lo lee con su nombre por defecto |
Conjuntos con URL de vídeo: 0 → 1 490 de 4 096 |
- Con el YAML de la 808, GA cuenta 63 artistas en lugar de 16: el corte de
GetArtistBreakdownantes de ordenar se nota, y la prueba de la 811 sobre ese reparto falla con esos datos y el código antiguo. - Mover solo los elementos
Updatehacía fallar la restauración,error NU1107: Version conflict detected for Microsoft.Extensions.Logging.Abstractionsen GA.Infrastructure, porque solo cinco paquetes Microsoft.Extensions estaban alineados. La 812 pone los 19 que se distribuyen con .NET y ASP.NET Core en una sola versión, 10.0.6, la más alta que pide un proyecto o un paquete. - Tres de los seis proyectos de pruebas fuera de la solución, que ningún workflow nombra, entran en ella: las pruebas de Graphiti, con la referencia de proyecto que les faltaba, las de ProbabilisticGrammar y las de TabConversion.Api.
GaChatbot.TestsyTests/GaApi.Teststampoco compilan enmain, yFloorManager.Tests.Playwrightnecesita un FloorManager en marcha. - La comprobación
risk-reportde GA falla en la 812 por diseño: su política prohíbe a un agente modificar.github/workflowsy consideraDirectory.Build.*,*.csprojy*.slnxdecisiones irreversibles, así que debe revisarla un mantenedor. - La 817 modifica un
.csproj, que la política de riesgo de GA cuenta como una puerta de un solo sentido: por eso es una pull request aparte. - La primera ejecución de la CI de la 816 falló en una prueba de otro proyecto que da 10 segundos a PowerShell; la misma prueba había fallado en otra rama el 2026-05-23, y la nueva ejecución pasó.
2026-10-06 — Las PR 816 y 817 de GA, revisadas
Sección titulada «2026-10-06 — Las PR 816 y 817 de GA, revisadas»Las PR 816 y 817 de GA siguen abiertas, sin revisión ni comentarios. Su CI pasa, 16 comprobaciones con 5 omitidas, y GitHub las da por fusionables sin conflicto, aunque el main de GA avanzó 14 commits desde su base, hasta 40d33747. Leídos con la API de GitHub, los tres defectos no cambiaron en ese commit:
- El
ToString() => NamedeChordTemplatesigue sin sersealed(ChordTemplate.cs:84). ScaleVideoUrlByIdsigue leyendo el recursoGA.Domain.Core.Scales.Data.scale_video_urls.jsony la ruta de repliegueScales/Data/(ScaleVideoUrlById.cs:30, :38), yGA.Domain.Core.csprojsigue sin nombrar el archivo.TestEnvironmentsigue solo enGA.Business.Core.Tests.TestBootstrap(TestEnvironment.cs:1).
La lección 7 muestra ahora la trampa de ToString junto a ChordTemplate, con examples/l07_record_tostring.cs. Un record derivado imprime Seventh { Name = Major 7th, Quality = Major 7th }; el mismo record bajo una base cuyo ToString es sealed imprime Major 7th. Las dos salidas vienen del SDK 10.0.112, comparadas con expected/ como lo hace check.sh. El ejemplo existente l07_inheritance.cs, ejecutado igual, sigue coincidiendo con su salida esperada. Las sondas de GA no se volvieron a ejecutar: necesitan una copia de GA fuera del código del curso. Tampoco se ejecutó check.sh completo.
Por verificar
Sección titulada «Por verificar»- Cuántos artistas contaría GA una vez cargados sus tres archivos YAML. Un script de PyYAML sobre los archivos en bruto, fuera del código del curso, estima 63. Según la misma estimación,
Take(20)dejaría fuera a 8 artistas con más entradas que el menor número conservado, entre ellos The Beatles (3 entradas). - Los comandos de instalación para Linux y macOS: en esos sistemas operativos solo se ejecutó el
setup-dotnetde la CI. - El recorrido del depurador de la lección 3 en VS Code, Visual Studio y Rider, para una aplicación basada en archivos y para un proyecto. VS Code 1.118 y Rider están instalados en mi máquina; Visual Studio no.
- Las condiciones de licencia de los tres editores, en el momento de leerlas.
Preguntas abiertas
Sección titulada «Preguntas abiertas»- ¿Tienen los demás proyectos de GA, más allá de GA.Domain.Core y GA.Core, advertencias de nulabilidad que las dos listas
NoWarnocultan? Solo se midieron esos dos (2026-10-02).