Author: Dominicode

  • TypeScript 7.0 en Go: Mejoras significativas en rendimiento y paralelismo

    TypeScript 7.0 en Go: Mejoras significativas en rendimiento y paralelismo

    TypeScript 7.0 en Go: qué está pasando y por qué es histórico

    Tiempo estimado de lectura: 3 min

    • Reescritura en Go: Microsoft está migrando el compilador oficial de TypeScript a Go, buscando binarios nativos, paralelismo real y un GC con latencias más predecibles.
    • Rendimiento práctico: Benchmarks internos muestran mejoras de orden de magnitud que reducen compilaciones de minutos a segundos, con impacto directo en CI/CD y experiencia de editor.
    • Compatibilidad y fricción: Integraciones que consumen la API interna de tsc requerirán adaptación (RPC, bindings, WASM) y pruebas exhaustivas en casos límite.
    • Acción inmediata: Estabilizar en TypeScript 6.0, automatizar chequeos de tipos en CI y mapear dependencias que usan la API interna de tsc.

    Tabla de contenidos

    TypeScript 7.0 en Go: qué está pasando y por qué es histórico — la frase debería ser familiar para cualquier Tech Lead que haya sufrido compilaciones lentas en monorepos. Microsoft está reescribiendo el compilador de TypeScript en Go, un movimiento que cambia la base de rendimiento y operacionalidad de todo el ecosistema. Esto no es una mejora incremental: es una rearquitectura que hace viable un análisis tipo‑a‑gran escala sin renunciar a la precisión semántica que define a TypeScript.

    Resumen rápido (lectores con prisa)

    TypeScript 7.0 es la reescritura del compilador oficial en Go, orientada a rendimiento y paralelismo. Ofrece binarios nativos, mejor paralelización y un GC con latencias más predecibles. Es relevante para monorepos, CI y experiencia de editor. Prepara la migración estabilizando en TypeScript 6.0 y automatizando chequeos de tipos en CI.

    TypeScript 7.0 en Go: qué está pasando y por qué es histórico (resumen técnico)

    El compilador actual está escrito en TypeScript y corre sobre Node/V8. Esa decisión fue pragmática en 2012, pero hoy limita la paralelización y sufre del JIT/GC de V8 en cargas largas. Reescribir tsc en Go aporta tres ventajas concretas:

    • Binarios nativos sin warm‑up de JIT.
    • Paralelismo real con goroutines y memoria compartida para analizar módulos en paralelo.
    • Un GC con latencias más predecibles, mejorando la experiencia de tsserver.

    Las herramientas que demostraron el valor del código nativo ya probaron que compilar fuera de Node puede multiplicar la velocidad. SWC, esbuild, Biome y Turbopack ya marcaron esa tendencia. Ahora el compilador oficial entra en esa categoría, pero manteniendo la verificación de tipos completa que esas herramientas no cubren.

    Por qué importa para proyectos grandes y monorepos

    Los beneficios no son teóricos. Microsoft reporta mejoras de orden de magnitud en benchmarks internos, reduciendo compilaciones que tardaban minutos a segundos. Traducido a la vida real:

    • CI/CD: menos minutos por ejecución ⇒ menos coste y despliegues más rápidos.
    • tsserver: indexado y respuestas en el editor que no degradan con el tiempo.
    • Compilaciones incrementales: casi instantáneas en repositorios con cientos de paquetes.

    Si tu pipeline actual dedica gran parte del tiempo a tsc --noEmit, esto cambia la economía del desarrollo.

    Impacto en Angular y React: matices prácticos

    Angular

    Angular está fuertemente integrado con el pipeline de TypeScript (Angular Compiler y Language Service). Proyectos enterprise con workspaces (Nx, monorepos) verán una mejora directa en ng build, ng serve y en la reactividad de las herramientas de plantilla.

    React/Next.js/Vite

    La cadena de transpilación de React/Next.js/Vite ya utiliza SWC o esbuild para velocidad, pero sigue ejecutando tsc para verificación de tipos en CI. Ahí la ganancia será ostensible: los chequeos de tipos dejarán de ser el cuello de botella de los pipelines.

    En ambos casos, el resultado es práctico: menos tiempo en loops edit→build→test y más capacidad para ejecutar validaciones costosas (análisis estático adicional) sin penalizar al equipo.

    Riesgos y fricciones en el ecosistema

    El cambio es histórico, no indoloro. Puntos a vigilar:

    • Herramientas que consumen la API del compilador (por ejemplo ts-morph) necesitarán adaptaciones para interoperar con el nuevo binario o exponer puentes (RPC, bindings, WASM).
    • Integraciones internas que dependen de detalles de implementación de tsc pueden requerir trabajo de migración.
    • Compatibility testing: aunque el lenguaje no debería cambiar, diferencias sutiles en corner cases exigen pruebas exhaustivas.

    La recomendación es seguir la guía oficial del repositorio de TypeScript y monitorizar los anuncios de Microsoft para migraciones y tooling.

    Qué hacer hoy: plan de preparación para equipos técnicos

    1. Estabiliza tu base de código en TypeScript 6.0: activa strict: true y corrige errores. TypeScript 6.0 actúa como puente hacia 7.0.
    2. Automatiza chequeos de tipos en CI: ejecuta tsc --noEmit y añade cobertura para casos límite de tipos.
    3. Identifica dependencias: detecta librerías y herramientas que usan la API interna de tsc y marca tickets de migración.
    4. Mide: registra tiempos actuales de compilación y coste de CI para cuantificar mejoras futuras.
    5. Mantén pruebas: pruebas end‑to‑end y contract tests; cualquier cambio del compilador debe validar el comportamiento real del producto.

    Perspectiva: por qué es histórico

    La convergencia de herramientas nativas (Rust/Go) con el ecosistema JavaScript es una tendencia clara: mayor velocidad sin perder integridad semántica. TypeScript 7.0 no es solo rendimiento; es la posibilidad de escalar el análisis estático a organizaciones enteras sin sacrificar productividad. Para equipos que priorizan calidad y velocidad operativa, esto reconfigura las decisiones de arquitectura y la inversión en tipado.

    Fuentes y lecturas

    Adoptar TypeScript 6.0 y preparar tu infraestructura ahora es la mejor forma de capitalizar la promesa de TypeScript 7.0 en Go cuando el binario esté listo para producción.

    FAQ

    ¿Qué cambia exactamente al reescribir tsc en Go?

    La implementación pasa de ejecutarse sobre Node/V8 a binarios nativos en Go. Esto aporta binarios sin warm‑up de JIT, paralelismo real con goroutines y un GC con latencias más predecibles.

    ¿Debo migrar mis repositorios ahora mismo?

    No necesariamente. La recomendación práctica es estabilizar en TypeScript 6.0 (activar strict: true, corregir errores) y preparar la infraestructura (CI, pruebas) para una futura migración cuando el binario sea estable.

    ¿Cómo afectará esto a mi CI/CD?

    En la mayoría de casos reducirá significativamente los tiempos de ejecución de chequeos de tipos, disminuyendo coste y acelerando despliegues. Es importante medir tiempos actuales para cuantificar la mejora.

    ¿Qué pasa con herramientas que usan la API de tsc?

    Esas herramientas necesitarán adaptaciones: exponer bridges (RPC), bindings o compilar a WASM según el caso. Herramientas como ts-morph son ejemplos que requerirán trabajo de migración.

    ¿Cambiará el lenguaje TypeScript?

    El lenguaje en sí no debería cambiar por la reescritura. Sin embargo, diferencias sutiles en casos límite podrían aparecer, por lo que se requieren pruebas exhaustivas de compatibilidad.

    ¿Cómo puedo medir el beneficio esperado?

    Registra métricas actuales de compilación y coste de CI, ejecuta benchmarks representativos y compara tiempos antes y después. Automatiza registros para cuantificar el impacto en pipelines y tiempos de desarrollador.

  • Cómo evitar la deuda técnica al integrar agentes de IA en el desarrollo

    Cómo evitar la deuda técnica al integrar agentes de IA en el desarrollo

    ¿Y si la velocidad que te vendieron como progreso es, en realidad, el motor que va a deshacer tu arquitectura?

    Tiempo estimado de lectura: 8 min

    • Ideas clave:
    • Integrar agentes de IA sin capturar intención produce deuda técnica a escala.
    • Necesitas trazar decisiones → requerimiento → test → código y hacerla canónica.
    • Una herramienta como Plum no pinta paredes; convierte intención volátil en artefactos persistentes.
    • Gobernanza debe vivir fuera del agente: hooks, CI y aprobaciones humanas son imprescindibles.

    Introducción

    ¿Y si la velocidad que te vendieron como progreso es, en realidad, el motor que va a deshacer tu arquitectura?

    Poca gente lo dice sin rodeos: integrar agentes de IA para escribir código sin un sistema que capture la intención es una receta perfecta para deuda técnica a escala industrial. Y no hablo de “posibles problemas”. Hablo de que, hoy, el código puede crecer más rápido de lo que cualquier humano puede leer —y eso duele en producción.

    This is her code. This is what she was managing. This is her VS code.

    Margaret Hamilton sujetó esa complejidad con una pila de impresiones. Ella no tenía prompts; tenía procedimientos. Nosotros tenemos prompts y convicciones ingenuas.

    Vamos al punto.

    Resumen rápido (lectores con prisa)

    Plum es una herramienta de gobernanza que intercepta commits, extrae decisiones y las convierte en artefactos trazables. Úsala cuando quieras que las decisiones que toman agentes o developers queden registradas y enlazadas a specs, tests y código. Importa porque previene deuda técnica acelerada por IA y funciona mediante git hooks, diffs, y un flujo de aprobación humana.

    1) El problema (simple y aterrador)

    Si un Product Manager edita una regla en producción, ¿el resto del sistema cambia con ella?

    En la práctica, no.

    Los hotfixes saltan directo al trunk.

    Los tests se rompen en silencio.

    Las specs siguen siendo documentos en Markdown que nadie actualiza.

    Y cuando introduces agentes de IA en ese mix, la cosa se acelera: los LLMs toman micro-decisiones en chats, tú implementas, haces commit y la “intención” se evapora.

    Resultado: código con autoría pero sin porqué. Comportamiento sin contrato. Equipos que arreglan cosas por intuición y no por diseño.

    2) Por qué los tests y specs no bastan

    Un test valida un output. No captura intención.

    Un spec define un contrato —hasta que alguien lo ignora.

    La implementación revela límites: casos borde, problemas de estado, compromisos de rendimiento. La única forma real de enriquecer una spec es escribir el maldito código. Implementar obliga a decidir. Y esas decisiones deben quedar registradas.

    3) ¿Qué hace falta?

    • Capturar decisiones. No dejar que vivan en el chat.
    • Vincular decisión → requerimiento → test → código.
    • Hacer que esa trazabilidad sea canónica y no opcional.

    Sin eso, tus agentes son obreros hiperproductivos que construyen habitaciones sin planos. Velocidad sin planos = casa que se cae.

    4) Plum: la plomada que no pinta paredes

    No es mágica. No genera código bonito.

    Plum hace otra cosa muchísimo más valiosa: transforma intención volátil en artefacto persistente.

    Qué hace Plum (sí, práctico)

    • Intercepta commits via git hooks.
    • Lee diffs y scans de traces de agentes.
    • Extrae decisiones (qué, por qué, quién).
    • Deduplica lógicas repetidas.
    • Te obliga a aprobar/rechazar/editar antes de permitir el commit.
    • Si apruebas, actualiza specs Markdown y genera un .jsonl con la decisión, autoría y trazas.
    • Ejecuta un sync que mapea spec ↔ tests ↔ código y muestra huecos de cobertura.

    Metáfora: la plomada cuelga del trípode y te dice si la pared está vertical. Plum no pinta; evita derrumbes.

    5) Por qué esto no puede ser una “skill” dentro del agente

    Una skill vive dentro del agente. Es una sugerencia.

    Un control de gobernanza tiene que vivir fuera. Debe poder bloquear commits, correr en CI y ser determinista.

    Si la herramienta fuera sólo otra respuesta del LLM, se ignoraría. Punto.

    6) Problemas reales a resolver (y por qué no es trivial)

    • Umbral de interrupción: si cada hotfix genera cinco decisiones para revisar, los devs odian la herramienta. Necesitas tolerancias dinámicas: que el sistema sólo te despierte para decisiones vagas, peligrosas o contradictorias.
    • Dedupe y fuzzy decision ID: identificar decisiones no es binario; es difuso y repo-específico. Necesitamos algoritmos ajustables y feedback humano.
    • Rollbacks automáticos: si rechazas una decisión, el sistema debería revertir el cambio relevante o pedir al agente que rehaga la tarea coherentemente. Hoy eso no está pulido.
    • Spec sharding: las specs crecen. Hay que fragmentarlas en requisitos testables. Un LLM puede ayudar a shardear, pero hay que diseñarlo.
    • Integración de test runners: en la versión actual Plum está acoplado a pytest. Necesitamos soporte agnóstico: conformance tests, runners multi-lenguaje, harnesses de integración.
    • Escalabilidad: en proyectos monolíticos gigantes aún no sabemos si el approach escala. Téstealo en una rama pequeña antes de clonar tu repo legacy.

    7) Cómo se gana valor real (dejando de ser postura)

    • Haz que cada decisión importante deje rastro. No excepciones.
    • Exige aprobación humana para decisiones con impacto.
    • Vuelve la spec viva: que el archivo Markdown no sea un monumento a la intención, sino el contrato vigente.
    • Los tests deben describir intención, no solo outputs. Property tests e invariantes sistémicas son tus nuevos héroes.
    • Si un agente necesita leer 50 archivos para cambiar una función, rehace la arquitectura: modularidad extrema, boundaries claros.

    8) Diseño técnico inteligente (lo que aprendí construyéndolo)

    • Usa git hooks como checkpoint. Si el commit no pasa la validación de decisiones, el commit falla.
    • Mantén un .plumignore para no disparar reviews por cambios triviales (README, docs, etc.).
    • Almacena estado y config en una carpeta oculta (.plum). Versiona el .jsonl.
    • Deduping y parsing de specs: estructura las llamadas LLM con DSPy para hacerlas más deterministas y testables.
    • Router de modelos: no todo exige GPT-costoso. En dedupe puedes usar un modelo OSS rápido. La experiencia del dev gira alrededor de latencia.
    • Diseña la UX: permitir modos (silent, strict, dangerously-approve) para distintos contextos.

    9) Ejemplo mínimo de flujo (para que lo pruebes en 15 minutos)

    • pip install plum-dev
    • cd repo (with specs.md and pytest suite)
    • plum init → apunta a folder de specs y a tests
    • Haz cambios con tu agente y commit
    • Si hay decisiones, git commit fallará y te pedirá revisión
    • Aprobar actualiza spec; reject detona rollback o workflow manual según tu configuración

    10) Umbral y gobernanza: políticas prácticas

    • En sistemas críticos: tolerancia cero. Todo pasa por aprobación humana.
    • En prototipos: modo “agile fast-lane” para no morir de fricción.
    • En equipos mixtos: definir perfiles por carpetas/paquetes. Modules core = strict; UI experimental = lenient.
    • Pipeline: bloquear merges si spec↔tests↔código no están sync. Es duro, sí. Necesario, también.

    11) Cultura y disciplina

    No se automatiza cultura. Se diseña.

    Pide que cada PR incluya:

    • ¿Qué decisión justificó este cambio?
    • ¿Qué requisitos se actualizaron?
    • ¿Qué tests nuevos cubren la decisión?

    Y deja que la herramienta coja esos metadatos y los convierta en .jsonl rastreables.

    12) Lo práctico y lo urgente

    • Si ya usas agentes y no tienes este tipo de control, estás acelerando una deuda técnica que no podrás pagar. No es dramático; es inevitable.
    • Prioridad de adopción:
      • 1. Empezar a capturar traces.
      • 2. Agregar hooks que bloqueen commits sin revisión de intención.
      • 3. Transformar specs en contratos testables.
      • 4. Automatizar sync y coverage mapping.

    13) ¿Qué pasa si no lo haces?

    Velocidad hoy = caos mañana.

    Cuando un bug crítico aparezca a las 2 AM, nadie sabrá por qué la regla se cambió. Commits huérfanos. Blame que no sirve. Migraciones peligrosas. Equipos quemados. Clientes enfadados.

    14) No todo es miedo: oportunidades enormes

    • Auditoría real sobre decisiones: útil para compliance y seguridad.
    • Mejor onboarding: nuevos devs leen el árbol de decisiones para comprender el porqué.
    • Menos discusiones eternas en PRs: si la decisión está bien documentada, la discusión baja y la calidad sube.
    • Productividad con control: velocidad + gobernanza = ventaja competitiva.

    15) Cierre con acción concreta

    Instala la plomada. Prueba en una rama pequeña. No por postureo. Por supervivencia técnica.

    Si quieres:

    • Te mando un template de .jsonl para decisiones.
    • Te paso un flujo de PR que puedes pegar en tu repo.
    • Te doy el checklist para integrar Plum en CI en 15 minutos.

    Respóndeme este mensaje con “Mándame el template” o corre ahora:

    • pip install plum-dev
    • cd tu-repo
    • plum init
    • haz un commit con un agente y observa qué decisiones aparecen.

    Esto no acaba aquí.

    Si no empiezas a capturar intención hoy, tus agentes construirán un legado que nadie querrá mantener mañana. Empieza por un archivo .jsonl. Empieza por una regla dura en tu CI. Haz que la próxima vez que alguien pregunte “¿por qué esto existe?” la respuesta esté en el repo y no en el recuerdo difuso de una conversación vieja.

    ¿Quieres el checklist y el template ahora? Dímelo. Y mientras lo instalas, piensa en esto: velocidad sin plomada es solo una forma elegante de cavar tu propia trampa.

    Para quien está explorando gobernanza de agentes y workflows, una continuación lógica es revisar investigaciones y herramientas de integridad técnica desarrolladas por equipos que experimentan con estos retos. Consulta Dominicode Labs como punto de referencia para materiales y experimentos relacionados con trazabilidad de decisiones y automatización segura.

    FAQ

    ¿Qué es Plum y para qué sirve?

    Plum es una herramienta de gobernanza que intercepta commits, extrae decisiones desde diffs y trazas de agentes, obliga a revisarlas y las convierte en artefactos persistentes (.jsonl) y actualizaciones en specs Markdown. Sirve para capturar intención y vincularla con tests y código.

    ¿Por qué no bastan los tests y las specs?

    Porque un test valida un output y una spec es un contrato que puede quedarse desactualizado. La implementación revela decisiones operacionales que deben quedarse registradas; solo ejecutar y aprobar esos cambios garantiza que la spec refleje intención real.

    ¿Cómo se integra Plum en el flujo de trabajo?

    Plum se integra mediante git hooks que interceptan commits, revisan diffs y traces, y requieren aprobación humana para cambios con decisión. Si se aprueba, Plum actualiza specs y genera el registro .jsonl; si no, puede revertir o pedir una re-ejecución coherente.

    ¿Qué pasa si rechazo una decisión durante el commit?

    Según la configuración, el rechazo puede detonar un rollback automático del cambio relevante o iniciar un workflow manual que pida al agente rehacer la tarea coherentemente. El comportamiento exacto depende de la policy definida.

    ¿Plum afecta la experiencia del desarrollador?

    Sí: introduce una fricción intencional para decisiones relevantes. Para evitar rechazo por exceso de ruido, Plum debe soportar tolerancias dinámicas (modos silent, strict, dangerously-approve) y un .plumignore para cambios triviales.

    ¿Es Plum dependiente de un test runner?

    En su versión inicial Plum está acoplado a pytest, pero el objetivo es soportar runners multi-lenguaje y conformance tests para ser agnóstico respecto al ecosistema de pruebas.

    ¿Cómo empezar con Plum sin romper el equipo?

    Prueba en una rama pequeña, habilita modos lenientes para partes experimentales del repo y aplica tolerancia cero solo en módulos críticos. Empieza por capturar traces y agregar hooks progresivamente.

  • Cómo elegir el formato adecuado para contenido técnico

    Cómo elegir el formato adecuado para contenido técnico

    ¿Quieres que esto sea útil o que suene bonito en una página y nadie haga nada?

    Tiempo estimado de lectura: 1 min

    Ideas clave

    • Tienes un post ya escrito y necesitas decidir el siguiente paso: expandirlo, convertirlo en guía técnica o adaptarlo a redes.
    • Se ofrecen tres opciones claras con resultados distintos según objetivo y audiencia.
    • Puedes solicitar tono y extras (CI / .env / JSONL) para ajustar el entregable.

    Contenido principal

    1) Expandirlo a largo (1.500–2.000 palabras)

    • Versión profunda, técnica y persuasiva.
    • Gancho potente, ejemplos reales, checklist de adopción, riesgos, pasos de CI, y cierre con CTA.
    • Ideal si quieres un artículo para tu blog o newsletter.

    2) Transformarlo en una guía técnica práctica (800–1.200 palabras)

    • Comandos, .env ejemplo, flujo CI, script de rotación de credenciales, y best practices para agentes IA.
    • Directo al grano. Para equipos que van a implementar ya.

    3) Recortar y adaptar a LinkedIn/Twitter thread + TL;DR

    • Versión corta, viral, con 8–12 tuits o un post largo en LinkedIn que invite a comentar.
    • Perfecto para provocar conversación y atraer gente al artículo.

    Cómo responder

    Dime cuál opción y si quieres tono: más técnico, más comercial, o más provocador (yo voto por provocador). También puedo añadir: checklist de seguridad, fragmento de CI (GitHub Actions), o template de .env y JSONL para decisiones.

    Respóndeme “Opción 1/2/3” y si quieres el extra (CI / .env / JSONL). Me pongo a escribir.

    Recursos

    Si tu post toca automatización, agentes o workflows y quieres material adicional para pruebas y experimentos, puedes consultar recursos relacionados en Dominicode Labs. Es un complemento lógico cuando se trabaja con implementaciones prácticas y plantillas.

    FAQ

    ¿Qué respondo?

    Responde con “Opción 1”, “Opción 2” o “Opción 3”. Si quieres algún extra, añádelo entre paréntesis, por ejemplo: “Opción 2 (CI, .env)”.

    ¿Qué incluye la Opción 1?

    Una versión larga (1.500–2.000 palabras) orientada a profundidad técnica y persuasión, con gancho, ejemplos, checklist, riesgos, pasos de CI y un cierre con CTA.

    ¿Qué incluye la Opción 2?

    Guía técnica práctica de 800–1.200 palabras con comandos, ejemplo de .env, flujo CI, scripts de rotación y recomendaciones para agentes IA, enfocada en implementación.

    ¿Qué incluye la Opción 3?

    Versión corta pensada para redes: 8–12 tuits o un post largo en LinkedIn con TL;DR para generar conversación y atraer lectores al artículo principal.

    ¿Puedo pedir extras?

    Sí. Puedes solicitar checklist de seguridad, fragmentos de CI (por ejemplo GitHub Actions), o templates de .env y JSONL para decisiones. Indica claramente qué extras quieres al responder.

    ¿En qué formato recibo el entregable?

    El contenido se entregará listo para pegar en WordPress. Si pides fragmentos de CI o templates, se incluirán como bloques de texto listos para copiar.

  • Cómo evitar el uso de `any` en TypeScript y mejorar tu código

    Cómo evitar el uso de `any` en TypeScript y mejorar tu código

    ¿Sigues parcheando con any porque “es más rápido”? Felicidades: acabas de convertir a tu compilador en un cómplice silencioso de los bugs nocturnos.

    Tiempo estimado de lectura: 5 min

    • TypeScript no te salva por arte de magia: es una herramienta que hay que configurar y aplicar, no decoración del IDE.
    • No uses any como parche: usa unknown o validación runtime para datos externos.
    • Activa strict y prioriza validación en la frontera: tsconfig, linters, CI y validadores como Zod.

    Introducción

    Poca gente lo dice tan claro: TypeScript no te salva automáticamente. Si lo tratas como decoración del IDE, te dará una falsa sensación de seguridad. Y cuando las cosas se rompan en producción, nadie recordará quién puso ese as any a las tres de la mañana.

    Voy a ser directo. Esto es lo que rompe proyectos y cómo lo arreglas para que deje de romperlos.

    Resumen rápido (lectores con prisa)

    TypeScript proporciona tipos estáticos para detectar errores tempranos en desarrollo. No valida tipos en runtime; para datos externos hay que usar validación en la frontera (por ejemplo Zod) y mantener "strict": true en tsconfig. Evita any y el operador de aserción no-nula !; prefiere unknown, encadenamiento opcional y guard clauses. Integra linters y CI que ejecuten tsc --noEmit y pruebas de contratos para evitar deuda técnica silenciosa.

    Qué falla y cómo lo arreglas

    1) Deja de usar any como parche rápido

    any = apagar las comprobaciones. unknown = obligarte a pensar.

    Usa unknown cuando no conoces la forma de un dato. Forcear any es como cerrar los ojos y conducir a 140 km/h: puedes llegar, o no.

    Ejemplo idiota, pero real:

    // NO
    function process(payload: any) {
      console.log(payload.name.toUpperCase());
    }
    
    // SÍ
    function processSafe(payload: unknown) {
      if (typeof payload === 'object' && payload !== null && 'name' in payload) {
        console.log((payload as { name: string }).name.toUpperCase());
      }
    }
    

    No te apetece escribir esa comprobación ahora. Perfecto: pon una validación con Zod y delega la detección a la frontera.

    2) Activa strict. No negociable.

    Si tu tsconfig dice "strict": false estás firmando cheques a la deuda técnica.

    Síntomas: parámetros sin tipado, nulos que aparecen sin avisar, inicialización incompleta de clases. Solución simple: "strict": true y arreglar las fallas una por una. ¿Migración? Usa @ts-expect-error puntualmente. No rebajes la seguridad global.

    3) El operador ! es una mentira elegante

    usuario.address!.street parece limpio. Es una bomba.

    Mejor: encadenamiento opcional o guard clauses.

    • usuario.address?.street — seguro, devuelve undefined.
    • if (!usuario.address) return — claro, explícito.

    Si ven ! en un PR, que explique por qué. Si no puede explicar, rechaza el PR.

    4) as T NO valida datos externos

    const data = await res.json() as User es confiarle la vida a un string.

    En la frontera (red, persistencia, input externo), usa validación runtime. Zod, io-ts, AJV: cualquiera que genere el guard que puedas correr al recibir datos. Y sí: extrae el esquema a un único lugar para que el tipo y el validador sean la misma verdad.

    Ejemplo con Zod:

    import { z } from 'zod';
    const UserSchema = z.object({ id: z.string(), name: z.string() });
    type User = z.infer;
    
    const raw = await res.json();
    const user = UserSchema.parse(raw); // lanza si no concuerda
    

    5) La “gimnasia de tipos” rompe equipos

    Type Gymnastics — esos tipos de 40 líneas que solo el autor entiende — son deuda técnica disfrazada. Úsalos donde aporten valor: librerías, infra, utilities core. No en cada componente. Si un tipo necesita 30 minutos para entenderlo, lo estás usando mal.

    Buenas prácticas: alias cortos, nombres claros, ejemplos en comentarios y tests de tipos (tsd) para que no se rompa en silencio.

    Checklist operativo (copia y pega y aplica ya)

    • tsconfig.json: "strict": true
    • ESLint: activar reglas
      • @typescript-eslint/no-explicit-any: error
      • @typescript-eslint/strict-boolean-expressions: warn/error
    • Pre-commit: husky + lint-staged para bloquear any y !
    • CI: job que ejecuta tsc --noEmit y tests de contratos (Zod parse)
    • Boundary validation: todas las respuestas HTTP parseadas con Zod/io-ts
    • Tests de tipos con tsd en PRs críticos

    Snippet de CI (esqueleto GitHub Actions)

    name: Validate Types
    on: [pull_request]
    jobs:
      types:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - run: pnpm install
          - run: pnpm build # incluye tsc --noEmit
          - run: pnpm test:contracts # tests que hacen parse de esquemas Zod
    

    Cómo aplicarlo en equipos (cultura > herramientas)

    • Regla simple: todo dato que venga de fuera pasa por un esquemas.
    • PRs deben documentar la asunción: “Por qué este ! está justificado”.
    • Prohibe any en lint. No excepciones.
    • Revisión de tipos en pair programming para cambios complejos.
    • Añade tests e2e que verifiquen la integración real del esquema (no solo mocks).

    Errores típicos y la respuesta corta

    • “No activamos strict porque produce demasiados errores” → Activarlo e ir resolviendo; cada corrección es una deuda pagada.
    • “Validar en runtime es caro” → El coste es mínimo comparado con el tiempo perdido debugueando un null en producción.
    • “Los tipos complejos son elegantes” → Sí. Elegantes y peligrosos si nadie los entiende.

    Mini-guía de herramientas que te salvan la vida

    • Zod: validación runtime + inferencia de tipos. Ganador simple.
    • @typescript-eslint: reglas para prohibir any, !, etc.
    • tsd: tests de tipos que evitan roturas silenciosas.
    • husky + lint-staged: bloqueo en pre-commit de malas prácticas.
    • Sentry / logs: cuando la validación falla en producción, registra payload + endpoint.

    Métrica que deberías vigilar semanalmente

    • PRs con any encontrados: objetivo = 0.
    • Rechazos por ! sin justificación: objetivo = 0.
    • Número de validaciones runtime faltantes en endpoints críticos: objetivo = 0.

    Si tienes más de 1 en cualquiera, tienes trabajo de deuda técnica.

    Cierre sin azúcar: esto es disciplina, no postureo

    TypeScript te da herramientas para poner reglas fuertes y claras en el código. Sin disciplina, esas reglas se convierten en adorno. Cambiar la cultura es más duro que tocar tsconfig, pero mucho más rentable.

    ¿Quieres algo práctico para arrancar mañana? Te puedo enviar:

    • Un repo template con tsconfig, ESLint, husky, Zod y pruebas de contratos listas.
    • Un workflow de GitHub Actions que falla el CI si hay any o ! no justificado.
    • Un checklist PDF para code reviews centrado en tipado seguro.

    Respóndeme “Envíame el template” o “Quiero el workflow” y te lo paso listo. No es sexy. Es lo que evita que pases la noche arreglando prod por culpa de un as any. Esto no acaba aquí.

    FAQ

    ¿Por qué no debo usar any?

    Porque desactiva las comprobaciones de tipos y oculta errores que el compilador podría detectar. Usar any convierte el compilador en cómplice de bugs que aparecen en producción.

    ¿Cuándo usar unknown en lugar de any?

    Usa unknown cuando recibes datos sin estructura conocida. Obliga a validar o refinar el tipo antes de operar sobre el valor, evitando asunciones peligrosas.

    ¿Qué hace exactamente “strict”: true?

    Activa un conjunto de opciones de compilador que refuerzan la seguridad de tipos: strictNullChecks, noImplicitAny, strictBindCallApply, entre otras. Detecta parámetros sin tipado, nulos no manejados y problemas de inicialización.

    ¿Cómo valido respuestas HTTP correctamente?

    Usa validación runtime en la frontera con esquemas compartidos (por ejemplo Zod). Parseas el payload recibido con el esquema y manejas el error si no concuerda antes de propagar datos al resto de la aplicación.

    ¿Qué hacer si activar strict rompe demasiados archivos a la vez?

    Actívalo y corrige las fallas progresivamente. Para casos puntuales usa @ts-expect-error temporalmente, pero no como solución permanente.

    ¿Cómo evitar que los tipos complejos sean incomprensibles?

    Prefiere alias cortos y nombres claros, añade ejemplos y tests de tipos (tsd) y reserva tipos largos para librerías o infraestrutura donde el equipo esté alineado.

  • Cómo usar Claude Code para tareas sin ser developer

    Cómo usar Claude Code para tareas sin ser developer

    Es claude code tan solo para developers ? 3 cosas que puedes hacer con claude sin ser developer

    “Tiempo estimado de lectura: 3 min”

    • Claude Code es una herramienta orientada a terminales y repos; Claude (modelo web/API) ofrece razonamiento técnico accesible sin instalar dependencias.
    • Con Claude puedes diseñar y depurar workflows en herramientas como n8n (automatización), transformar y analizar datos, y generar documentación y diagramas (Mermaid, OpenAPI).
    • La diferencia clave no es saber programar, sino estructurar problemas y validar hipótesis técnicas usando el modelo web/API.

    Introducción

    Es claude code tan solo para developers ? Si escuchaste “CLI” y cerraste la puerta, respira: la respuesta técnica es sí —pero la historia completa no es tan simple.

    Claude Code (el agente CLI de Anthropic) está pensado para terminales, repos y tareas que tocan el código. Pero Claude, el modelo, vive en la web, en APIs y en integraciones: te da razonamiento técnico sin obligarte a teclear npm install. Aquí te explico por qué importa y tres cosas concretas que puedes hacer sin ser developer.

    Resumen rápido (lectores con prisa)

    Qué es: Claude Code es un agente CLI; Claude (modelo) se accede vía web/API e integraciones.

    Cuándo usarlo: Usa Claude Code si un agente debe tocar tu repo y ejecutar tests; usa Claude Web/API para razonamiento, diseño de flujos y transformación de datos.

    Por qué importa: Permite a non-devs con criterio diseñar, validar y documentar soluciones técnicas sin convertirse en especialistas en sintaxis.

    Cómo funciona: En vez de escribir sintaxis, describes escenarios, estructuras y reglas; el modelo transforma esa descripción en snippets, esquemas y diagramas reutilizables.

    Es claude code tan solo para developers ? Lo esencial en 60 segundos

    Claude Code = herramienta para desarrolladores. Vive en la terminal. Requiere Git, variables de entorno y un repo que pueda inspeccionar y modificar.

    Claude (3.7 Sonnet y variantes) = modelo razonador accesible por web/API. No necesitas compilar nada, sí necesitas saber explicar problemas con precisión. En vez de escribir sintaxis, planteas escenarios, estructuras de datos y reglas. El peso se traslada del teclado al criterio.

    Traducción práctica: si eres product manager, automation builder o founder, puedes usar Claude como copiloto intelectual. No como quien programa, sino como quien diseña y valida soluciones.

    1) Diseñar y depurar workflows en n8n — sin tocar Node.js

    n8n es el lugar donde los flujos se vuelven reales. Pero cuando un JSON llega sucio o una API no tiene nodo nativo, la fricción aparece.

    Lo que haces con Claude:

    • Pegas el payload del webhook y pides: “Dame el fragmento JS para extraer estos campos y normalizarlos.”
    • Le pides la lógica de reintentos y manejo de errores: condiciones, backoff y notificaciones.
    • Si una API requiere HMAC o firma en cabeceras, Claude te escribe la plantilla para el nodo HTTP.

    Ejemplo (conceptual): le describes el JSON y obtienes el snippet listo para pegar en un Code Node de n8n. No tienes que memorizar async/await; solo validar la salida.

    Referencia: n8n (automatización)

    2) Transformar y analizar datos — sin pelear con hojas de cálculo eternas

    Limpiar datos es un agujero negro. Claude lo hace predecible.

    Casos concretos:

    • Generar regex para extraer emails, IDs o patrones específicos. (“Extrae solo .edu y .org que parezcan institucionales.”)
    • Convertir CSV/XML desordenados a JSON con esquema validado. Pegas 50 filas y pides el JSON-schema.
    • Redactar consultas SQL complejas: joins, ventanas, filtros por fechas. Le das la estructura de tablas y la métrica que quieres; él devuelve la query optimizada para tu caso.

    No es “codificar por ti”. Es convertir trabajo repetitivo y propenso a errores en instrucciones reproducibles.

    3) Documentación y diagramas técnicos que no te roban medio día

    El 70% del valor de una decisión técnica está en cómo se comunica. Claude entiende Mermaid.js y puede producir diagramas desde tu texto.

    Lo que recibes:

    • Código Mermaid listo para pegar en Notion o GitHub y ver el diagrama al instante.
    • Un borrador de OpenAPI a partir de la descripción de un endpoint (paths, parámetros, respuestas).
    • Un mapa de arquitectura cloud con dependencias y puntos de integración (ideal para alinear con ingeniería sin sonar inocente).

    Pequeña ventaja: llegas a la reunión con algo que se puede visualizar y discutir, no con una vaga idea.

    Docu: Mermaid (diagramas) · OpenAPI spec

    ¿Cómo decidir si usar Claude Code o Claude Web/API?

    Regla simple:

    • Si vas a dejar que un agente toque tu repo, ejecuciones y tests: Claude Code (requiere developer).
    • Si necesitas razonamiento, diseño de flujos, transformación de datos o documentación: Claude Web/API o integraciones (ideal para non-devs con criterio).

    El nuevo diferencial no es “saber programar”. Es saber estructurar problemas y validar hipótesis técnicas. Claude amplifica eso.

    Conclusión

    No conviertas la terminal en el test de tu valía. Aprende a describir problemas con precisión y tendrás una herramienta que piensa en arquitectura, no solo en sintaxis. Esto apenas comienza: la próxima ronda será cómo integrar Claude en tus procesos de despliegue y gobernanza sin romper producción.

    Fuentes útiles: Anthropic – Claude, n8n (automatización), Mermaid (diagramas), OpenAPI spec

    Para explorar implementaciones y experimentos relacionados con automatización y agentes, visita Dominicode Labs. Es una continuación lógica para quien quiere pasar del diseño a prototipos reproducibles.

    FAQ

    Respuesta: Claude Code es el agente CLI de Anthropic diseñado para operar en terminales y repos (requiere Git, variables de entorno y permisos de repo). Claude, en cambio, es el modelo accesible por web/API e integraciones y está orientado a razonamiento y generación sin necesidad de ejecutar comandos locales.

    Respuesta: No. Para acceder al razonamiento y generación de soluciones técnicas puedes usar Claude Web/API o integraciones; no necesitas ser developer, pero sí saber describir problemas con precisión.

    Respuesta: Sí. Puedes describir el payload o el problema y pedir snippets o plantillas listos para pegar en un Code Node de n8n, así evitas escribir Node.js desde cero.

    Respuesta: Generación de regex, conversión de CSV/XML a JSON con esquema validado, y redacción de consultas SQL complejas (joins, ventanas y filtros). Claude transforma tareas repetitivas en instrucciones reproducibles.

    Respuesta: Sí. Claude puede producir código Mermaid y borradores de OpenAPI que se pegan directamente en herramientas como Notion o GitHub para visualización inmediata.

    Respuesta: Elige que un agente toque tu repositorio cuando sea necesario ejecutar pruebas, aplicar cambios automáticos o inspeccionar código de forma programática. Si solo necesitas diseño, razonamiento o generación de artefactos técnicos, la web/API suele ser suficiente.

  • Implementación efectiva con Plan Mode en Claude Code

    Implementación efectiva con Plan Mode en Claude Code

    Plan Mode primero, código después: el workflow que cambia cómo trabajas con Claude Code

    Tiempo estimado de lectura: 5 min

    • Plan Mode obliga a auditar y planear antes de ejecutar cambios en código.
    • Workflow en tres fases: análisis, refinamiento y ejecución; cada fase reduce riesgo y scope de impacto.
    • Activa Plan Mode en cambios multiplataforma, código heredado o integraciones de librerías arquitectónicas.
    • Mide efectividad por integración sin rollback, estabilidad en CI y ahorro de horas en debugging.

    Plan Mode primero, código después es la regla que separa entregas limpias de correcciones interminables. Activa Plan Mode, deja que Claude analice el repositorio y produzca un plan antes de que toque una sola línea de código. Esa inversión de diez minutos evita horas de debugging por decisiones implícitas.

    Resumen rápido (lectores con prisa)

    Plan Mode obliga a auditar y planear cambios antes de codificar. Úsalo cuando el cambio implica múltiples archivos, código heredado o librerías que afectan la arquitectura. Workflow: análisis, refinamiento y ejecución. Mide por integración sin rollback y estabilidad en CI.

    Plan Mode primero, código después: qué es y por qué importa

    Plan Mode es un modo de sesión en Claude Code que obliga al agente a auditar el código existente, mapear dependencias y proponer una secuencia de cambios verificable antes de implementar. Se activa con Shift+Tab en sesiones interactivas de Claude Code; la documentación oficial lo describe como un flujo que prioriza planificación sobre ejecución (https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview y https://www.anthropic.com/claude).

    ¿Por qué importa? Porque los errores de diseño no son fallos de sintaxis: son decisiones implícitas que se propagan. Implementar primero amplifica esos errores. Planear primero los expone cuando aún cuestan cero cambios.

    Cómo funciona el workflow (práctico y repetible)

    El workflow consta de tres fases claras: análisis, refinamiento y ejecución. No son sugerencias; son pasos que los equipos efectivos repiten cuando integran agentes en su proceso.

    1) Análisis inicial (activar Plan Mode)

    Activa Plan Mode (Shift+Tab). Describe el objetivo como contrato, no como receta. Ejemplo: “Aísla la lógica de autenticación para pruebas unitarias sin DB” en vez de “usa repositorio para auth”. Deja que Claude liste archivos relevantes, dependencias directas y riesgos.

    2) Revisión y refinamiento (iterar sobre el plan)

    Lee el plan: archivos a tocar, orden propuesto, efectos secundarios y tests necesarios. Corrige límites de dominio si hace falta. Esa iteración es barata: texto, no commits. Aquí se define el alcance real y se evitan sorpresas de integración.

    3) Aprobación e implementación (ejecutar con control)

    Aprobas el plan y Claude implementa en el orden validado. Cada cambio es acotado, con tests adjuntos y notas de diseño. Si algo rompe, el impacto está limitado al módulo que se aprobó, no a toda la base de código.

    Ejemplo real de uso en migración

    Meta: migrar API REST a tRPC por módulos.

    Spec

    • Módulo A: AuthService (sin dependencias).
    • Módulo B: UserService (depende de A).
    • Módulo C: Billing (depende de B).

    Con Plan Mode, Claude devuelve: archivos a crear/modificar por módulo, tipos DTO esperados, tests unitarios y orden de merges. Implementación ocurre por sesión por módulo. Resultado: integraciones predecibles y rollback sencillo.

    Cuándo activar Plan Mode (criterio técnico)

    Activa Plan Mode cuando:

    • El cambio afecta múltiples archivos o contracts públicos.
    • Trabajas en código heredado que no conoces.
    • Vas a integrar una librería que afecta la arquitectura (auth, DB, infra).
    • La tarea es una refactorización o migración.

    No lo actives cuando:

    • El cambio es un ajuste pequeño en un único archivo.
    • Creas un archivo nuevo con una spec cerrada.
    • Resuelves un typo o validación trivial.

    El criterio es simple: a mayor riesgo arquitectónico, mayor valor del plan previo.

    Reglas prácticas para que Plan Mode funcione

    • Siempre comienza con CLAUDE.md actualizado. El agente leerá convenciones y patrones prohibidos antes de planear (si tu repo lo tiene, intégralo; si no, crea uno).
    • Exige que el plan incluya: archivos modificados, orden de cambios, tests a ejecutar y riesgos conocidos.
    • Valida el plan tú, un peer o el tech lead; las aprobaciones humanas reducen regresiones.
    • Mantén las sesiones acotadas: una sesión = un módulo. Evita planos globales indefinidos.

    Métricas que importan (no solo LOC/hora)

    Mide efectividad por:

    • Tiempo hasta integración sin rollback.
    • Número de handoffs con correcciones arquitectónicas.
    • Cobertura y estabilidad en CI tras cada merge.
    • Tiempo invertido en revisión del plan vs. horas ahorradas en debugging.

    Un plan de 10 minutos que evita 2 horas de corrección es ROI directo.

    Riesgos y límites honestos

    Plan Mode reduce errores, no elimina la necesidad de juicio humano. Si la spec es ambigua, Claude producirá una implementación ambigua más rápido. El agente no reemplaza decisiones críticas de diseño, trade-offs de rendimiento o consideraciones legales de seguridad. Su fuerza está en ejecutar lo que tú especificas mejor y antes de que toque escribir código.

    Conclusión

    Adoptar “Plan Mode primero, código después” cambia la métrica del equipo: de velocidad de salida a resiliencia de la plataforma. Si quieres que Claude Code deje de ser un generador de parches y pase a ser un colaborador técnico confiable, exige un plan. Haz que piense antes de tocar tu repo.

    Para equipos que exploran workflows, integraciones y automatización avanzada, consulta Dominicode Labs como continuación lógica del enfoque: recursos y experimentos centrados en agentes y productividad técnica.

    FAQ

    ¿Qué es Plan Mode?

    Plan Mode es un modo de sesión en Claude Code que obliga al agente a auditar el código existente, mapear dependencias y proponer una secuencia de cambios verificable antes de implementar.

    ¿Cuándo debo activarlo?

    Actívalo cuando el cambio afecta múltiples archivos, trabajas en código heredado, o integras librerías que afectan la arquitectura. Para cambios pequeños y aislados no es necesario.

    ¿Qué debe incluir un plan mínimo?

    El plan debe listar archivos a modificar, orden de cambios, tests a ejecutar y riesgos conocidos. También conviene indicar límites de dominio y criterios de aceptación.

    ¿Cómo reduce el riesgo en migraciones?

    Al definir el alcance y el orden de merge por módulo, limita el blast radius y facilita rollbacks. Permite validar la integración por partes con tests adjuntos.

    ¿Plan Mode reemplaza la revisión humana?

    No. Plan Mode reduce errores estructurales, pero las aprobaciones humanas siguen siendo necesarias para decisiones críticas y trade-offs no técnicos.

    ¿Qué métricas debe rastrear mi equipo?

    Tiempo hasta integración sin rollback, número de handoffs con correcciones arquitectónicas, cobertura y estabilidad en CI, y la relación entre tiempo de planificación y horas ahorradas en debugging.

  • Implementando Compound AI para Optimizar la Efectividad en Testing

    Implementando Compound AI para Optimizar la Efectividad en Testing

    ¿Quieres que la IA escriba código… o que lo arruine en silencio mientras nadie sabe por qué?

    Tiempo estimado de lectura: 8 min

    • Ideas clave:
    • Los LLMs no son inherentemente malos; el problema es soltarlos sin reglas ni orquestación.
    • Compound AI es orquestación: múltiples modelos, validadores, RAG y un controlador que decide.
    • Spec, Código y Tests deben mantenerse sincronizados; la trazabilidad y decisiones registradas son críticas.

    Introducción

    Poca gente lo dice claro: no es que los LLMs sean malos. Es que los estamos soltando sin reglas. Y rápido.
    Eso se nota cuando el triángulo Spec — Código — Tests se desincroniza a ritmo algorítmico. Y adivina qué aparece primero: deuda técnica.

    Claire Le Goues en CMU lo adelantó hace años. No es novedad; es evolución. Reparación automática de programas y análisis de cobertura no son juguetes académicos. Son la columna vertebral de cualquier agente que quiera escribir código que aguante en producción.

    Lo que estamos construyendo hoy se llama Compound AI. Y si lo manejas mal, es una mina.

    Resumen rápido (lectores con prisa)

    Compound AI: orquestación de múltiples modelos, validadores, bases de conocimiento (RAG) y un controlador.
    Úsalo cuando necesites código reproducible, verificable y trazable en producción.
    Importa porque reduce deuda técnica y fallos en producción al exigir specs operables, tests automatizados y decisiones registradas.
    Funciona mediante pipelines: inputs tipados, transformaciones, validación automática y decision logging.

    1) Por qué esto ya no es ML-only

    Los investigadores pueden inventar algoritmos bonitos. Pero la ingeniería de verdad exige cosas aburridas: orquestación de estado, reintentos inteligentes, persistencia de memoria, latencias aceptables y observabilidad.
    Necesitas backends robustos. PaaS. Infra que aguante agentes que lanzan 50 tareas concurrentes y esperan consistencia.

    2) DSPy y la estructuración de llamadas

    Frameworks como DSPy (o lo que quieras llamar ese nivel de orquestación) transforman llamadas LLM en flujos compilables.
    Piensa en DSLs para IA: inputs tipados, outputs comprobables, rutas deterministas. Menos “ensayo y error” y más pipelines reproducibles.

    3) Test-Time Inference y RLMs — lo que no es magia

    En vez de quemar ciclos entrenando eternamente, gastas cómputo en inferencia inteligente.
    Modelos de razonamiento (RLMs) exploran caminos, ejecutan validadores, comparan resultados y devuelven la versión que pasa las pruebas.
    Sí: eso cuesta. Sí: merece la pena cuando lo que quieres no es una demo, sino software que no explote a las 2AM.

    4) ¿Por qué necesitas ingenieros backend (con experiencia en PaaS)?

    Porque la solución no es un notebook de investigación. Es operación:

    • Orquestar estado entre modelos.
    • Persistir trazas y decisiones.
    • Manejar reintentos sin duplicar efectos.
    • Escalar validadores y tests en paralelo.
    • Aislar fallos y hacer rollback automáticos.

    Si tu equipo no tiene esto, el agente será como un aprendiz con acceso root: peligroso.

    5) El Triángulo que manda: Spec, Código, Tests

    Si uno se desincroniza, todo se va a la mierda. Punto.

    • La Spec debe ser operable. Markdown no basta. Necesitas specs con semántica, vinculadas a código y tests.
    • El Código debe exponer por qué existe. No solo el “qué”.
    • Los Tests no son opcionales. Deben ser ejecutados por el pipeline de agente antes de cualquier merge automático.

    Implementación ≠ caja negra. Implementación comunica intención. Y esa intención debe quedar como dato.

    6) Trazabilidad: la regla de oro

    Cada decisión que toma un agente necesita un artefacto: quién, cuándo, por qué, y qué alternativas se descartaron.
    Si el agente aplicó un “hack” para pasar un test, eso no puede quedar en un chat efímero. Tiene que vivir en tu repo, indexable. JSONL. PR metadata. Historia forense.

    ¿Por qué? Porque poder buscar “find all shortcuts” salva horas de debugging y evita que el mismo hack mute millón de veces.

    7) Integración práctica: stack mínimo para empezar hoy

    No necesitas toda una nave espacial. Esto es un MVP operativo:

    • Orquestador: un servicio que planifica pasos y guarda estado (puede ser una pequeña cola + DB).
    • Callers LLM: modelos rápidos (OSS) para edición y modelos potentes (RLM) para verificación.
    • RAG vector DB para contexto y specs.
    • Validadores: linters, pruebas unitarias, integración y un sandbox de ejecución.
    • Decision store: archivo versionado (.decisions.jsonl) por PR.
    • CI que no solo ejecuta tests, sino que verifica que la spec y los tests se actualizaron si el código cambió.

    8) Un flujo mínimo (ejemplo)

    1. Dev escribe o actualiza spec en formato operable.
    2. El agente genera código y propone cambios en una rama.
    3. Pipeline ejecuta tests + validadores.
    4. Agente intenta optimizar. Si aplica un atajo, registra una decisión en .jsonl. Commit falla si no hay artefacto.
    5. Reviewer aprueba la decisión o solicita cambio.
    6. Merge + sync spec/tests/código.

    Sí, agrega fricción. Es la fricción que salva producción.

    9) Herramientas y patrones recomendados

    • Esquemas validados: usa Zod o similar para validar outputs LLM cuando tocas boundaries.
    • Captura de decisiones: .jsonl con campos: id, pregunta, decisión, autor (LLM/humano), timestamp, diff link.
    • Umbrales configurables: “strict” para core, “lenient” para experiments.
    • Rollbacks automáticos: si una decisión se revoca, tus pipelines deben poder revertir o marcar la rama como needing-fix.
    • Observabilidad: traces de latencia, éxito de validadores, número de decisiones por PR.

    10) Cultura, no solo stack

    No automatices los valores. Automatiza la disciplina.
    Si el equipo ve la herramienta como un juez en lugar de asistente, la odiarán. Hazla útil. Hazla pequeña. Hazla punitiva solo cuando tenga que serlo.

    • Regla simple: cada cambio que no sea trivial necesita al menos una línea en la spec o una entrada en el decision log.
    • No más “and let it run and we go answer some email and then we come back and now I get a decision and I’m like, that’s insane. Don’t do that.” Si vas a delegar, que quede registrado.

    11) Riesgos reales y cómo mitigarlos

    • Ruido: Demasiadas decisiones pequeñas saturan. Solución: umbrales y agrupación por categoría.
    • Alucinaciones del LLM: Validadores estrictos y esquemas runtime.
    • Duplicidad de specs: Fragmenta specs por dominio y mantén ownership.
    • Ataques o leak de credenciales: todo secreto rotatable y accesible solo a procesos autorizados.

    12) Qué cambiar en GitHub (si tuvieras la varita mágica)

    • Markdown como entidad semántica. No solo texto.
    • Linkar decisiones ↔ specs ↔ tests ↔ diffs en la UI.
    • Búsqueda por “intención” (por ejemplo: “find decisions that relaxed auth checks”).
    • Hooks nativos que prevengan merges sin decision artifacts.

    13) Resultado: ¿qué ganas si lo haces bien?

    • Menos deuda acumulada.
    • Onboarding más rápido. Nuevos devs leen la historia de decisiones.
    • Automatización sin descontrol.
    • Auditoría real para compliance.
    • Velocidad que no se convierte en caos.

    14) No es sexy. Es efectivo.

    Las grandes respuestas técnicas no son flashes de genialidad. Son procesos con disciplina.
    Tenemos herramientas para bajar esa disciplina a la realidad operativa. Compound AI no es excusa para saltarse pasos. Es oportunidad para formalizarlos.

    ¿Quieres que lo vuelva práctico?
    Puedo:
    – Escribir el template de .jsonl para decisiones.
    – Diseñar el flujo de CI (GitHub Actions) que bloquee merges sin sincronía spec↔tests↔code.
    – Crear un checklist para ponerlo en marcha en 2 semanas.

    Respóndeme “Dame el template” o “Quiero la CI” y te lo entrego listo para copiar.
    Y recuerda: velocidad sin registro es solo una forma elegante de cavar tu propia trampa. Esto no acaba aquí.

    Si quieres avanzar en pipelines, validación y decision logging con ejemplos prácticos y plantillas, revisa los recursos y experimentos de Dominicode Labs. Es una continuación lógica para equipos que quieren pasar de prototipos a procesos operables. Encontrarás ejemplos de decision logs y patrones de integración que encajan con lo expuesto arriba.

    FAQ

    ¿Qué es Compound AI?

    Compound AI es la orquestación de múltiples modelos, herramientas de validación, bases de conocimiento (RAG) y un controlador que decide qué modelo o herramienta usar, cuándo y cómo, para producir resultados reproducibles y verificables.

    ¿Cuándo debo usar validadores estrictos?

    Usa validadores estrictos en componentes core que afectan seguridad, integridad de datos o disponibilidad. Para experimentos o prototipos puedes aplicar umbrales más lenient, pero documentándolo en el decision log.

    ¿Qué debe contener un decision log (.jsonl)?

    Campos mínimos: id, pregunta, decisión, autor (LLM/humano), timestamp y diff link. Debe ser indexable y versionado por PR.

    ¿Cómo evito que el agente aplique hacks sin supervisión?

    Bloquea commits sin artefacto de decisión; ejecuta validadores en CI; exige que cualquier atajo quede registrado en .jsonl y sea revisado por un humano antes del merge.

    ¿Qué cambios mínimos implemento en CI?

    1) Ejecutar tests y validadores automáticamente. 2) Comprobar que specs y tests cambien si el código cambia. 3) Fallar merges que no incluyan decision artifacts.

    ¿Cómo balancear fricción y velocidad?

    Define umbrales configurables: “strict” para core y “lenient” para experiments. Agrupa decisiones pequeñas y aplica políticas de batching para reducir ruido sin sacrificar trazabilidad.

  • Migrar de espec a producción en un día con Claude Code

    Migrar de espec a producción en un día con Claude Code

    De spec a producción en un día: migración real con Claude Code

    Tratar a Claude Code como un “programador más” es la receta para rehacer horas de trabajo. Tratarlo como un equipo paralelo que ejecuta specs precisas es la forma de pasar de spec a producción en un día: migración real con Claude Code. Aquí tienes el flujo probado, las reglas rígidas y los errores que realmente te harán perder el día.

    Resumen rápido (lectores con prisa)

    Claude Code acelera la ejecución técnica cuando recibe specs precisas y sesiones acotadas. Usa un CLAUDE.md versionado, descompone el sistema en módulos con contratos, lanza sesiones por módulo y valida cada handoff antes de integrar. El flujo minimiza errores y permite pasar de spec a producción en un día si se siguen las reglas.

    Tiempo estimado de lectura: 6 min

    • Ideas clave:
    • Claude Code funciona como un ejecutor: especifica antes de ejecutar y valida antes de integrar.
    • Divide la migración en módulos atómicos con contratos y tests incluidos.
    • Usa sesiones acotadas para evitar que el agente “invente” decisiones arquitectónicas.
    • Revisión humana en cada handoff y pipelines de CI por módulo son obligatorios.

    De spec a producción en un día: el patrón que funciona

    Referencias clave

    La diferencia entre una migración rápida y una que se desboca está en la disciplina: especificar antes de ejecutar, fragmentar antes de paralelizar y validar antes de integrar. Claude Code acelera ejecución; no reemplaza la necesidad de criterio humano para tomar decisiones arquitectónicas.

    A continuación, el flujo operativo que equipos reales usan para migrar en un día sin incendios.

    Fase 0 — Precondición: el contrato de proyecto

    Antes de cualquier línea de código, publica o actualiza un CLAUDE.md en la raíz del repo con:

    • Stack, comandos y convenciones (ej.: pnpm, TypeScript strict, patrón de servicios).
    • Patrones prohibidos y límites de seguridad.
    • Comandos de CI y thresholds de tests.

    Claude Code incorpora este archivo al contexto inicial; sin él, el agente inventa decisiones. Mantén el CLAUDE.md versiónada y sincronizado con cualquier cambio de stack.

    Fase 1 — Spec de arquitectura (1–2 horas)

    El líder técnico escribe la spec: estado actual, objetivo, invariantes y una descomposición en módulos con contratos públicos.

    Resultado concreto:

    • Lista de módulos atómicos y su orden (dependencias DAG).
    • Para cada módulo: signature, DTOs, efectos secundarios permitidos, criterios de aceptación automáticos y manuales.

    Ejemplo simple para migrar API REST a tRPC:

    • Módulo A: AuthService — createSession(userCreds): SessionDto
    • Módulo B: UserService — getUser(id): UserDto (depende de AuthService)
    • Módulo C: Billing — charge(accountId, amount): ChargeResult (depende de UserService)

    La spec es el contrato. Nada se implementa sin ella.

    Fase 2 — Implementación paralela con sesiones acotadas (3–4 horas)

    Lanza sesiones independientes de Claude Code por módulo. Cada sesión recibe:

    1. CLAUDE.md.
    2. Spec del módulo (requirements, design, tasks, acceptance).
    3. Lista de tareas atomizadas (crear tipos, implementar funciones, tests unitarios).

    Reglas de sesión:

    • Mínimo contexto: solo archivos relevantes y la spec del módulo.
    • Tasks atómicas y verificables: “añadir interfaz X” > “implementar función Y”.
    • Tests deben ser parte de la entrega. Claude produce código + tests.

    Ventaja: el agente no necesita retener todo el repo, evita “alucinaciones” arquitectónicas y produce artefactos integrables.

    Fase 3 — Handoff e integración (1–2 horas)

    Cada módulo terminado pasa por revisión humana contra la spec. Validaciones rápidas:

    • ¿Las firmas coinciden con las prometidas?
    • ¿Se respetaron patrones prohibidos del CLAUDE.md?
    • ¿Los tests pasan y la cobertura cumple el mínimo definido?

    Integración:

    • Merge secuencial según DAG de dependencias.
    • Ejecutar builds e integración continua en cada step.
    • Resolver conflictos de API con parches mínimos, volver a ejecutar tests.

    Si algo falla, el alcance de la corrección está acotado al módulo fallido. No es necesario rehelar toda la migración.

    Fase 4 — Regresión y criterios de producción (2 horas)

    Pruebas que deben pasar antes de deploy:

    • Tests unitarios y de integración: cobertura igual o superior al sistema legado por módulo.
    • Pruebas end-to-end en flujos críticos.
    • Métricas de performance (p95) dentro de los límites definidos en la spec.
    • Auditoría: sin dependencias nuevas no autorizadas, sin uso de patrones prohibidos.

    Solo cuando todo esto pasa y la revisión humana valida, se programa el deploy.

    Qué falla cuando fallas el proceso (anti-patrones)

    – Enviar una spec ambigua. Resultado: implementaciones rápidas pero inconsistentes.

    – Hacer una sesión única y global. Resultado: contexto saturado y decisiones implícitas.

    – No versionar CLAUDE.md. Resultado: el agente aplica reglas obsoletas con más fe que un humano.

    Checklist práctico para tu primer día de migración

    • [ ] CLAUDE.md actualizado y en la raíz.
    • [ ] Spec de arquitectura con módulos y contratos firmados.
    • [ ] Tasks atomizadas por módulo y asignadas a sesiones de Claude Code.
    • [ ] Validaciones automáticas y criterios de aceptación escritos en la spec.
    • [ ] Revisión humana planificada para cada handoff.
    • [ ] Pipeline de CI preparado para integración continua por módulo.

    Cierre: por qué esto no es solo “más rápido”

    La velocidad que trae Claude Code es real. Pero el verdadero valor viene de transformar la práctica: dividir el trabajo, especificar contratos y establecer handoffs claros. Si ejecutas el flujo como equipo (humano + agente), pasar de spec a producción en un día deja de ser una promesa de marketing y se convierte en un patrón repetible.

    En la próxima publicación compartiremos una plantilla de spec y un ejemplo real de CLAUDE.md listo para copiar/pegar que puedes usar en tu primer experimento de migración con Claude Code.

    FAQ

     

     

    ¿Qué es CLAUDE.md y por qué es obligatorio?

    CLAUDE.md es un archivo en la raíz del repositorio que contiene el stack, comandos, convenciones, patrones prohibidos y thresholds de CI. Es obligatorio porque Claude Code incorpora este archivo al contexto inicial; sin él, el agente puede “inventar” decisiones arquitectónicas.

    ¿Cuánto contexto debe recibir cada sesión de Claude Code?

    Cada sesión debe recibir el contexto mínimo necesario: el CLAUDE.md, la spec del módulo y solo los archivos relevantes. Reducir el contexto evita alucinaciones arquitectónicas y decisiones implícitas.

    ¿Qué deben incluir las tareas atomizadas?

    Las tareas deben ser verificables y pequeñas: crear tipos, implementar funciones concretas, añadir tests unitarios. Ejemplos: “añadir interfaz X” o “implementar función Y”.

    ¿Qué validaciones humanas son imprescindibles?

    Revisiones rápidas contra la spec: firmas de API, cumplimiento de patrones prohibidos en CLAUDE.md, que los tests pasen y que la cobertura cumpla los mínimos definidos.

    ¿Cómo se gestiona la integración cuando un módulo falla tests?

    Si un módulo falla, el alcance de corrección se acota a ese módulo. Se corrige, se vuelve a ejecutar tests y se reintegra según el DAG de dependencias, sin rehacer toda la migración.

    ¿Por qué evitar sesiones globales con el agente?

    Las sesiones globales saturan el contexto del agente y llevan a decisiones implícitas y variedad de implementaciones inconsistentes. Las sesiones acotadas garantizan consistencia y verificabilidad.

  • Cuándo usar Zod en lugar de TypeScript para validación en runtime

    Cuándo usar Zod en lugar de TypeScript para validación en runtime

    Zod vs TypeScript puro: cuándo usar validación en runtime

    ¿Confías en TypeScript para proteger tu app en producción? Deja de hacerlo. TypeScript es un analizador estático; su trabajo termina cuando el código se compila. Si quieres seguridad real en ejecución necesitas otra cosa. Aquí va la guía práctica: Zod vs TypeScript puro: cuándo usar validación en runtime.

    TypeScript ordena tu código. Zod protege tus fronteras. Úsalos juntos, no en guerra.

    Tiempo estimado de lectura: 4 min

    • TypeScript es un analizador estático: no protege en runtime.
    • Zod parsea en runtime y mantiene una sola fuente de verdad con z.infer.
    • Valida en las fronteras (endpoints, webhooks, env, uploads); confía en TypeScript dentro del dominio.
    • Mide impacto de rendimiento y evita validaciones redundantes en el core.

    ¿Confías en TypeScript para proteger tu app en producción? Deja de hacerlo. TypeScript es un analizador estático; su trabajo termina cuando el código se compila. Si quieres seguridad real en ejecución necesitas otra cosa. Aquí va la guía práctica: Zod vs TypeScript puro: cuándo usar validación en runtime.

    Resumen rápido (lectores con prisa)

    Qué es: Zod es una librería de validación y parsing en runtime; TypeScript es un sistema de tipos estático.

    Cuándo usarlo: Usa Zod en las fronteras (endpoints, webhooks, env, uploads); usa TypeScript dentro del dominio.

    Por qué importa: TypeScript sufre type erasure y no impide fallos en producción; Zod parsea y falla rápido.

    Cómo usarlo: Definir esquemas Zod, derivar tipos con z.infer y parsear payloads en los handlers.

    Por qué TypeScript no basta (y dónde duele más)

    TypeScript tiene un problema estructural: Type Erasure. Los tipos desaparecen al compilar. Eso significa que las aserciones (as T) son mentiras que el compilador acepta y la app paga en runtime.

    interface Usuario { id: number; email: string; }
    
    const datos = await respuesta.json() as Usuario;
    console.log(datos.email.toLowerCase()); // Boom si email no existe
    

    Si la API cambia, o devuelve HTML en un error 500, tu código explota. TypeScript no está ahí para detenerlo.

    Zod y el principio “Parse, don’t validate”

    Zod opera en runtime. Su filosofía es clara: no intentes “validar” por inercia; parsea y falla rápido.

    import { z } from 'zod';
    
    const UsuarioSchema = z.object({
      id: z.number(),
      email: z.string().email(),
    });
    
    type Usuario = z.infer;
    
    const res = await fetch(url);
    const raw = await res.json();
    const usuario = UsuarioSchema.parse(raw); // lanza si algo falla
    console.log(usuario.email.toLowerCase());
    

    Con z.infer mantienes una sola fuente de verdad: el esquema. Nada de duplicar interfaces y validadores.

    safeParse vs parse

    Si quieres manejo de errores controlado:

    const result = UsuarioSchema.safeParse(raw);
    if (!result.success) {
      // logging, métricas, respuesta 400 al cliente...
      throw new Error('Payload inválido');
    }
    const usuario = result.data;
    

    safeParse devuelve un objeto con success y error para flujos menos crudos.

    Dónde aplicar validación (regla práctica)

    No todo necesita Zod. La regla del arquitecto es simple:

    • Valida en runtime en las fronteras: entrada HTTP, webhooks, archivos subidos, variables de entorno, LocalStorage.
    • Confía en TypeScript dentro del dominio: funciones internas, paso de props entre componentes, mutaciones internas en stores tipados.

    Aplicar Zod en todas partes degrada rendimiento y readability. No validar en las fronteras te expone a fallos catastróficos.

    Casos prácticos y patterns

    1) Respuesta API (backend → frontend o backend → backend)

    • Parsea siempre antes de usar.
    • Registra el error y devuelve 400 o fallback claro.

    2) Webhooks / n8n / automatizaciones

    • Parsea y verifica firma si aplica.
    • Rechaza rápido para evitar procesar datos corruptos.

    3) Variables de entorno en arranque (ejemplo con Zod)

    const EnvSchema = z.object({
      DATABASE_URL: z.string().url(),
      NODE_ENV: z.enum(['development','production']),
    });
    const env = EnvSchema.parse(process.env);
    

    Arranque fallido = fallo visible y evitar estados inconsistentes.

    4) Formularios en frontend

    Integra Zod con React Hook Form para validar antes de mutar el estado o enviar al servidor.

    Coste y alternativas: cuándo preocuparse por rendimiento

    Zod añade CPU y peso al bundle. En la mayoría de apps esto es irrelevante frente a la estabilidad que gana tu producto. En sistemas de altísima demanda (millones de eventos por segundo) evalúa alternativas más ligeras o validaciones a medida.

    Alternativas emergentes existen, pero la elección debe basarse en mediciones. No te cases con una librería sin perf tests en tu caso real.

    Integración práctica: patrón recomendado

    1. Punto de entrada (API handler, webhook) → Zod parse
    2. Convertir a tipos con z.infer → pasar al core tipado con TypeScript
    3. Lógica interna → TypeScript puro, sin comprobaciones redundantes
    4. En el cliente, validar inputs críticos; en el servidor, validar todo lo externo

    Conclusión y pasos accionables

    • Zod y TypeScript no son excluyentes. TypeScript organiza tu código; Zod lo hace seguro en producción.
    • Si tienes que elegir hoy, empieza por defender las fronteras: añade validación Zod en endpoints y webhooks.
    • Usa z.infer para que el tipo estático derive del esquema y mide impacto.

    Recuerda: el compilador no vive en producción. Tú sí. Protege lo que importa.

    Prueba esto ahora: añade un esquema Zod a uno de tus endpoints y corre safeParse con un payload inesperado. Verás la diferencia. Esto no acaba aquí; la próxima nota tratará cómo estructurar esquemas Zod para versiones y migraciones sin romper consumidores.

    FAQ

    ¿TypeScript protege mi app en producción?

    No. TypeScript es un analizador estático y sus tipos desaparecen al compilar (type erasure). No impide que datos inválidos lleguen a runtime.

    ¿Qué es Zod y por qué usarlo?

    Zod es una librería de validación y parsing en runtime. Su filosofía es “parse, don’t validate”: parsea datos y falla rápido si no coinciden con el esquema, evitando errores silenciosos en producción.

    ¿Cuándo usar parse vs safeParse?

    Usa parse cuando quieras que el proceso lance inmediatamente y falle rápido. Usa safeParse para manejar errores de forma controlada (logging, métricas, respuesta 400) sin exceptions no controladas.

    ¿Dónde aplicar validación en mi arquitectura?

    Valida en las fronteras: endpoints HTTP, webhooks (p. ej. n8n), archivos subidos, variables de entorno, y LocalStorage. Dentro del dominio confía en TypeScript y evita validaciones redundantes.

    ¿Zod impacta tanto el rendimiento?

    Zod añade CPU y peso al bundle, pero en la mayoría de apps el coste es aceptable frente a la estabilidad que aporta. En sistemas de altísima demanda evalúa alternativas más ligeras y mide con perf tests.

    ¿Cómo integrar Zod con TypeScript sin duplicar tipos?

    Define esquemas Zod y deriva los tipos estáticos con z.infer. Así mantienes una sola fuente de verdad: el esquema.

  • Cómo evitar memory leaks en aplicaciones Angular

    Cómo evitar memory leaks en aplicaciones Angular

    Frontend Memory Leaks y como evitarlo en Angular

    Tiempo estimado de lectura: 3 min

    • Identifica suscripciones, listeners y timers que sobreviven a componentes.
    • Prefiere async pipe y herramientas integradas (takeUntilDestroyed) para evitar fugas.
    • Diagnostica con Chrome DevTools: heap snapshots y comparación de instancias.
    • Disciplina de equipo: code review, linters y políticas de invalidación en singletons.

    Introducción

    ¿Tu SPA se vuelve lenta sin error en consola? Frontend Memory Leaks y como evitarlo en Angular debería ser parte de tu checklist antes de enviar a producción. Si no controlas referencias, suscripciones y listeners, la app “come” memoria hasta que la pestaña muere.

    Resumen rápido (lectores con prisa)

    Qué es: Objetos no referenciados siguen vivos y el Garbage Collector no los elimina.

    Cuándo usar: Siempre que tu SPA cree y destruya componentes, gestiona suscripciones, listeners y timers.

    Por qué importa: Fugas causan degradación silenciosa de rendimiento en sesiones largas y móviles.

    Cómo funciona: Evita referencias persistentes: async pipe, takeUntilDestroyed, Renderer2 y limpieza en ngOnDestroy.

    Frontend Memory Leaks y como evitarlo en Angular: qué pasa y por qué importa

    Un memory leak ocurre cuando objetos que ya no necesitas siguen referenciados y el Garbage Collector no los elimina. En Angular esto duele más: la app vive sin recargas, los componentes se crean y destruyen, y cualquier referencia residual se acumula en el heap.

    No es magia ni culpa del navegador: es disciplina de código. Y sí, pasa en producción, en móviles y en equipos con pestañas cientos abiertas.

    Fuentes útiles:

    Vectores comunes y cómo cerrarlos

    Suscripciones RxJS sin gestionar

    • Qué pasa: .subscribe() vive más que el componente. El callback mantiene la instancia viva.
    • Soluciones: Async pipe (templates), takeUntilDestroyed() en Angular 16+, o takeUntil con un destroy$ en versiones anteriores.
    • Docs: RxJS takeUntil ; Angular rxjs-interop

    Event listeners globales

    Qué pasa: window.addEventListener('resize', fn) sin removeEventListener mantiene la referencia.

    Solución: usar Renderer2.listen() (retorna un unlisten) o guardar la referencia y llamarla en ngOnDestroy().

    Timers (setInterval, setTimeout)

    Qué pasa: un timer que cierra sobre this impide la recolección.

    Solución: almacenar el id y clearInterval/clearTimeout en ngOnDestroy().

    Servicios singleton con datos retenidos

    Qué pasa: providedIn: 'root' vive toda la sesión; si almacenas grandes estructuras sin limpieza, la memoria crece.

    Solución: políticas explícitas de invalidación / límites / weak references lógicas.

    Patrones prácticos (código)

    Async pipe — la opción más simple

    <!-- template -->
    <div *ngIf="data$ | async as data">{{ data.title }}</div>
    

    El async se suscribe y se desuscribe automáticamente cuando el componente muere.

    takeUntilDestroyed() — Angular 16+ (recomendado para TS)

    import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
    
    this.service.stream()
      .pipe(takeUntilDestroyed())
      .subscribe(x => this.handle(x));
    

    Patrón clásico (Angular <16)

    private destroy$ = new Subject<void>();
    
    ngOnInit() {
      this.service.stream()
        .pipe(takeUntil(this.destroy$))
        .subscribe(...);
    }
    
    ngOnDestroy() {
      this.destroy$.next();
      this.destroy$.complete();
    }
    

    Listeners con Renderer2

    private unlisten: () => void;
    
    ngOnInit() {
      this.unlisten = this.renderer.listen('window', 'scroll', this.onScroll.bind(this));
    }
    
    ngOnDestroy() {
      this.unlisten?.();
    }
    

    Timers

    private intervalId?: ReturnType<typeof setInterval>;
    
    ngOnInit() {
      this.intervalId = setInterval(() => this.poll(), 5000);
    }
    
    ngOnDestroy() {
      clearInterval(this.intervalId);
    }
    

    Cómo diagnosticar fugas — proceso práctico

    1. Abre Chrome DevTools → Memory (Chrome DevTools Memory).
    2. Toma Heap Snapshot.
    3. Navega al componente sospechoso, repite la interacción que crees filtra memoria.
    4. Regresa y toma otro snapshot.
    5. Compara: si ves instancias de tu componente o Detached DOM nodes, hay fuga.

    Allocation timeline te muestra crecimiento en tiempo real: una línea que solo sube y no baja es una mala señal.

    Política de equipo: lo que realmente previene fugas

    Esto no es sólo técnica, es disciplina:

    • Regla: preferir Async Pipe cuando sea posible.
    • Regla: toda suscripción en clase debe documentarse: ¿se cancela? ¿por quién?
    • Code reviews: busca .subscribe( sin takeUntil / takeUntilDestroyed o sin async.
    • Linters y tareas CI: detecta patrones peligrosos (por ejemplo .subscribe( sin unsubscribe en componentes).
    • Tests de rendimiento en CI: integra un paso de e2e que simule navegación repetida y monitorice memoria.

    Cierre: no cures síntomas, cambia hábitos

    Un memory leak no es un bug aislado; es deuda técnica que crece silenciosamente. Angular te da herramientas —async pipe, takeUntilDestroyed, Renderer2— pero depende del equipo usarlas consistentemente.

    Si quieres, en Dominicode podemos publicar una checklist de code-review y un snippet de ESLint que detecte suscripciones peligrosas. No te prometo magia: te prometo menos pestañas explotando. Apúntate y seguimos.

    FAQ

    ¿Qué es un memory leak?

    Un memory leak ocurre cuando objetos que ya no necesitas siguen referenciados y el Garbage Collector no los elimina. En una SPA esto provoca acumulación de memoria en el heap mientras la sesión continúa.

    ¿Cómo detectarlo en Angular?

    Usa Chrome DevTools → Memory: toma heap snapshots antes y después de interacciones repetidas. Busca instancias de componentes o Detached DOM nodes que no desaparecen.

    ¿Cómo manejar suscripciones RxJS?

    Prefiere async en templates, o en código use takeUntilDestroyed() (Angular 16+) o takeUntil con un destroy$ y limpieza en ngOnDestroy().

    ¿Y los listeners globales?

    No uses addEventListener sin remover. Usa Renderer2.listen() y llama al “unlisten” en ngOnDestroy().

    ¿Qué hacer con timers e intervalos?

    Guarda los ids retornados por setInterval/setTimeout y llama a clearInterval/clearTimeout en ngOnDestroy().

    ¿Los servicios singleton pueden filtrar memoria?

    Sí. Los servicios providedIn: 'root' viven toda la sesión; si almacenan grandes estructuras sin limpieza la memoria crece. Define políticas de invalidación y límites.