EL CONTRATO YAML COMO FUENTE DE VERDAD: EL CÓDIGO SE REGENERA, EL CONTRATO NO
En el desarrollo tradicional, la documentación siempre va detrás del código. Se escribe después, se actualiza tarde, y eventualmente miente — porque el código evolucionó y la documentación no. En AAL la relación se invierte: el contrato YAML es la fuente de verdad, el código es una consecuencia del contrato, regenerable en cualquier momento por cualquier LLM que lo reciba. Si el código y el contrato se contradicen, el código está mal.
Stack: YAML · Python · cualquier LLM
Proyectos de referencia: TeliOs · metodología AAL
Objetivo: Hacer el código desechable y el contrato permanente — el riesgo real es perder el YAML, no el código
01. EL PROBLEMA QUE RESUELVE
En el desarrollo tradicional, la única fuente de verdad real termina siendo el código mismo — que es difícil de leer para cualquiera que no lo escribió, y completamente opaco para un LLM que llega sin contexto. El resultado es que cada sesión de trabajo con un LLM empieza desde cero, explicando lo que ya existe.
El contrato YAML elimina ese problema. Define con precisión qué hace cada componente, qué expone, de qué depende, y bajo qué condiciones funciona correctamente. El LLM recibe el contrato y genera el código — no al revés.
// Explicación no técnica
Imagina que construyes muebles. Tienes dos opciones: construir la silla y después intentar dibujar el plano de lo que construiste, o dibujar el plano primero y después construir la silla siguiendo el plano. La primera opción produce planos que siempre están desactualizados. La segunda produce planos que siempre son correctos porque son la fuente de la silla. En AAL, el contrato YAML es el plano. La silla es el código.
02. ANATOMÍA DE UN CONTRATO YAML COMPLETO
Un contrato completo tiene cinco secciones: metadata para identidad y estado, interface para lo que expone, dependencias para lo que necesita, restricciones para los límites no negociables, y tests_aceptacion para la verificación. El contrato de store.js es el ejemplo canónico de TeliOs.
# Contrato de store.js — motor de estado de TeliOs
metadata:
id: TELIO-U001
version: 1.0.0
nombre: 'TeliOs Store — Motor de Estado Global'
tipo: utility
estado: pendiente
descripcion: >
Estado único centralizado del ecosistema TeliOs.
Persiste en localStorage. Notifica cambios via events.js.
Es la única fuente de verdad del sistema.
Máximo 100 líneas. Cero dependencias externas.
lenguaje: JavaScript
archivo: src/store.js
interface:
exports:
getState:
tipo: function
descripcion: 'Retorna el estado completo o una clave anidada'
parametros:
key: { tipo: string, requerido: false,
descripcion: 'Clave con notación de punto: kayros.inicio' }
retorna:
tipo: any
descripcion: 'El valor en la clave, o el estado completo si no se especifica'
setState:
tipo: function
descripcion: 'Actualiza estado, persiste en localStorage, notifica cambios'
parametros:
key: { tipo: string, requerido: true }
value: { tipo: any, requerido: true }
retorna:
tipo: boolean
descripcion: 'true si guardó correctamente, false si localStorage falló'
resetModule:
tipo: function
descripcion: 'Reinicia un módulo a sus valores por defecto'
parametros:
module: { tipo: string, requerido: true }
retorna:
tipo: boolean
dependencias:
internas:
- TELIO-U003 # events.js — notifica cambios con emit('state:changed')
externas: {} # CERO dependencias externas — principio absoluto
restricciones:
calidad:
max_lineas: 100
cobertura_tests: '> 80%'
sin_dependencias: true
performance:
max_tiempo_escritura: '< 10ms'
max_tamanio_estado: '< 5MB'
comportamiento:
debe_notificar: true
debe_persistir: true
fallback_memoria: true
tests_aceptacion:
- id: T001
nombre: 'setState persiste en localStorage'
cuando: "setState('arke.tipoSer', 'fuego')"
entonces:
- "localStorage contiene clave TELIOS_STATE"
- "getState('arke.tipoSer') === 'fuego'"
- "Events recibe emit('state:changed', {key: 'arke.tipoSer', value: 'fuego'})"
- id: T002
nombre: 'getState con clave anidada'
cuando: "setState('kayros.diasTotal', 1096)"
entonces:
- "getState('kayros.diasTotal') === 1096"
- "getState('kayros') es un objeto con diasTotal: 1096"
- id: T003
nombre: 'fallback a memoria cuando localStorage falla'
cuando: 'localStorage.setItem lanza QuotaExceededError'
entonces:
- "setState retorna false"
- "getState sigue funcionando desde memoria"
- "La app no rompe"
notas_implementacion: >
Usar IIFE para encapsular.
No usar clases — módulo funcional puro.
El estado DEFAULT_STATE debe definirse completo al inicio.
Las claves anidadas usan notación de punto: 'kayros.inicio'.
| Sección | Contenido | Para qué sirve |
|---|---|---|
| metadata | ID, versión, tipo, estado, descripción | Identidad única del componente. El LLM sabe qué es y para qué existe. |
| interface | Funciones exportadas, parámetros, retornos | El contrato público — lo que otros módulos pueden llamar. |
| dependencias | Internas (IDs de células), externas (librerías) | Mapa del grafo de dependencias. Detecta ciclos antes de implementar. |
| restricciones | Límites de líneas, performance, comportamiento | Los límites no negociables que el LLM no puede ignorar. |
| tests_aceptacion | Escenarios cuando/entonces | Criterio de éxito objetivo. Si pasan los tests, la célula está correcta. |
03. USAR EL CONTRATO PARA GENERAR EL CÓDIGO
El prompt de implementación en FocOs no describe el problema — entrega el contrato directamente. La instrucción clave es la última: si el contrato y la implementación se contradicen, cambia la implementación. Si el contrato tiene un error, dilo antes de implementar.
PROMPT_IMPLEMENTACION = """
Implementa la célula {id} del ecosistema TeliOs.
CONTRATO:
{contenido_yaml}
REGLAS ABSOLUTAS:
1. Máximo {max_lineas} líneas
2. Cero dependencias externas
3. Implementar EXACTAMENTE lo definido en interface.exports
4. Incluir los tests de aceptación como comentarios // TEST: al final
5. JSDoc en cada función exportada
El contrato es la verdad.
Si el contrato y tu implementación se contradicen — cambia la implementación.
Si el contrato tiene un error — dímelo antes de implementar.
"""
04. REGENERAR UNA CÉLULA DESDE EL CONTRATO
Este es el caso de uso que justifica toda la metodología. El código se perdió o se corrompió — pero el contrato YAML existe en el repo. Eso es suficiente para recuperarlo completamente en 15 minutos. Sin el contrato, la misma operación toma horas reconstruyendo desde memoria o desde código roto.
# El contrato YAML existe — eso es suficiente para regenerar
# Flujo de recuperación:
# 1. Abrir TELIO-U001.contract.yaml
# 2. Pegar el contenido en el prompt de implementación
# 3. El LLM genera store.js desde cero — conforme al contrato
# 4. Verificar los tests de aceptación T001, T002, T003
# 5. Si pasan — célula regenerada. Si no — el LLM itera.
# Tiempo total con contrato: 10-15 minutos
# Tiempo total sin contrato: horas o días
Un archivo YAML de 80 líneas en texto plano commiteado en Git es prácticamente imposible de perder. El riesgo en AAL se desplaza por completo: ya no es perder código — es perder el contrato. Y el contrato es mucho más fácil de proteger que el código.
-- CONCLUSION
El contrato YAML como fuente de verdad resuelve el problema más profundo del desarrollo con LLMs: la fragilidad de la base de conocimiento. Si el contrato existe, el código puede perderse, corromperse o quedar obsoleto sin consecuencias permanentes. El LLM puede regenerarlo en 15 minutos. Esto cambia la naturaleza del riesgo en el desarrollo — el riesgo ya no es perder código, es perder el contrato. Y eso es mucho más difícil.
> SYSTEM_READY > NODE_ONLINE