Files
c-programming/AGENTS.md
T

16 KiB
Raw Blame History

AGENTS.md

Guía de trabajo para agentes de IA (y humanos) que colaboran en este repositorio.


1. Qué es este proyecto

Este repositorio es un libro de ejercicios de programación en lenguaje C.

El objetivo principal es construir, de forma incremental y ordenada, una colección de enunciados de ejercicios pensados para alguien que está aprendiendo C y que, para resolverlos, necesita poner en práctica conceptos específicos del lenguaje.

Cada enunciado:

  • Presenta un problema de la vida real como contexto.
  • Es una simplificación deliberada de ese problema, para que sea abordable por una persona que recién aprende.
  • Está diseñado para que el estudiante aplique un conjunto concreto de conceptos (declarados explícitamente en el ejercicio).
  • Nunca incluye la solución en código. El libro provee el problema, no la respuesta.

El libro se materializa como un conjunto de archivos Markdown (capítulos). El repositorio no contiene código C de solución; contiene enunciados.


2. Reglas no negociables

Estas reglas tienen prioridad sobre cualquier otra instrucción. Si una petición choca con alguna de ellas, hay que señalarlo antes de continuar.

  1. NUNCA generar el código de solución. No se escribe, insinúa ni deja entrever la implementación completa del enunciado. Se permiten, como máximo, fragmentos ilustrativos de entrada/salida esperada (texto por consola), no de lógica del programa.
  2. Los enunciados siempre en español. El texto dirigido al estudiante (título, contexto, consigna, ejemplos, aclaraciones) va en español, con ortografía y redacción cuidadas.
  3. Contexto real, complejidad simplificada. Todo enunciado parte de una situación del mundo real, pero recortada a lo esencial para que sea resoluble con los conceptos objetivo. Nunca convertir el ejercicio en un proyecto de ingeniería.
  4. Conceptos explícitos. Cada ejercicio declara qué conceptos de C debe ejercitar. La consigna tiene que poder resolverse usando esos conceptos y no otros innecesarios.
  5. Claridad absoluta. Un enunciado ambiguo es un enunciado roto. Debe quedar claro qué entra, qué sale y qué se espera. Se recomienda incluir un ejemplo.
  6. Identificadores pueden sugerirse en inglés. Los nombres de variables, funciones y tipos sugeridos van en inglés (idioma de facto del código). No es obligatorio imponerlos, pero sí la convención del repositorio.

3. Anatomía de un ejercicio

Todo ejercicio sigue esta plantilla. Los campos marcados como opcionales pueden omitirse cuando aportan poco.

### Ejercicio N.M — [Título corto en español]

**Conceptos** · `concepto-1`, `concepto-2`, `concepto-3`

**Contexto** · Situación real en 1–3 oraciones (qué problema del mundo real motiva el ejercicio).
Aclarar de forma explícita que es una simplificación.

**Consigna** · Qué hay que lograr. Enumerable si tiene varios pasos. Sin ambigüedad.

**Entrada** · Qué recibe el programa (formato, tipo y rango esperado).
**Salida** · Qué debe producir, con el formato esperado.

**Ejemplo** *(opcional)* ·
```
Entrada:  ...
Salida:   ...
```

**Identificadores sugeridos** *(opcional)* · `average`, `studentList`, `MAX_ITEMS`
(En inglés. Se ofrecen como guía, no como obligación.)

**Restricciones / pistas** *(opcional)* · Qué construcciones usar,
qué evitar, casos borde a considerar. NUNCA la lógica de la solución.

**Criterios de aceptación** · Lista verificable de qué debe cumplir una solución correcta.

Regla de oro del ejemplo

El bloque de Ejemplo ilustra entrada y salida (o un caso de uso textual). Jamás muestra cómo se calcula internamente. Está permitido describir con palabras el resultado; está prohibido mostrar el algoritmo.


4. Estructura del libro (archivos)

El libro vive bajo un directorio raíz de contenido. Se propone:

c-programming/
├─ AGENTS.md                        # este archivo (reglas del proyecto)
├─ README.md                        # presentación del libro e índice general
├─ book/                            # FUENTE: capítulos en Markdown
│  ├─ 00-introduccion.md
│  ├─ 01-conceptos-basicos.md
│  ├─ 02-variables-y-tipos.md
│  ├─ 03-operadores-y-expresiones.md
│  ├─ 04-estructuras-de-control.md
│  ├─ 05-funciones.md
│  ├─ 06-arreglos-y-cadenas.md
│  ├─ 07-punteros.md
│  ├─ 08-structs-y-uniones.md
│  ├─ 09-memoria-dinamica.md
│  ├─ 10-archivos.md
│  ├─ 11-estructuras-de-datos.md
│  └─ 12-arenas.md
├─ dist/                            # SALIDA: un PDF por cada capítulo trabajado
│  └─ 12-arenas.pdf
├─ assets/
│  └─ pdf/
│     └─ print.css                  # hoja de estilo canónica de los PDF
└─ .opencode/
   └─ skills/
      └─ book-pdf/SKILL.md          # procedimiento para generar los PDF
  • Un archivo por tema/concepto principal.
  • El README.md mantiene el índice y el enlace a cada capítulo.
  • Nombres de archivo en kebab-case y con prefijo numérico para conservar el orden.
  • El prefijo numérico del archivo se usa también para numerar los ejercicios (### Ejercicio 04.2).

5. Progresión de conceptos

Los ejercicios deben seguir una dificultad creciente. Orden de referencia de los conceptos:

  1. Estructura de un programa, main, #include, compilación.
  2. Variables, tipos primitivos, constantes.
  3. Operadores aritméticos, lógicos y relacionales, precedencia.
  4. Condicionales: if, else, switch.
  5. Bucles: for, while, do-while.
  6. Funciones: parámetros, retorno, alcance, prototipos.
  7. Arreglos y cadenas de caracteres.
  8. Punteros y aritmética de punteros.
  9. struct, typedef, union, enum.
  10. Memoria dinámica: malloc, free, manejo de errores.
  11. Archivos: lectura y escritura con stdio.h.
  12. Estructuras de datos simples (listas, pilas, colas) y algoritmos básicos de ordenamiento/búsqueda.

Un ejercicio puede combinar conceptos de niveles anteriores, pero no debe exigir conceptos de niveles posteriores sin declararlos como objetivo.


6. Convenciones de redacción

  • Tono: docente, claro y motivador. Tratar al lector de "vos" o de forma neutra, de manera consistente dentro de un capítulo.
  • Idioma del texto: español. Términos técnicos del lenguaje pueden quedar en inglés cuando sea lo natural (array, pointer, struct), pero preferir el término en español con el inglés entre paréntesis la primera vez.
  • Identificadores sugeridos: en inglés, lowercase_snake_case o camelCase según se elija por capítulo, pero consistente dentro del mismo.
  • Números de ejercicio: N.M, donde N es el número del capítulo y M el del ejercicio.
  • Extensión: enunciados concisos. Si un ejercicio crece demasiado, dividirlo.
  • Un problema real por ejercicio, con su simplificación aclarada.

7. Estilo didáctico al explicar conceptos ("para tontos")

Los capítulos no solo enuncian ejercicios: también explican los conceptos que el lector necesita. Esa explicación sigue un estilo llano, concreto y progresivo —el mismo que se usó en book/14-entrada-salida-estandar.md—, pensado para que el lector entienda de verdad y no solo lea. Estas reglas aplican a todo capítulo que explique conceptos.

Analogía cotidiana primero. Todo concepto arranca con una comparación del mundo real que el lector ya domina; recién después aparece el término técnico. Ejemplos del capítulo 14: las tres tuberías (stdin/stdout/stderr) son "una fábrica"; getchar es "sacar caramelos de a uno"; el búfer es "el villano de la película". La analogía se sostiene durante toda la explicación; no se abandona a la primera frase.

Títulos con gancho, no etiquetas. En vez de "Introducción a getchar", el título promete algo concreto: "getchar: el caramelito de a uno". Lo mismo vale para las subsecciones.

Explicar el POR QUÉ, no solo el qué. Cada regla llega con su motivo. No alcanza con decir "guardá en int, no en char": hay que explicar por qué (tiene que representar los 256 bytes posibles y un valor extra, EOF).

Voz cercana y frases cortas. Se trata al lector de "vos" (ver sección 6). Párrafos breves, en presente, sin rodeos. Se permite —y se espera— marcar la idea clave con negrita y con MAYÚSCULAS ocasionales.

Cómo estructurar un capítulo largo:

  • Dividirlo en partes con un índice al inicio. La tabla lleva, por cada parte, "la idea en una frase".
  • Después de cada concepto, un bloque de práctica con uno o más ejercicios cortos, antes de avanzar al siguiente concepto.
  • Cerrar con un apartado tipo "lo que te llevás": las ideas clave en pocos bullets, y el puente al capítulo siguiente.

Recursos que se repiten:

  • Apodos para las trampas clásicas: "la trampa N.º 1", "el bug más famoso del principiante", "el villano de la película".
  • Blockquotes (>) para notas, advertencias y "momentos ajá": "Momento ajá", "Ojo con esto", "Para guardar", "Truco de laboratorio". En el PDF todas se dibujan con fondo de color (sección 10).
  • Tablas comparativas para contrastar opciones o señales parecidas (p. ej. EOF vs '\0' vs '\n').
  • Diagramas ASCII para mostrar lo visual: flujos conectados, los dos búferes en serie.
  • Código ilustrativo comentado en lenguaje llano: cada línea que introduce algo nuevo lleva un comentario claro y de varias líneas que dice exactamente qué hace. Los bloques declaran su lenguaje en el fence para que highlight.js los resalte (sección 10).
  • Escenario de prueba en cada ejercicio: un bloque text con la entrada y la salida esperada, para que el lector pueda comprobar su solución.

El límite que NO se cruza. Este estilo permite código ilustrativo para explicar un concepto (una llamada a una función, un esqueleto mínimo, un patrón genérico), pero nunca la solución de un ejercicio. Las reglas no negociables (sección 2) siguen mandando: se entrega el problema; la lógica que resuelve la consigna la escribe el lector. El código de ejemplo sirve para entender una herramienta, jamás para resolver un enunciado del libro.


8. Lo que está prohibido

  • Escribir la solución, total o parcial, del enunciado (incluida la lógica en pseudocódigo).
  • Convertir el ejercicio en un proyecto grande, con build system, múltiples archivos o dependencias externas.
  • Usar bibliotecas que no sean la librería estándar de C, salvo que sea el tema explícito del capítulo.
  • Dejar conceptos de la consigna sin declarar o usar-sin-avisar conceptos fuera del objetivo.
  • Enunciados ambiguos, incompletos o sin criterios de aceptación.
  • Mezclar idiomas dentro de un mismo enunciado (salvo la excepción de identificadores sugeridos).

9. Flujo para agregar contenido

Checklist al crear o editar un ejercicio:

  1. Elegir el capítulo (archivo) y el número de ejercicio.
  2. Declarar los conceptos objetivo.
  3. Redactar el contexto real y aclarar la simplificación.
  4. Escribir la consigna, entrada y salida de forma inequívoca.
  5. Agregar un ejemplo de entrada/salida si aporta claridad.
  6. Sugerir identificadores en inglés.
  7. Añadir criterios de aceptación verificables.
  8. Revisar que no haya código de solución.
  9. Verificar idioma (español), ortografía y consistencia de estilo.
  10. Actualizar el índice del README.md si se agregó un capítulo.

Recordatorio permanente: se entrega el problema, nunca la respuesta.


10. Generación de PDF (dist/)

Cada capítulo trabajado se publica como PDF en dist/, con el mismo nombre que su Markdown: book/12-arenas.md → dist/12-arenas.pdf.

  • Los PDF se generan con el MCP md-to-pdf (herramienta md-to-pdf_markdown_to_pdf). No instalar pandoc/LaTeX ni armar un pipeline propio: ya existe.
  • El diseño es único y compartido: vive en assets/pdf/print.css. No se estiliza capítulo por capítulo.
  • El procedimiento completo y los parámetros fijos de generación están en la skill del proyecto: .opencode/skills/book-pdf/SKILL.md. Hay que seguirla siempre para que todos los PDF tengan el mismo diseño.

Reglas de diseño (resumen):

  • Fuente de código: monoespaciada, distinta de la fuente del cuerpo (serif). Todo bloque de código declara su lenguaje en el fence (```c, ```bash, ```text); así highlight.js aplica resaltado de sintaxis. Un bloque sin lenguaje no se resalta (las trazas de consola van como ```text).
  • Notas / advertencias: se escriben como blockquote (>). En el PDF todas se dibujan igual, con un fondo de color que resalta del blanco de la hoja.
  • Títulos sin huérfanos: un título (h1–h4) nunca puede quedar solo al pie de página: siempre tiene que llevar al menos tres líneas de contenido debajo, en la misma hoja. Si no caben, se fuerza un salto de página antes del título. print.css ya lo aplica (break-after: avoid en los títulos y en el primer párrafo que los sigue, más orphans/widows: 3); no romper esas reglas.
  • printBackground debe estar activo (si no, no se pintan los fondos de código y notas).
  • Encabezado, pie de página y numeración de páginas fijos.

Si se modifica assets/pdf/print.css, hay que regenerar todos los capítulos para que ningún PDF quede con un diseño distinto.


Protocolo de escritura de archivos extensos

Cuando el agente (humano o IA) necesita escribir un archivo Markdown de contenido grande (≥ 600 líneas, como los capítulos del libro), no usar una única llamada a write con todo el contenido. Los herramientas de escritura pasan el contenido dentro de un string JSON y los caracteres especiales (tres backticks ```, $, {, }, \, comillas) pueden romper el parseo.

Enfoque correcto (confirmado en producción)

  1. Escribir con write solo los primeros ~500-600 líneas, hasta la primera sección completa (hasta un --- o final de una parte). El archivo se crea correctamente porque el contenido es manejable para el parser JSON.

  2. Usar edit para ir agregando las secciones restantes. Cada llamada a edit reemplaza una cadena corta (oldString) por otra más larga (newString). La cadena a buscar es siempre muy breve (ej: el último texto del archivo actual) y la cadena de reemplazo incluye la nueva sección.

    oldString: "- [ ] Termina limpiamente al escribir \"exit\"."    ← solo la última línea existente
    newString: "- [ ] Termina limpiamente al escribir \"exit\".\n\n---\n# PARTE 5 — ..."     ← misma + nueva sección
    
  3. Verificar el conteo de líneas con un bash/PowerShell simple después de cada edit grande, para confirmar que la sección se incorporó correctamente:

    Get-Content book\22-file-descriptors.md | Measure-Object -Line
    

Por qué fallaba el enfoque anterior

Un archivo de capítulo tiene ~1200-1500 líneas con:

  • Bloques de código C con backticks triples (```c) que el parser JSON confunde
  • Strings con comillas escapadas (\") que colisionan con las del string JSON
  • Caracteres especiales como $ en ejemplos de shell o \n en strings C

Con chunks de ≤ 600 líneas, el contenido cabe en un string JSON sin romper el parseo.

Regla práctica

Nunca escribir más de 600 líneas de una sola vez con write. Si el contenido total es mayor, usar write para la primera parte y edit sucesivo para el resto.