AirtableCleanup: Transformación Schema-Driven y Rediseño del Skill de Cierre Inteligente
La jornada de hoy se centró en dos frentes críticos: la evolución de nuestra herramienta AirtableCleanup de una solución hardcodeada a una arquitectura schema-driven y el rediseño fundamental del skill de cierre para nuestras herramientas de IA. El objetivo principal era dotar a estas herramientas de una inteligencia contextual y una flexibilidad sin precedentes, permitiéndoles adaptarse a cualquier base de datos o conversación sin intervención manual. Queríamos pasar de datos crudos a razonamiento procesable, tanto en la interfaz de usuario como en el registro de sesiones.
Qué hicimos
Arquitectura AirtableCleanup
- Migración a schema-driven: Abandonamos la UI estática y hardcodeada en el frontend. Ahora, la herramienta AirtableCleanup consume el esquema real de cualquier base de datos Airtable a través de un endpoint
/api/schemaexpuesto por el servidor. Esto permite que la interfaz de usuario se renderice dinámicamente, adaptándose a los campos y tipos de datos de la base conectada sin necesidad de modificar el código del cliente. Este cambio fue crucial para la universalización de la herramienta. - Integración de prompts de extracción: Desarrollamos e integramos prompts específicos para la extracción de datos desde transcripciones de llamadas. Estos prompts utilizan el esquema real de Airtable, lo que garantiza que la información extraída se alinee con la estructura de la base de datos de destino, un paso vital para la automatización de procesos de seguimiento de conversaciones con clientes.
- Búsqueda de grupos en tiempo real: Implementamos un filtro de grupos de duplicados directamente en el lado del cliente, eliminando la necesidad de roundtrips al servidor para cada búsqueda. Una decisión técnica clave fue preservar los índices originales del array de grupos durante el filtrado. Esto era fundamental porque las acciones como
markGroup,dismissysetMasterdependen de esos índices para operar correctamente sobre los datos subyacentes, evitando la ruptura de referencias al manipular la vista. - Scaffold de skill de cierre universal: Se sentaron las bases para un scaffold de un skill de cierre universal (SKILL.md). El objetivo era estandarizar el proceso de registro de cierre entre distintos repositorios de proyectos, permitiendo una visión consistente de las sesiones de trabajo.
Rediseño del Skill de Cierre (Claude Code Skills)
- Frontmatter YAML obligatorio en contenido: Se introdujo un requisito para incluir un frontmatter YAML estructurado en el contenido de cada entrada del Segundo Cerebro. Campos como
title,date,proyecto,git,tipo,descripcion,aprendizajeytagsson ahora mandatorios. Esto permite una indexación, categorización y búsqueda eficiente de los registros de sesión, transformando un volcado de texto en un sistema de memoria consultable. - Permisos específicos para la autonomía: Tras experimentar con
bypassPermissionsglobal, que representaba un riesgo de seguridad significativo al otorgar acceso irrestricto a todas las sesiones de IA, revertimos a un modelo de permisos explícitos. Ahora, el skill de cierre solo tiene acceso a comandos específicos deBashcomogit:*,python:*ycurl:*. Esto garantiza la autonomía necesaria para operar sin comprometer la seguridad general del sistema. - Diferenciación entre cierre manual e inteligente: Se clarificó la distinción entre un script de cierre diario (
cierre_diario.py) y el skill de cierre manual. El script automatiza la recolección de commits de 24 repositorios, útil para un registro básico, pero no reemplaza al skill manual, que tiene acceso al contexto completo de la conversación de la IA y puede generar un análisis inteligente. - Rediseño del contenido del skill de cierre: La mejora más significativa fue la transformación del campo
contentdel skill de cierre. Dejó de ser una simple lista de commits para convertirse en un análisis estructurado de la sesión. Ahora incluye secciones detalladas como el problema resuelto, las decisiones tomadas y sus razones, lo que no funcionó, los logros concretos, los aprendizajes reales y el contexto de los pendientes. Este cambio eleva el registro del Segundo Cerebro de una mera bitácora a una base de conocimiento procesable.
El problema real
El desafío más crítico surgió de dos frentes interconectados. Primero, la versión inicial de AirtableCleanup estaba inherentemente limitada por su diseño hardcodeado, lo que la hacía inútil para cualquier base Airtable que no fuera la específica para la que fue creada. Esto implicaba que cada nueva base requería una modificación manual del código fuente, una barrera significativa para su escalabilidad y utilidad universal.
En paralelo, nuestro skill de cierre original para las herramientas de IA generaba un historial de sesiones ineficaz. La salida se limitaba a listas de commits de Git y nombres de archivos, datos que, si bien son crudos y precisos, carecían del contexto y el razonamiento detrás de las decisiones. Este "historial" era inútil para entender por qué se había hecho algo en retrospectiva, ya que no capturaba la esencia de la conversación o el proceso de pensamiento de la IA. Intentar utilizar un planificador de tareas (Task Scheduler) para un cierre "inteligente" falló precisamente por esto: un script automatizado carece de la capacidad de interpretar y contextualizar una conversación.
Adicionalmente, se encontró un bug sutil en la lógica de formatFieldValue de AirtableCleanup: los arrays de registros vinculados (linked records) podían llegar como null, a pesar de que el esquema los declaraba como arrays. JavaScript, por defecto, no inicializa campos opcionales, lo que resultaba en fallos en producción cuando se intentaba iterar sobre un valor null como si fuera un array.
Cómo lo resolvimos
Para AirtableCleanup, la solución fue una reingeniería completa hacia un modelo schema-driven. En lugar de hardcodear los campos en el cliente, desarrollamos un endpoint de servidor (/api/schema) que expone el esquema real de Airtable. El frontend consume este esquema y construye la UI dinámicamente, eliminando la necesidad de cambios de código para cada base de datos. Para el bug de los linked records, se implementó un null check explícito en formatFieldValue (value?.map(...) o un if (value)), lo que garantizó que el procesamiento solo ocurriera si el valor no era nulo, previniendo los crashes. La búsqueda en tiempo real se resolvió con un filtro client-side que, crucialmente, preservaba los índices originales de los grupos, asegurando que las acciones subsiguientes pudieran referenciar correctamente los elementos.
Para el skill de cierre, la solución fue transformar radicalmente su propósito y su salida. Se abandonó la generación de listas de commits en favor de un análisis estructurado de la conversación. Esto se logró al imponer un frontmatter YAML con metadatos obligatorios y al redefinir el template de content para que incluyera secciones como "problema resuelto", "decisiones tomadas y por qué", "lo que no funcionó" y "aprendizajes reales". Este nuevo formato obliga a la IA a contextualizar su trabajo, transformando los datos crudos en razonamiento. La seguridad se abordó reemplazando bypassPermissions global con una lista explícita y granular de permisos (Bash(git:*), Bash(python:*), etc.), mitigando el riesgo sin sacrificar la autonomía del skill. Se clarificó que un script ciego no puede automatizar la inteligencia, lo que consolidó la necesidad del skill de cierre manual para la verdadera contextualización de la sesión.
Aprendizaje
El valor de un sistema de memoria no reside en la acumulación de datos crudos, sino en la capacidad de capturar y recuperar el razonamiento detrás de cada decisión. Sin ese contexto del "por qué", el historial de proyectos se vuelve inútil en cuestión de meses, imposibilitando la auditoría, la mejora continua y el aprendizaje organizacional. El enfoque schema-driven para interfaces es una dirección correcta, pero exige una gestión robusta de la autenticación en el servidor y la exposición de endpoints tipados que sirvan como fuente única de verdad para la UI. Además, la manipulación de datos indexados en búsquedas filtradas exige un cuidado extremo: filtrar una vista no es lo mismo que filtrar los datos subyacentes, y la referencia a índices debe mantenerse intacta para que las acciones sobre esos datos sigan siendo coherentes. Finalmente, la experiencia nos reconfirma que los campos opcionales, especialmente arrays o linked records de APIs externas, deben ser tratados con null checks explícitos, ya que la ausencia de datos no siempre se traduce en un array vacío, sino en un valor null que puede romper la ejecución.