Buscar/Modifica una gran base de código de runtime multilenguaje sin romper el comportamiento existente

Modifica una gran base de código de runtime multilenguaje sin romper el comportamiento existente

Para un gran proyecto de runtime nativo y de scripts con dependencias incorporadas y parcheadas. La IA lee primero la guía más cercana, usa los atajos de compilación y prueba, sigue sus tipos propios y prohibiciones, y pone los cambios tras indicadores de compatibilidad.

Para usar estas reglas de IA
## Lee la guía más cercana al código y comprueba si hay un proyecto padre La documentación de orientación en este tipo de repositorio está organizada por capas. Una guía raíz ofrece una orientación de alto nivel; las guías situadas dentro de los subdirectorios aportan contexto específico de cada componente, como las clases clave, tablas de dónde buscar, convenciones locales y antipatrones. Lee siempre la guía más cercana al código que vas a tocar, además de la guía raíz. - Determina siempre si el repositorio se ha clonado de forma independiente o si está anidado como componente de un proyecto padre mayor. Si está anidado, hay documentación importante que reside en la raíz del proyecto padre y que no es visible desde aquí; lee el readme del padre, la guía del padre y los demás documentos de nivel superior antes de dar nada por supuesto. - Investiga y lee con libertad, pero reúne este contexto antes de proponer o realizar cambios. - Cuando descubras información de alto nivel duradera que falte en las guías, propón añadirla en lugar de dejarla únicamente en la conversación. ## Compila y prueba con los atajos del proyecto, no con comandos improvisados El proyecto tiene un único sistema de compilación de referencia más una capa ligera de atajos gestionada por un ejecutor de tareas. Usa los atajos para el trabajo del día a día y baja a la herramienta de compilación subyacente solo cuando un atajo no exponga la opción que necesitas. No improvises comandos de compilación ad hoc. Atajos habituales que conviene buscar y reutilizar: compilar, ejecutar todas las pruebas, formatear, analizar el código de los lenguajes de scripting, analizar el código nativo, analizar los paquetes del lenguaje de sistemas, transmitir la salida de las pruebas para depurar, ejecutar una única suite de compatibilidad o de conformidad, generar el esqueleto de una prueba nueva, generar definiciones de tipos, generar la base de datos de índices del editor, compilar y probar con el sanitizador de direcciones, producir un informe de cobertura y vigilar los directorios de código fuente para volver a ejecutar un comando cuando haya cambios. ## Encuentra el destino de prueba correcto y sus variantes automáticas Coexisten varias familias de pruebas y cada una tiene su propio punto de entrada: - Pruebas de integración dirigidas por configuración: un archivo de configuración serializado que declara un servicio con módulos de script embebidos, una fecha de compatibilidad, indicadores de funcionalidad y enlaces tales como enlaces de servicio, datos estructurados, almacenes de clave-valor y espacios de nombres de objetos con estado. - Pruebas unitarias nativas construidas mediante una macro dedicada, con un sufijo de prueba separado por guion en el nombre del archivo. - Suites de compatibilidad del runtime y suites de conformidad con los estándares web, cada una ejecutada por nombre. - Bancos de pruebas de rendimiento, ejecutados por ruta. Tanto el comando de compilación como el de pruebas aceptan destinos explícitos y, por defecto, abarcan todo el árbol. Los nombres de destino llevan un marcador de sufijo obligatorio, y las macros de compilación generan automáticamente varias variantes por prueba: una variante predeterminada fijada a la línea base de compatibilidad más antigua, una variante en la fecha más reciente con todos los indicadores activados y una variante con todas las compuertas temporales activadas. Para encontrar el destino correcto de un archivo, lee el archivo de compilación del mismo directorio o consulta al sistema de compilación todos los destinos de ese paquete. ## Ubica las áreas principales del código y sigue una implementación parecida Construye un mapa mental antes de editar y, para cualquier trabajo nuevo, busca una implementación existente parecida y sigue su patrón. - API del runtime: implementaciones nativas de las interfaces expuestas a los scripts, más la capa de compatibilidad con la biblioteca estándar y sus pruebas. - Subsistema de entrada/salida: almacenamiento y almacenamiento en caché de objetos con estado, seguimiento de solicitudes, límites de recursos, hilos y ciclo de vida de los trabajadores. Un objeto de contexto por solicitud mantiene unida toda la solicitud. - Capa de pegamento: enlaces con el motor, envoltorios de tipos, gestión de promesas, gestión de memoria y el sistema de módulos. - Capa de servidor: el punto de entrada del binario y el tratamiento de la configuración, con un modelo de seguridad basado en capacidades descrito mediante un archivo de esquema. - Árboles específicos de cada lenguaje para la capa de compatibilidad, un runtime de scripting alternativo y los componentes de integración con el lenguaje de sistemas. Las capas de compatibilidad son duales: la mitad nativa reside en un árbol y la mitad de scripting en otro, y los módulos nuevos deben registrarse en la tabla de módulos designada. Las definiciones de tipos se derivan de la información de tipos nativa más declaraciones escritas a mano y se regeneran; nunca se editan a mano. ## Sigue la guía de estilo y haz commits pequeños que pasen las pruebas Sigue la guía de estilo interna a la que se hace referencia, incluidas sus excepciones documentadas; allí donde el proyecto se desvíe deliberadamente de esa guía, la desviación es la norma. - Ajústate exactamente al estándar de lenguaje fijado, a las extensiones poco habituales de los archivos fuente del proyecto y al sufijo con guion de los archivos de prueba. - Un único comando de formateo ejecuta todos los formateadores en todos los lenguajes. Ejecútalo, junto con el comando completo de pruebas, antes de enviar un cambio. - Una comprobación previa al commit bloquea las macros de impresión de depuración en el código preparado y vuelve a ejecutar la verificación de formato. No la sortees. - Divide los cambios en commits pequeños; cada commit debe compilar y superar las pruebas por sí solo. No dejes commits de corrección posterior. - Los archivos fuente del lado de scripting están tipados de forma estricta: se exigen la semántica exacta de propiedades opcionales, la sintaxis de campos privados y los tipos de retorno explícitos. ## Usa los tipos de la biblioteca base propia en lugar de los estándar La base de código utiliza deliberadamente su propia biblioteca base en lugar de la biblioteca estándar del lenguaje para la mayoría de los tipos. Adáptate al archivo que te rodea en vez de recurrir a los contenedores estándar. Sustituciones que hay que aplicar: cadena con propiedad y vista de cadena sin propiedad en lugar de la cadena estándar; array de tamaño fijo y vector expandible en lugar del vector estándar; identificadores de propiedad únicos, con recuento de referencias, con recuento de referencias seguro para hilos y débiles en lugar de los punteros inteligentes estándar; un tipo maybe en lugar de optional; un envoltorio invocable en lugar del objeto función estándar; una unión etiquetada en lugar de variant; una porción de array en lugar de los spans en crudo; el tipo de excepción de la biblioteca; y la promesa de la biblioteca y la promesa bifurcada en lugar de los futures estándar. Por seguridad, prefiere una porción de array antes que un puntero en crudo, y un identificador ligado al tiempo de vida antes que una referencia desnuda cuando la referencia esté ligada al tiempo de vida del propietario. Para los errores, usa la macro dedicada para desenvolver un maybe, las macros de requisito orientadas a scripts cuando el fallo deba manifestarse como una excepción de script con un tipo de excepción adecuado, y las macros nativas de aserción y precondición para las invariantes internas. ## Evita los patrones prohibidos que causan fugas y daños ocultos Estas reglas son absolutas; incumplirlas provoca corrupciones sutiles, fugas o rupturas de compatibilidad. - Nunca coloques identificadores locales o globales del motor dentro de declaraciones de estructuras de tipo valor; usa los envoltorios de referencia proporcionados. - Nunca coloques identificadores del motor dentro de tipos promesa, y nunca pases el bloqueo del motor a corrutinas asíncronas. - Nunca mantengas referencias del montón de scripts a objetos de entrada/salida sin el envoltorio propietario; un guardián de ámbito lo impone. - Prefiere las propiedades de prototipo antes que las propiedades de instancia, que anulan la optimización del recolector de basura. - Nunca congeles en profundidad contenido proporcionado por el usuario, algo inseguro con valores cíclicos. - Nunca añadas métodos a una interfaz que despacha nombres desconocidos de forma remota sin protegerlos tras un indicador de compatibilidad, y nunca cambies los valores serializados de una enumeración. - Prefiere la llamada aditiva de registro de tareas antes que el descriptor de acceso a la lista de tareas en crudo, y evita los parámetros booleanos en favor de tipos booleanos fuertes. - Toda referencia almacenada en un objeto nativo accesible desde el montón de scripts debe implementar la visita del recolector de basura; los ciclos de referencias nativas nunca se recolectan. Una comprobación de análisis estático dedicada valida esto. - Los errores por uso indebido de la base de datos embebida siempre lanzan excepción y nunca se suprimen; las transacciones no se permiten en la base de datos de objetos con estado. - La evaluación de módulos nunca debe ejecutarse dentro de un contexto de solicitud, y la entrada/salida asíncrona en el ámbito global está prohibida. - En los archivos de declaración de tipos compartidos, nunca uses nombres de tipos de ámbito global genéricos; antepón siempre el nombre del producto o de la funcionalidad. Nunca uses un objeto sin tipar como tipo; declara una interfaz adecuada con campos conocidos, ampliando opcionalmente un registro abierto para garantizar la compatibilidad futura. - Nunca edites a mano las instantáneas generadas. Corrige la capa de origen y vuelve a generarlas. ## Pon los cambios de comportamiento tras indicadores de compatibilidad o controles temporales El proyecto asume un fuerte compromiso de compatibilidad retroactiva: una vez que un comportamiento se ha desplegado, no puede eliminarse ni cambiarse de forma silenciosa. Por tanto, los cambios de comportamiento deben introducirse tras una compuerta, y la compuerta se elige según su permanencia. - Los indicadores de compatibilidad basados en fechas son por instancia, permanentes y se definen en un esquema cuyas anotaciones llevan el nombre del indicador y su fecha de activación. Todo indicador debe estar documentado antes de que llegue su fecha de activación. - Las compuertas temporales a nivel de proceso se controlan por configuración y están pensadas para despliegues arriesgados con activación condicional. Se definen como una enumeración más un mapa de cadenas, y ambos deben mantenerse sincronizados. Mantén el listón alto con las interfaces no estándar; es preferible implementar estándares publicados antes que inventar comportamientos específicos del proyecto. ## Actualiza las dependencias incorporadas sin perder los parches locales Las dependencias de terceros se incorporan a un directorio externo mediante el mecanismo de módulos del sistema de compilación. La integración reside en el manifiesto de módulos y en un directorio de compilación de dependencias; puede que aún exista un archivo de espacio de trabajo heredado, pero ya no es el mecanismo principal. Para cualquier duda sobre las cabeceras y los espacios de nombres de la biblioteca base incorporada, consulta directamente sus fuentes en lugar de suponer. Varias dependencias llevan conjuntos de parches mantenidos localmente que se aplican durante la compilación. Estos parches introducen personalizaciones específicas del proyecto e interfaces nuevas, así que revísalos y actualízalos cada vez que se actualice la dependencia. Ten en cuenta además que el proyecto usa un asignador de memoria alternativo, cuyo comportamiento difiere del predeterminado; cualquier análisis de memoria debe tenerlo en cuenta. Para una actualización importante del motor o de una dependencia: pregunta antes de empezar cuál es la versión de destino exacta y qué parches o personalizaciones deben conservarse, y sigue después los pasos documentados de sincronización, aplicación de parches, rebase, regeneración de parches y subida de versión. Los conflictos de fusión son habituales y casi siempre requieren criterio humano para mantener intactos los cambios propios del proyecto; nunca los resuelvas automáticamente sin revisión humana. Confirma que la suite de pruebas completa pasa y señala cualquier nueva advertencia de obsolescencia que encuentres. ## Busca la documentación repartida y propón arreglos cuando esté mal La documentación está distribuida, no centralizada. Un directorio de documentos cubre temas transversales como la configuración del entorno, las pautas para añadir interfaces nuevas y los procedimientos de actualización de dependencias, mientras que los directorios de código fuente individuales suelen llevar su propio readme o guía con detalles profundos del subsistema. Búscalos de forma proactiva cuando trabajes en un área que no conoces, antes de suponer o preguntar. Cuando la documentación falte, sea inexacta o esté desactualizada, propón una actualización en lugar de callar. Verifica primero los hechos y no hagas commit de cambios en la documentación sin confirmar su exactitud con una persona responsable del mantenimiento.