Guía
Cómo aplicar Context Architecture a un codebase existente
Context Architecture se aplica a un codebase que ya existe, reordenándolo de a poco, nunca armando uno nuevo desde cero. Lees el repo como alguien sin contexto, arreglas la documentación que miente y respaldas cada afirmación que el repo hace sobre sí mismo con un check que falla cuando esa afirmación deja de ser verdad.
Un repo parte limpio y crece tres años. Las convenciones se separan. Los docs dejan de calzar con el código. Los nombres de las carpetas te dicen qué framework armó la cosa, no qué hace la cosa.
Ahora pásaselo a un lector sin memoria: alguien en su primer día, o un agente de IA arrancado en frío. Pídele un cambio. No puede saber qué significa nada, dónde va el cambio, ni cuál de dos patrones que conviven es el actual. El repo creció. Nadie lo diseñó para que se pudiera leer.
Ese es el problema que esto arregla. La especificación dice qué es Context Architecture y por qué. Esta página es la parte que haces con las manos: cómo aplicarla a un repo que ya tienes.
El "ya tienes" importa. Un proyecto nuevo parte con la estructura que le da su framework, y este problema todavía no existe. Aparece después, cuando el código crece más allá de lo que una persona mantiene en la cabeza. Así que esto no es una forma de empezar un proyecto. Es una forma de arreglar uno. No estás construyendo una ciudad nueva, le estás poniendo nombres a las calles de una que ya se desparramó.
Antes de empezar: ¿vale la pena?
Tiene un costo real. La reorganización inicial, los checks que son código que tienes que mantener en verde, y un pequeño impuesto en cada pull request para que cada afirmación quede atada a un check.
Se paga en proporción a cuánto trabajo de agentes o de varias personas absorbe el repo. Vale la pena en un codebase que aguanta refactors, migraciones, features con spec, contribuciones de agentes. No vale la pena en un prototipo desechable ni en un problema que todavía no entiendes. Ahí el impuesto cuesta más de lo que devuelve, y saltártelo es lo correcto. Decirlo en voz alta es parte de la disciplina.
El orden de operaciones
Hazlo de a poco. No detienes todo para reorganizar de una. Aterrizas un cambio acotado y reversible a la vez, y cada uno llega con el check que mantiene honesta su afirmación. Nada de reescribir todo de golpe.
El orden va de lo más barato y seguro a lo más caro:
- Lee el repo como un lector en frío, y nombra los modos de falla con los que choques.
- Arregla los docs que mienten.
- Pon
AGENTS.mden las fronteras de arriba. - Convierte el comentario que más repites en review en una regla de lint.
- Desarma una carpeta cajón de sastre.
- Haz que las capacidades se encuentren.
- Avanza hacia una estructura por dominio, al final, y solo si se gana el costo de mover todo.
- Conecta el bucle que evita que se vuelva a pudrir.
El resto de la guía es un paso por sección, y después un ejemplo completo.
Paso 1: auditar el repo como un lector en frío
Abre el repo como si nunca lo hubieras visto y no recordaras nada. Lee el árbol de primer nivel, luego las fronteras, luego un puñado de archivos hoja. En cada nivel, una pregunta: ¿podría hacer un cambio correcto acá sin preguntarle a nadie? Cada "no" es un defecto que acabas de encontrar.
Los defectos vienen en cinco formas. Ninguno es culpa del modelo, y por eso un modelo mejor o un prompt más astuto no arregla ninguno:
- Reimplementación. La fuente de verdad no se podía encontrar, así que el lector reconstruye lo que ya existe.
- Estructura inventada. No se impuso ninguna, así que el lector impone la suya.
- Obediencia a docs falsos. Cita archivos borrados o contradice el código actual, con total confianza.
- Propagación de patrón obsoleto. Copia el patrón más ruidoso aunque ese patrón esté muerto.
- Cara o sello con la ambigüedad. Dos convenciones conviven, así que usa la que leyó primero.
Anota, por principio, un veredicto y la evidencia. Hazlo a mano, o carga el skill de Context Architecture en tu agente y deja que escriba el informe.
Cómo se ve esto. En un servicio de pagos, la primera pasada encuentra la lógica de reembolsos
repartida en tres carpetas (una reimplementación esperando para ocurrir), un README que apunta a un
script de deploy borrado hace meses (docs falsos) y dos helpers de fecha con firmas distintas (un cara
o sello). Tres modos de falla nombrados antes de tocar una línea.
Paso 2: arreglar el context-rot primero
Parte por hacer que los docs dejen de mentir. Un doc que cita un archivo borrado o contradice el código es peor que no tener doc, porque un lector con confianza hace lo que dice.
Encuéntralo a mano o con un script: saca cada ruta de archivo, comando, símbolo y enlace de tu
README, tus archivos AGENTS.md y CLAUDE.md, y tus documentos de diseño, y verifica que cada uno
siga existiendo o siga corriendo. Arregla cada mentira contra lo que el código realmente hace hoy.
Después haz que el rot sea imposible de traer de vuelta. Agrega un test que afirme que cada ruta que los docs citan sigue existiendo en disco. Ahora "este doc es preciso" es una afirmación con un check detrás, en vez de un deseo.
Cómo se ve esto. El README documenta un deploy.sh que se borró hace un año. Sacas la referencia
muerta, escribes el comando real y agregas ese test de rutas. La próxima vez que alguien mueva un
archivo por debajo de un doc, la suite se pone roja en el mismo pull request, no en producción seis
semanas después.
Paso 3: poner AGENTS.md en las fronteras de arriba
El contexto va junto al código que describe, en cada frontera que es dueña de algo. Puesto ahí,
envejece al mismo ritmo que el código y lo lee el mismo agente que está por editarlo. Empieza por la
raíz y los dos o tres directorios de más tráfico. Ahí cada AGENTS.md compra la mayor legibilidad.
Escribe solo lo que no puedes sacar leyendo el código: la fuente de verdad, los invariantes, la deuda técnica que aceptaste a propósito, y el razonamiento que un spec dejó atrás. Mantén cada uno corto.
# AGENTS.md (billing)
Dueño de la facturación, los reembolsos y el calendario de cobranza.
## Fuente de verdad
Los precios vienen del paquete `pricing-engine`, nunca hardcodeados acá.
## Invariantes
- Un reembolso nunca excede el monto capturado. Lo hace cumplir `refunds/guard.test.ts`.
- Todo el dinero es enteros en centavos, sin floats. Lo hace cumplir la regla lint `no-float-money`.
## Deuda técnica aceptada
La ruta legacy `chargeV1` se queda hasta la migración 2026-Q3. No la extiendas.
Mira los invariantes: cada uno nombra el check que lo hace cumplir. Ese es todo el punto. Un invariante sin nada detrás es solo una línea nueva que se puede pudrir. Si el check todavía no existe, escríbelo en el mismo cambio, o redacta la línea como un hueco conocido, no como una garantía.
Paso 4: codificar la convención más repetida
Toma el comentario que más dejas en review, el que vive solo en la cabeza de tu equipo, y ponlo en la cadena de herramientas. Una convención que un agente no puede leer es una convención que va a romper, siempre.
Este es el movimiento en el que se apoyan los demás pasos. Cuando una afirmación tiene que sostenerse, así se sostiene: una regla de lint que enuncia la convención y falla en el mismo lugar, o un tipo que hace que lo incorrecto no compile.
Cómo se ve esto. El comentario que más dejas es "importa desde la raíz del paquete, no rutas profundas". Hoy vive en la cabeza de quienes revisan, así que un agente lo rompe en su primer commit.
# antes: una convención que vive en la cabeza de quienes revisan
"siempre importar desde la raíz del paquete, nunca rutas profundas"
# después: la convención, escrita y exigida
.oxlintrc.json # una regla no-restricted-imports que falla la ruta profunda en CI
Una vez que la regla está en el linter, la ruta profunda falla al toque, con un mensaje que cita la regla, no a quien revisó y justo estaba prestando atención ese día.
Paso 5: nombrar una frontera de cajón de sastre
utils/, common/, helpers/, core/, lib/. Acá es donde la responsabilidad va a morir. Nada en el
nombre frena al código no relacionado, así que la carpeta crece para siempre. Elige la peor y divídela
en carpetas cuyos nombres digan, cada uno, de qué son dueñas.
# antes
src/utils/ # 40 archivos no relacionados
# después
src/pricing/ # la matemática de precios que estaba escondida en utils
src/auth-session/ # los helpers de sesión que estaban escondidos en utils
src/shared/ # lo que es genuinamente genérico, chico y sin dependencias
El nombre está haciendo el trabajo. Una carpeta llamada pricing resiste el código que no es sobre
pricing, porque deja de calzar. Si no puedes nombrar una frontera con precisión, la frontera está mal, y
shared no es la respuesta. Un shared/ chiquito para un formateador de fechas o un tipo result está
bien. La deuda es echar mano del nombre genérico para esquivar la pregunta de dónde va algo.
Paso 6: hacer las capacidades descubribles
Una capacidad que un agente no puede encontrar es, para ese agente, una capacidad que no existe.
Simplemente la rehace, o la salta. Mueve tus scripts, generadores y comandos a lugares predecibles y
nombrados, y nómbralos por lo que hacen: scripts de package.json, un directorio scripts/ o
skills/, comandos que de verdad escribiste.
Mejor todavía, genera la lista de capacidades a partir de esas rutas convencionales en vez de mantenerla a mano, y testea que la lista esté completa. Una lista mantenida a mano es una afirmación más esperando para pudrirse.
Cómo se ve esto. Tres scripts de deploy y de seed viven en el directorio personal de un ingeniero y
un hilo de Slack que nadie encuentra. Los mueves a scripts/ con nombres que dicen qué hacen y los
listas en package.json. El siguiente agente los encuentra donde mira primero, en vez de escribir un
cuarto.
Paso 7: avanzar hacia una estructura por dominio (al final)
El primer nivel debería decir qué hace el sistema, no qué framework lo armó: billing/, onboarding/,
payments/, no controllers/, services/, utils/. El framework vive un nivel más abajo, dentro del
dominio al que sirve.
Este es el movimiento caro y el más propenso a romper imports, así que va al final y va en tajadas. A
menudo un movimiento parcial más un AGENTS.md en la raíz que explica la estructura hacia la que migras
compra más legibilidad, por archivo movido, que reorganizar todo de una.
# antes: organizado por capa técnica
src/
controllers/ services/ models/ utils/
# después: organizado por dominio, el framework un nivel más abajo
src/
billing/
controllers/ services/ models/ # el framework, dentro del dominio al que sirve
onboarding/
payments/
Evita que se devuelva con una regla de lint que impide que el código de dominio se filtre a una carpeta
de capa, y mantén la estructura objetivo en el AGENTS.md raíz para que un lector que cae a mitad de la
migración sepa hacia dónde es adelante.
Paso 8: instalar el metabolismo
La versión madura no solo revisa el contexto, lo alimenta. Un repo que se revisa a sí mismo no puede pudrirse en silencio. Un repo que se alimenta a sí mismo absorbe conocimiento nuevo en el momento en que se crea.
Una línea en el AGENTS.md raíz y en la checklist de review lo logra: cuando un pull request agrega una
fuente de verdad o un invariante, lo documenta en ese mismo pull request, con un check detrás. Ahora el
contexto crece con el sistema en vez de ir seis meses atrás.
Un ejemplo completo, de principio a fin
Un servicio que empezó como una app de un framework y creció tres años. El árbol grita el framework, no
el producto, y el único doc es un README que está medio equivocado.
# antes
src/
controllers/ # 22 archivos, dominios mezclados
services/ # 18 archivos, dominios mezclados
models/
utils/ # el cajón de sastre
helpers/ # un segundo cajón de sastre
README.md # apunta a un script de deploy borrado el año pasado
Pídele a un agente "agregar un flujo de reembolso parcial" acá y míralo chocar con tres de los cinco
modos de falla en una sola tarea: no encuentra dónde viven los reembolsos (repartidos entre
controllers/, services/, models/), rehace matemática de dinero que ya está en utils/, y sigue el
README hacia un script de deploy que ya no está.
El arreglo, en el orden de arriba, sin un solo commit de golpe:
- Context-rot. Saca la referencia muerta al deploy del
README, escribe el comando real, agrega un test de que cada ruta que elREADMEy losAGENTS.mdcitan sigue existiendo. - Contexto embebido. Un
AGENTS.mdraíz (qué posee el servicio, la estructura hacia la que migra) y uno en el área de más tráfico. - Codificar. El comentario de review más repetido era "el dinero es enteros en centavos". Eso pasa a
ser una regla lint
no-float-money. - Nombrar. Divide
utils/yhelpers/: la matemática de dinero pasa amoney/, el código de sesión aauth-session/, el resto genuinamente genérico se queda en unshared/chico. - Descubrible. Los scripts ad-hoc se mueven a
scripts/con nombres reales, listados enpackage.json. - Por dominio, en tajadas. Mueve
refundsprimero: unbilling/refunds/que mantiene juntos su controller, su service y su model. El siguiente agente que pregunte por reembolsos los encuentra en un solo lugar.
# después
src/
billing/
AGENTS.md # invariantes y la fuente de verdad de billing
refunds/ # controller + service + model, juntos
invoices/
auth-session/
money/ # la matemática que estaba enterrada en utils, ahora nombrada y exigida
shared/ # chico, genérico, sin dependencias
scripts/ # nombrados, listados en package.json
AGENTS.md # las reglas de la casa, y la estructura hacia la que se migra
README.md # preciso, y un test lo mantiene así
Ahora la misma tarea aterriza en billing/refunds/, contra un AGENTS.md que enuncia el invariante del
reembolso, reutilizando el paquete money/ al que la regla lint ya apunta. Los modos de falla no tienen
dónde ocurrir.
Correrlo con el skill
El paso 1 y casi todos los movimientos de arriba son cosas que un agente puede correr. El skill de Context Architecture es un solo archivo que cargas en tu agente: lee el repo como un lector en frío, encuentra los docs que mienten y te devuelve el backlog en el orden de arriba. Apúntalo a tu repositorio y empieza por lo que marca primero.
Hacia dónde seguir
- La especificación: la regla, los cuatro pilares, el mecanismo y los ocho principios completos.
- La comparación con context engineering y harness engineering: qué capa diseña cada una, y por qué esta se sitúa debajo de ellas en tiempo de diseño.
- El skill: para correr el trabajo con tu propio agente.
- El glosario: los términos que se usan en la especificación, definidos.