Agentic development: cómo evoluciona un harness

Un repo que trabaja con agentes también tiene que mejorar con el uso. Esta página explica cómo cambia este boilerplate: qué se edita cuando una sesión aprende algo, cómo se comprueba que el cambio no rompió nada y cómo llega ese cambio a los proyectos que lo consumen.

FundamentosSkillsEvalsUpdaterADR

La skill como unidad de cambio

En un proyecto de software normal, lo que cambia es el código. En un harness agéntico cambia también la forma en que el agente trabaja, y esa forma vive en texto: instrucciones, referencias, tablas de gotchas. En este repo ese texto está organizado en skills, una carpeta por flujo de trabajo bajo .agents/skills/. Cada skill tiene un SKILL.md con su frontmatter (nombre, descripción que el harness usa para activarla, metadata.kind) y una carpeta references/ con el detalle que se carga solo cuando hace falta.

Tratar la skill como unidad de cambio tiene una consecuencia práctica. Una lección mal escrita en una skill se carga en todas las sesiones futuras que la activen, se copia a los briefings de cada subagente a través del registry y, si la skill viene de upstream, viaja a cada proyecto consumidor en el próximo update. Un recuerdo equivocado en la memoria de una sesión se olvida. Una regla equivocada en una skill se distribuye. Por eso el repo pone más filtros en el camino hacia una skill que en el camino hacia una nota.

Tampoco todo lo que una sesión aprende merece estar en una skill. El protocolo de refinamiento exige cuatro condiciones a la vez: que la lección siga siendo cierta el próximo sprint, que ningún comando pueda regenerarla desde una fuente de verdad, que cambie lo que el agente hace la próxima vez y que esté pagada con una fecha, una sesión y algo medido. Si falla alguna, va a la memoria de sesión (Engram) o a .context/, donde un comando la vuelve a generar.

El bucle de mejora

El recorrido completo tiene ocho pasos. Empieza con una fricción concreta en una sesión real y termina con esa misma fricción resuelta en un proyecto que nunca la vio. La mitad inferior del dibujo ocurre fuera de este repo, en los proyectos que se crearon a partir de él.

El bucle de mejora de un harness agéntico Ocho pasos en ciclo. Arriba, en el repo upstream: una fricción en una sesión, la propuesta en refinements.md, el OK humano por entrada y la edición de la skill con sus gates. Abajo, de derecha a izquierda: el commit en upstream, bun sync con el reporte de paridad, el proyecto consumidor y el issue skill-feedback que vuelve al principio. Repo upstream (este boilerplate) Proyectos consumidores 1. Fricción en una sesión real 2. Propuesta refinements.md 3. OK humano apply / drop por entrada 4. Edición + gates skills:check, evals 5. Commit upstream ADR si es arquitectura 6. bun sync sync + reporte de paridad 7. Proyecto usa la skill nueva 8. Feedback issue skill-feedback
Los pasos 1 a 5 ocurren en el boilerplate. Del 6 al 8 ocurren en cada proyecto consumidor, y la flecha del 8 al 1 cruza de vuelta la línea punteada.

Lo que el dibujo no muestra es dónde se frena cada paso. Una sesión nunca edita una skill en caliente: escribe una propuesta en su propia carpeta de sesión y guarda la misma lección en Engram por si esa carpeta se borra. El dueño del repo lee las propuestas y decide entrada por entrada. Una propuesta sin medición se descarta en esa revisión, aunque suene razonable.

Cómo se mide un cambio

Medir una skill tiene dos preguntas distintas. La primera es si se activa cuando debe y se queda quieta cuando no. La segunda es si, una vez activa, el agente hace lo correcto. Este repo cubre bien la estructura alrededor de ambas y tiene la segunda todavía abierta, y conviene saberlo antes de fiarse de un check verde.

Evals de activación
Las skills con evals/evals.json traen casos positivos y negativos: un prompt, si la skill debería activarse y qué comportamiento se espera. bun run skills:evals los descubre, los cuenta y valida su forma (JSON válido, prompt no vacío, polaridad declarada, ids únicos, la skill esperada existe). No invoca ningún modelo, así que un resultado verde solo dice que los casos están bien escritos. Si la skill se activa de verdad con esos prompts sigue sin medirse, y el propio script lo deja anotado como trabajo pendiente.
Gates estáticos
bun run skills:check ejecuta el lint de skills: frontmatter, vocabulario de metadata.kind, rutas citadas que ya no existen, secciones obligatorias según el tipo de skill. Forma parte de bun run repo:check junto con los tipos, el lint, el contrato de compatibilidad entre harnesses y el manifiesto KATA.
Registry
bun run skills:registry reconstruye .agents/skills/REGISTRY.md, que reúne las compact rules de cada skill. Los subagentes reciben esas reglas en su briefing en lugar de leer el SKILL.md entero. Si alguien edita una regla y olvida regenerar, skills:registry:check lo detecta en el commit.

La guía de Anthropic sobre autoría de skills recomienda escribir las evaluaciones antes que la documentación y medir contra una línea base sin la skill. Este repo tiene la mitad estructural de ese consejo automatizada en CI (skills:evals corre en .github/workflows/build.yml) y la mitad que exige un modelo real queda para cuando haya un grader conectado.

Cómo llega a los proyectos consumidores

Un proyecto creado desde este boilerplate recibe las mejoras con bun sync, que ejecuta cli/update-boilerplate.ts. El updater sincroniza por componentes y nunca pisa los archivos que son identidad del proyecto: AGENTS.md, .agents/instructions/agent-project.md, las configuraciones de MCP de cada harness, los hooks de husky, .agents/project.yaml y cualquier ruta que el proyecto declare en updater.protected_paths. Corre solo en el checkout principal: en un worktree se niega, porque sus backups y marcadores morirían con él (ver Worktrees).

Primero pregunta y después escribe: las áreas, los archivos de cada área (cada fila con su "Ver cambios"), los borrados y las claves nuevas de package.json se responden antes de tocar el primer archivo, y luego todo se aplica en un solo paso. Un archivo sincronizado que el proyecto editó y upstream también cambió también es una pregunta: en una corrida interactiva eliges conservar el tuyo, tomar el nuevo o decidir después (con --auto se sobrescribe y el original queda en .backups/). En una terminal con pantalla la corrida se ve en una página local con cada pregunta como tarjeta, mientras la terminal conserva el log completo; --headless lo deja todo en la terminal (bun sync --help).

Cuando upstream y el proyecto no coinciden en un archivo protegido, el updater no decide solo. Cierra con una tabla por superficie y un único prompt de paridad, que guarda en un archivo de un solo uso (parity-plan.md, ignorado por git) dentro del proyecto. La misma tabla sale en la tarjeta de reporte de la página y en la terminal. Cada fila trae su evidencia (encabezados, claves, servidores MCP) y pide una decisión: conservar la versión del proyecto, tomar la de upstream o fusionar. El agente presenta la tabla, espera la respuesta fila por fila y solo aplica lo elegido. Después vuelve a correr tests, tipos y lint.

El camino de vuelta también está escrito. Si en un proyecto consumidor una skill de upstream falla, la sesión no la edita ahí, porque el siguiente update que toque ese archivo la pondría a elegir entre perder el arreglo o dejar de recibir los de upstream. Redacta un issue con la plantilla skill-feedback, le quita las claves de Jira y los hosts del proyecto, y lo muestra al dueño. Solo con su OK se publica con gh issue create, y después se verifica leyendo el issue de vuelta.

Decisiones que no se re-discuten: ADRs

Algunas decisiones cuestan mucho de revertir: el runner de tests, el modelo de fixtures, cómo se aíslan los datos, cómo se autentican los tests. Si quedan solo en un plan archivado, la próxima sesión las vuelve a discutir o las rompe sin saberlo. Para eso existen los Architecture Decision Records en .context/ADR/, con el formato que popularizó Michael Nygard: contexto, decisión, alternativas descartadas y consecuencias.

La doctrina del repo pide que la decisión pase dos filtros antes de merecer un ADR: que sea arquitectura de tests y que sea difícil de revertir. Un fix de un test flaky o el nombre de un spec no califican. Los ADR son append-only, así que una decisión nueva reemplaza a la vieja con un ADR que la marca como superseded, y nadie borra la anterior.

Así lo hace este repo

Pieza Dónde vive Qué hace
Pipeline de cambios al framework .agents/skills/framework-development/SKILL.md Plan, Code, Verify y Archive. Verify corre en paralelo test, types:check, lint:check y skills:check; si falla uno, no hay archivo ni commit.
Contrato de una skill nueva .agents/skills/agentic-qa-core/references/skill-scaffold.md Frontmatter obligatorio, secciones por tipo (context, workflow, utility, core) y el formato medido de references/gotchas.md.
Propuestas de refinamiento .agents/skills/agentic-qa-core/references/skill-refinement-protocol.md Las cuatro condiciones, el esquema de cada bloque de propuesta y la matriz de dónde se aplica según quién es dueño de la skill.
Feedback hacia upstream .agents/skills/agentic-qa-core/references/upstream-feedback.md Resolución del repo destino, redacción del borrador, OK del dueño y verificación.
Runner de evals scripts/run-skill-evals.ts (bun run skills:evals) Validación estructural de los casos de activación. No llama a ningún modelo.
Lint de skills y registry scripts/lint-skills.ts, scripts/build-skill-registry.ts skills:check, skills:registry y skills:registry:check.
Updater con paridad cli/update-boilerplate.ts, cli/lib/updater-parity.ts Sync por componentes, tabla por superficie y prompt de paridad.
Doctrina de ADR .agents/skills/agentic-qa-core/references/adr-doctrine.md Los dos filtros, la regla de promoción desde un plan y el procedimiento de autoría. La plantilla vive en .context/ADR/README.md.

Las decisiones registradas están en .context/ADR/; el README.md de esa carpeta las indexa y trae la plantilla ADR-NNNN-template.md.

Errores comunes

Lo que más se repite

Editar una skill de upstream dentro de un proyecto consumidor. Funciona hasta el próximo bun sync que traiga cambios de upstream en ese archivo: te obliga a elegir entre tu versión y la nueva, y si tomas la nueva (o corres con --auto) la sobrescribe y deja una copia en .backups/. Abre un issue skill-feedback, o declara la ruta en updater.protected_paths sabiendo que dejas de recibir los arreglos de ese archivo.

Leer skills:evals en verde como prueba de que las skills se activan bien. Solo valida la forma de los casos.

Guardar en una skill un dato que un comando puede regenerar, como un endpoint o un nombre de estado de Jira. Se queda viejo en silencio. Ese dato va en .context/.

Aceptar "take upstream" en una fila de paridad que menciona claves o servidores que solo tiene el proyecto. Esa opción borra contenido del proyecto; en esos casos la fila sugiere fusionar.

Editar una compact rule y no regenerar el registry. Los subagentes siguen recibiendo la regla anterior hasta que alguien corra bun run skills:registry.

Para profundizar