LLM y OpenSpec: Mejores Practicas Completas
LLM y OpenSpec: Mejores Practicas Completas
Este capitulo cubre las mejores practicas para trabajar con LLMs usando el perfil Core de OpenSpec (comandos: /opsx:propose, /opsx:explore, /opsx:apply, /opsx:archive).
Gestion de contexto: la practica mas critica
Cuando la ventana de contexto del LLM supera el ~40% de uso, el rendimiento cae: logica fragmentada, regresiones de codigo y alucinaciones. OpenSpec resuelve esto con una estrategia diff-based, pero necesitas cooperar.
Una sesion por change
Cada change de OpenSpec debe trabajarse en una sesion limpia del LLM. No arrastres contexto de cambios anteriores. El flujo ideal:
- Abrir sesion nueva
- El LLM lee solo:
config.yaml+tasks.mddel change + specs relevantes - Implementar las tareas con
/opsx:apply - Archivar con
/opsx:archivey cerrar sesion
Carga bajo demanda
El LLM no necesita leer todo tu codebase. Solo carga:
| Siempre | Solo si es necesario |
|---|---|
openspec/config.yaml (contexto del proyecto) | Specs de areas afectadas |
tasks.md del change actual | Codigo fuente relevante |
proposal.md del change | Delta specs de changes paralelos |
Cuando el LLM ignora las specs
Si el modelo empieza a generar codigo que contradice tus especificaciones:
openspec update # regenera instrucciones AI y slash commands del proyecto
Este comando actualiza las instrucciones que el LLM usa para seguir tu workflow. Ejecutalo despues de modificar config.yaml o actualizar OpenSpec.
Escribir specs efectivos
Palabras clave RFC 2119
Usa terminologia formal para que los requisitos sean inequivocos:
| Palabra | Significado |
|---|---|
MUST / SHALL | Requisito absoluto, no negociable |
SHOULD | Recomendado, puede omitirse con justificacion |
MAY | Completamente opcional |
REQ-001: El sistema MUST validar el token JWT en cada request autenticado.
REQ-002: El sistema SHOULD cachear tokens validados por 5 minutos.
REQ-003: El sistema MAY aceptar tokens de refresh como alternativa.
Formato de escenarios
Usa exactamente 4 hashtags (####) para escenarios Given/When/Then. Con 3 o menos, la validacion falla:
#### Scenario: Usuario con token expirado
Given un usuario con token JWT expirado
When hace un request a un endpoint protegido
Then recibe 401 Unauthorized con mensaje descriptivo
Todo requisito MUST tener al menos un escenario o la validacion rechaza el spec.
Delta specs: la regla de MODIFIED
Al modificar un requisito existente, copia el bloque completo del requisito (desde ### Requirement: hasta todos sus escenarios) y editalo bajo ## MODIFIED Requirements. Si solo pones texto parcial, se pierden datos al archivar:
## MODIFIED Requirements
### Requirement: User Login
The login MUST require email, password and 2FA code when enabled.
(Previously: email and password only)
#### Scenario: Login with 2FA enabled
- GIVEN a user with 2FA enabled
- WHEN the user submits valid credentials
- THEN an OTP challenge is presented
- AND login completes only after valid OTP
El header ### Requirement: debe coincidir exactamente con el del spec original. Si omites el contenido completo, /opsx:archive no puede hacer el merge correctamente.
Principio de simplicidad
OpenSpec promueve una regla explicita:
Default to <100 lineas de codigo nuevo. Single-file implementations until proven insufficient.
Solo agrega complejidad cuando tengas datos reales que la justifiquen (>1000 usuarios, metricas de performance concretas, requisitos de escala medibles). Tres lineas similares de codigo son mejores que una abstraccion prematura.
Convenciones de nombrado
Los changes usan kebab-case con prefijo verbal:
| Prefijo | Uso | Ejemplo |
|---|---|---|
add- | Feature nueva | add-two-factor-auth |
update- | Modificar existente | update-login-flow |
remove- | Eliminar funcionalidad | remove-legacy-api |
refactor- | Reestructurar sin cambiar comportamiento | refactor-user-service |
fix- | Corregir bug | fix-token-expiration |
Verificar antes de archivar
Antes de ejecutar /opsx:archive, verifica manualmente tres dimensiones:
- Completeness: todas las tareas del checklist completadas, todos los requisitos implementados
- Correctness: la implementacion coincide con la intencion del spec (no solo que compile)
- Coherence: las decisiones de
design.mdestan reflejadas en el codigo final
/opsx:archive incluye validaciones internas, pero la revision humana sigue siendo necesaria. Si algo no cuadra, corrige antes de archivar.
config.yaml exhaustivo
El campo context de config.yaml es la brujula del LLM. Mientras mas preciso sea, menos alucina el modelo:
# openspec/config.yaml
schema: spec-driven
context: |
## Stack
- TypeScript 5.4, React 18.3, Hono 4.2
- PostgreSQL 16 con Drizzle ORM
- Deploy en Cloudflare Workers
## Convenciones
- Arquitectura hexagonal: domain/ → application/ → infrastructure/
- Validacion con zod en boundaries
- Tests con vitest
## Decisiones de diseno
- JWT sin refresh token (sesiones cortas de 1h)
- Rate limiting en API gateway, no en la app
rules:
proposal:
- Incluir versiones exactas de dependencias afectadas
- Identificar equipos afectados
Importante: El campo
rulespor artifact es un array de strings, no un string multilinea. Cada regla es un item de la lista. Si usas|(string multilinea), OpenSpec las ignora silenciosamente con el error: “Rules for ‘X’ must be an array of strings, ignoring this artifact’s rules”.
IDs validos de artifacts: Para el schema
spec-driven, los IDs son:proposal,specs(plural),design,tasks. Si usasspec(singular) u otro nombre incorrecto, las rules no se inyectan: “Unknown artifact ID in rules”.
Incluir versiones exactas evita que el modelo asuma APIs deprecated o patrones obsoletos. El campo context se inyecta en todos los artifacts que genera OpenSpec.
Verificar contra la realidad: Nunca escribas versiones de memoria. Consulta
package.json,go.mod,Cargo.tomlo el lock file real de tu proyecto. Si el context dice “React 18” pero tu package.json tiene React 19, el modelo generara codigo para la API equivocada — exactamente el problema que esta seccion intenta prevenir.
Errores comunes
| Error | Causa | Solucion |
|---|---|---|
| ”Change must have at least one delta” | No existe changes/[name]/specs/ con archivos .md | Crear la carpeta de specs en el change |
| ”Requirement must have at least one scenario” | Usar ### en lugar de #### para escenarios | Usar exactamente 4 hashtags |
| ”Incomplete MODIFIED sections” | No copiar el bloque ### Requirement: completo con todos sus escenarios | Copiar el bloque entero desde ### Requirement: hasta el ultimo escenario y editarlo |
| ”Rules must be an array of strings” | Usar | (string multilinea) en vez de array | Cambiar a formato - item por cada regla |
| ”Unknown artifact ID in rules” | Usar spec (singular) en vez de specs (plural) | IDs validos: proposal, specs, design, tasks |
| Versiones del stack incorrectas en context | Escribir versiones de memoria sin verificar | Consultar package.json/go.mod antes de escribir el context |
| Modelo ignora las specs | Instrucciones AI desactualizadas | Ejecutar openspec update |
| Codigo generado contradice config.yaml | Ventana de contexto saturada | Abrir sesion nueva, cargar solo lo necesario |
LLM como auditor sistematico
El problema
Tienes un proyecto funcional pero sabes que hay deuda tecnica: archivos grandes, funciones sin validacion, tests inexistentes, secretos hardcodeados. La revision manual es lenta e inconsistente. Un LLM puede analizar tu codebase completo — pero solo con instrucciones concretas.
La estrategia: 3 fases
| Fase | Accion | Resultado |
|---|---|---|
| 1. Auditar | El LLM analiza contra criterios definidos | Lista priorizada de problemas |
| 2. Planificar | Cada problema se convierte en un change | Propuestas con alcance acotado |
| 3. Aplicar | Se implementa cada change con /opsx:apply | Codigo mejorado y archivado |
Definir criterios de auditoria
Crea openspec/audit-criteria.md con criterios concretos:
# Criterios de Auditoria
## Estructura y organizacion
- [ ] Ningun archivo supera 150 lineas de codigo
- [ ] Funciones con menos de 30 lineas
- [ ] Separacion clara entre negocio, presentacion e infraestructura
## Seguridad
- [ ] Inputs validados con schema (zod, valibot)
- [ ] Sin secretos hardcodeados
- [ ] Variables sensibles en .env
## Testing
- [ ] Modulos criticos con tests unitarios
- [ ] Endpoints de API con tests de integracion
## Performance
- [ ] Sin queries N+1
- [ ] Lazy loading donde aplique
## Mantenibilidad
- [ ] Tipos definidos para interfaces publicas
- [ ] Sin any innecesarios
- [ ] Codigo muerto eliminado
Adapta los criterios a tu stack: agrega secciones especificas para frontend (accesibilidad, estado global), backend (rate limiting, logging) o base de datos (migraciones, indices).
Ejecutar la auditoria
Via explore:
/opsx:explore
Analiza el proyecto contra openspec/audit-criteria.md.
Para cada criterio: CUMPLE o NO CUMPLE, archivos afectados, severidad.
No propongas soluciones, solo diagnostica.
Via config.yaml (auditoria automatica en cada propuesta):
rules:
proposal:
- Incluir seccion "Hallazgos de auditoria" con problemas detectados en el area del cambio
- Priorizar hallazgos: critico > importante > menor
Convertir hallazgos en changes
/opsx:propose fix-hardcoded-secrets # CRITICO
/opsx:propose add-input-validation # CRITICO
/opsx:propose refactor-large-files # IMPORTANTE
/opsx:propose add-core-tests # IMPORTANTE
Orden de implementacion
- Seguridad critica (secretos, inyecciones) — riesgo real
- Configuracion (.env, linter, formatter) — base para el resto
- Estructura (dividir archivos, separar responsabilidades) — facilita tests
- Testing (unitarios e integracion) — safety net para refactoring
- Performance (queries, cache, lazy loading) — optimizar lo que funciona
- Mantenibilidad (tipos, imports, codigo muerto) — polish final
Automatizar auditorias periodicas
# config.yaml
rules:
tasks:
- "Al final de cada lista de tareas, incluir un check de auditoria"
- "Verificar que los cambios no introducen archivos > 150 lineas"
- "Verificar que no hay inputs sin validar"
Resumen
- Contexto limpio: una sesion por change, carga bajo demanda, umbral del 40%
- Specs efectivos: RFC 2119 (MUST/SHOULD/MAY), escenarios con
####, delta specs completos - Simplicidad: <100 lineas nuevas por defecto, single-file hasta que se demuestre insuficiente
- Verificar antes de archivar: completeness + correctness + coherence
- config.yaml preciso: versiones exactas, convenciones, decisiones de diseno
- Nombrado consistente: kebab-case con prefijo verbal (add-, update-, fix-, refactor-)
- Auditoria sistematica: criterios concretos → diagnostico → changes priorizados
- Automatizar: rules en config.yaml para calidad continua