


Crear una biblioteca que lea y escriba archivos de imagen por capas sin perder datos
Úsalo al crear una biblioteca para imágenes por capas en formato binario. Separa el análisis binario de la API de usuario, lee las secciones en orden, guarda los datos desconocidos, rehace los grupos de capas, prueba con lectura, escritura y relectura, y automatiza la publicación.
Para usar estas reglas de IA
## Instalar solo las dependencias que pide la tarea y usar los comandos del proyecto
Lee la documentación para colaboradores antes de cambiar el código.
Usa el gestor de entornos y los comandos de tareas del repositorio en lugar de invocar herramientas desde un entorno de ejecución no relacionado.
Configura únicamente los grupos de dependencias que requiera la tarea:
- instala las dependencias de desarrollo predeterminadas para el análisis sintáctico y las pruebas;
- añade el grupo opcional de renderizado cuando intervengan la composición o la rasterización;
- incluye los grupos de documentación solo cuando vayas a generar la documentación;
- prevé que ciertos paquetes opcionales de cálculo científico o dibujo no estén disponibles en algunas combinaciones nuevas de entorno de ejecución y sistema operativo.
Usa los comandos canónicos para:
- generar módulos de extensión compilados y artefactos de distribución;
- ejecutar el conjunto completo de pruebas con cobertura;
- ejecutar una sola prueba mediante su identificador de nodo;
- ejecutar pruebas sin cobertura al medir un comportamiento específico;
- ejecutar análisis de estilo, formato y comprobaciones de tipos estáticos;
- generar la documentación HTML e inspeccionar el directorio de salida indicado en ella.
No trates las dependencias opcionales de renderizado como requisitos esenciales del análisis sintáctico.
Proporciona instrucciones claras de instalación cuando se solicite una operación opcional sin sus dependencias.
## Separar la lectura y escritura binaria de bajo nivel de la API para el usuario
Mantén separado el análisis sintáctico binario de bajo nivel de la API de usuario de alto nivel.
La capa de bajo nivel:
- lee y escribe el formato binario sin procesar según su especificación;
- modela cabeceras, registros, bloques etiquetados, descriptores, recursos de imagen, máscaras, canales y datos de compresión;
- expone los métodos explícitos de serialización `read(fp)` y `write(fp)`;
- conserva los datos desconocidos que todavía no se pueden interpretar.
La capa de alto nivel:
- envuelve las estructuras documentales de bajo nivel en interfaces fáciles de usar;
- reconstruye árboles de objetos orientados al usuario a partir de registros binarios planos;
- expone tipos de capa, efectos, máscaras, renderizado y operaciones de documento;
- retrasa el análisis sintáctico costoso hasta que se accede a los datos, cuando el contrato lo permite.
El código interno debe importar las definiciones concretas de bajo nivel desde los módulos donde se definen.
Los usuarios externos deben utilizar las exportaciones admitidas del paquete.
No expongas detalles de representación de bajo nivel en métodos públicos sin una razón de compatibilidad.
## Leer y escribir las secciones del archivo en orden y conservar los datos desconocidos
Considera el orden de las secciones, las longitudes, las firmas y los anchos numéricos como parte del contrato del formato de archivo.
Un archivo de imagen por capas habitual contiene cinco secciones consecutivas:
1. Una cabecera de archivo de tamaño fijo con firma, versión, dimensiones, canales y modo de color.
2. Datos del modo de color, como paletas indexadas.
3. Recursos de imagen, como perfiles de color, guías y miniaturas.
4. Información de capas y máscaras con registros de capa, datos de canales y bloques etiquetados.
5. Datos de la imagen compuesta y aplanada.
Valida tamaños fijos de cabecera, como 26 bytes, cuando lo exija la especificación.
Lee y escribe las secciones en orden; no deduzcas los límites a partir de objetos en memoria que resulten convenientes.
Devuelve desde los métodos de serialización el número de bytes escritos para que quienes los invoquen puedan verificar el cómputo del tamaño.
Conserva las cargas desconocidas como bytes durante la ida y vuelta en vez de descartarlas.
## Reconstruir los grupos de capas a partir de la lista plana de registros
Cuando el formato almacene una jerarquía como lista plana, interpreta los registros de límite explícitos en lugar de presuponer solo la adyacencia.
Reconoce los marcadores de inicio y fin de grupo, y reconstruye las relaciones padre-hijo mediante una pila o una máquina de estados verificada equivalente.
Prueba como mínimo:
- registros ordinarios fuera de los grupos;
- un grupo que contenga varios elementos secundarios;
- grupos anidados;
- grupos vacíos;
- marcadores de límite mal formados o desequilibrados;
- la conservación del orden original de los registros.
Mantén disponible la lista plana de registros de bajo nivel para la serialización mientras expones un árbol mediante la API de alto nivel.
No permitas que la reconstrucción del árbol modifique registros binarios no relacionados.
## Añadir bloques etiquetados mediante un registro y dejar intactos los que no se admiten
Proporciona a las estructuras binarias un contrato base común con lectura en el ámbito de la clase y escritura en el ámbito de la instancia.
Compón estructuras complejas de forma recursiva a partir de primitivas pequeñas.
Usa de manera coherente las funciones de clases de datos tipadas para:
- inicializadores generados;
- validación de campos;
- anotaciones de tipo;
- representaciones controladas;
- conversión predecible a tuplas o secuencias cuando sea necesario.
Mantén los validadores coherentes con las anotaciones y usa un tipo de retorno de la misma instancia para constructores encadenables o que reconozcan la clase.
Para bloques etiquetados extensibles:
- usa una clave de etiqueta de ancho fijo y su carga asociada;
- asigna las etiquetas conocidas a clases gestoras mediante un registro;
- comprueba la presencia de una etiqueta antes de leer sus datos tipados;
- conserva intactos los bloques no compatibles para poder escribirlos después;
- separa el acceso público de conveniencia del acceso a registros internos.
No registres un gestor que consuma bytes que no pueda volver a escribir fielmente.
## Acelerar la compresión y los cálculos de píxeles sin romper la implementación alternativa
Mide las rutas sensibles al rendimiento antes de optimizarlas.
Usa códecs compilados para operaciones costosas de compresión o descompresión cuando estén disponibles, pero conserva una implementación alternativa correcta en lenguaje puro.
Usa carga diferida para máscaras, efectos y datos de canales cuando retrasar el análisis sintáctico conserve la semántica.
Usa vectorización de arreglos para cálculos de píxeles y modos de fusión a gran escala cuando mejore el rendimiento.
Toda optimización debe conservar:
- la compatibilidad de la salida binaria;
- el comportamiento ante errores;
- los resultados deterministas;
- la implementación no optimizada;
- la compatibilidad con entornos donde no estén disponibles dependencias compiladas u opcionales.
Prueba las implementaciones optimizadas y alternativas con los mismos datos de prueba.
No cambies los resultados de forma silenciosa para ganar velocidad.
## Probar los cambios leyendo, escribiendo y releyendo archivos, y añadir anotaciones de tipo
Organiza las pruebas de forma que reflejen la estructura del paquete y separa las pruebas binarias de bajo nivel de las pruebas de la API de alto nivel.
Mantén datos binarios de prueba representativos en un directorio específico y parametriza las pruebas para varios archivos.
Usa la validación de ida y vuelta como invariante principal:
1. Lee el archivo binario.
2. Modifica un campo controlado.
3. Escribe el archivo.
4. Vuelve a leer el resultado.
5. Verifica el cambio previsto y la conservación de los datos no relacionados.
Añade anotaciones de tipo adecuadas a la firma de cada función nueva.
Mantén los validadores de clases de datos alineados con las anotaciones.
Usa el tipo de compatibilidad del proyecto para los métodos que devuelvan una instancia de su propia clase.
Ejecuta pruebas específicas durante el desarrollo y, antes de terminar, el conjunto completo pertinente, el análisis de estilo, el formato y la comprobación de tipos.
Revisa los cambios de cobertura en lugar de usar únicamente el porcentaje de cobertura como prueba de corrección.
## Publicar con el flujo automatizado e indicar claramente lo que no se admite
Elige las versiones de lanzamiento según el estándar de versionado documentado del proyecto, incluidas las formas final, de prelanzamiento y de poslanzamiento.
Resume en el registro de cambios, bajo el encabezado de la nueva versión, las modificaciones realizadas desde la etiqueta anterior.
Usa exactamente el patrón de rama de lanzamiento que requiera el etiquetado automático.
Abre una solicitud de lanzamiento contra la rama principal y fusiónala solo después de recibir aprobación.
Deja que la automatización configurada etiquete el commit exacto fusionado, genere las distribuciones, cree el lanzamiento alojado y publique en el registro de paquetes.
No crees una etiqueta manual cuando el flujo de lanzamiento sea responsable del etiquetado.
Asegúrate de que la credencial de automatización tenga los permisos mínimos necesarios para activar los flujos posteriores y no la expongas nunca.
Antes de afirmar que una función opera correctamente, comprueba los límites documentados para:
- el renderizado de texto cuando no existe un motor de fuentes;
- las operaciones de ajuste compatibles y no compatibles;
- el subconjunto de efectos de capa implementados;
- la extracción frente a la edición de objetos incrustados;
- la conservación sin interpretación de datos desconocidos.
Declara explícitamente los comportamientos no compatibles en vez de aproximarlos de forma silenciosa.
Termina informando de las pruebas ejecutadas, las rutas opcionales no probadas, los riesgos de compatibilidad y cualquier limitación que afecte al cambio solicitado.
