Saltar a contenido

Clientes de escritorio y complementarios

Responsabilidades y modos de desarrollo

Electron empaqueta el frontend de React y el backend de Python en una sola aplicación de escritorio. Su proceso principal controla el proceso hijo del backend, las ventanas, el protocolo de la aplicación, el estado de las actualizaciones y las acciones privilegiadas. El proceso de renderizado usa una API de precarga limitada, nunca acceso sin restricciones a Node.js o al sistema de archivos.

El desarrollo nativo en el navegador y el desarrollo con Electron tienen puntos de entrada distintos:

Modo Frontend Responsable del backend
Navegador nativo Vite en http://localhost:5173 pnpm dev desde la raíz inicia Vite y uvicorn
Desarrollo con Electron Vite iniciado por separado en http://localhost:5173 pnpm desktop:dev inicia su propio proceso hijo de uvicorn en el puerto 5002
Electron empaquetado Frontend incluido en app://gnosi/index.html python/cervell_backend incluido en el paquete, o cervell_backend.exe en Windows

No ejecutes el backend nativo junto con el desarrollo de Electron: el supervisor de escritorio no adoptará otro proceso que ocupe el puerto 5002. El modo de desarrollo de Electron no inicia Vite ni solicita la recarga de uvicorn. Inícialo con uv run --frozen --no-sync pnpm desktop:dev después de sincronizar el entorno de Python, para que python3, o python en Windows, se resuelva dentro de ese entorno. El origen de confianza para desarrollo es HTTP localhost:5173; configura VITE_DEV_HTTPS=false para esa sesión de Vite. Una sesión HTTPS del complemento de Word es una configuración distinta, no un origen intercambiable con el del cliente de escritorio.

El README de escritorio contiene las instrucciones de configuración y recuperación. Los enlaces de los menús con React y el aviso de actualización pertenecen a frontend/src/app/desktop/; la presentación de las notas de versión pertenece a la funcionalidad del centro de control. Reorganizar estas responsabilidades internas no debe cambiar los nombres IPC, las acciones de actualización ni los destinos de descarga.

Inicio, ventanas e IPC

Antes de abrir Chromium o iniciar servicios, profile-startup.js obtiene el bloqueo de instancia única y prepara el perfil existente. Un conflicto o un estado de recuperación ambiguo detiene el inicio; no autoriza a borrar archivos.

Cada inicio del backend proporciona un valor nuevo de GNOSI_DESKTOP_INSTANCE. El supervisor exige que su propio proceso hijo siga activo y que la respuesta de estado sea satisfactoria, completa y de tamaño limitado, con la cabecera x-gnosi-desktop-instance correspondiente. Esa cabecera permite relacionar la respuesta con el proceso; no autentica al usuario ni cambia el JSON público de estado. Los tiempos de espera agotados, las redirecciones, las respuestas mal formadas, la salida prematura del proceso y las respuestas HTTP 200 ajenas hacen fallar el inicio y provocan la terminación y recogida del proceso hijo propio. Si falta el ejecutable empaquetado, nunca se recurre al Python del sistema.

Nueva ventana, Ajustes, la activación desde el Dock y la visualización diferida de ventanas no pueden eludir la espera a que el backend esté listo ni el cierre. Cerrar la última ventana de macOS no cierra la aplicación; salir de ella detiene su backend. En otras plataformas, cerrar todas las ventanas cierra la aplicación. Los mensajes de error de inicio están disponibles en inglés, catalán, español y francés antes de que cargue React; los detalles técnicos quedan en los registros.

Las ventanas principales usan contextIsolation: true, sandbox: true y nodeIntegration: false. Solo el marco principal actual de una ventana registrada, situada en el origen de confianza de desarrollo o del paquete, puede invocar IPC privilegiado. La navegación y las redirecciones no pueden conservar ese puente en otro origen. Los enlaces HTTP(S) solicitados en una ventana nueva se abren externamente.

El rellenado de formularios solo acepta una URL inicial HTTPS sin credenciales y fija su origen exacto antes de cargarla. Los controles de navegación y redirección se instalan antes de iniciar la carga; se bloquean los destinos sin cifrar y los de otro origen. La URL final de webContents se comprueba de nuevo inmediatamente antes de cada inyección del perfil sintético, de modo que el contenido redirigido no recibe ningún byte del perfil.

El protocolo del paquete sirve los recursos del frontend y actúa como proxy de /api/ hacia el backend local. Valida el componente de autoridad de la URL de la aplicación, impide salir de los directorios permitidos y usa el almacén de cookies de la sesión en lugar de reenviar las cabeceras de cookies sin procesar del proceso de renderizado. Conserva este comportamiento al modificar el enrutamiento o los adaptadores de transmisión en continuo.

El módulo empaquetado backend-proxy.js limita las solicitudes individuales GET /pages/:pageId/preview a 15 segundos, incluidas las cabeceras de respuesta y todo el cuerpo JSON. Una vista previa bloqueada de un archivo en la nube devuelve HTTP 504 y libera su conexión HTTP, de modo que las vistas previas de la galería no pueden dejar el guardado de vistas indefinidamente a la espera de conexiones ocupadas. Este límite no interrumpe una lectura bloqueada del sistema de archivos en el backend ni garantiza la disponibilidad de los archivos en la nube.

La cancelación del proceso de renderizado se propaga a las solicitudes al backend. Las demás respuestas de la API, incluidas las transmisiones de los agentes y las escrituras, conservan su duración y comportamiento de transmisión habituales. El contrato de empaquetado exige el módulo proxy; las pruebas de regresión cubren seis vistas previas bloqueadas simultáneas, cuerpos bloqueados, cancelación y transmisiones en continuo.

Los ocho gestores extraídos tienen contratos de solicitud y respuesta comprobados. El rellenado de formularios reside en ipc-handlers.js, ya incluido en el paquete; el proceso principal aporta la fábrica nativa de ventanas y el registro de mensajes. La validación del emisor sigue precediendo al acceso al payload y a la apertura de una ventana independiente y aislada sin puente de precarga. La validación de URL, el orden de eventos, la serialización del perfil y el programa inyectado no cambian y cuentan con pruebas diferenciales sintéticas. El programa dentro de la cadena no se comprueba estáticamente. Esto no acredita el comportamiento en webs reales, el tipado completo del proceso principal, la aceptación de instaladores ni la autorización de destinos arbitrarios para formularios. Las suscripciones de precarga devuelven funciones de cancelación idempotentes; los métodos de eliminación compatibles siguen disponibles para procesos de renderizado antiguos.

Datos locales y recuperación del perfil

El backend empaquetado selecciona el primer valor no vacío en este orden: GNOSI_DATA_DIR, GNOSI_LOCAL_DATA, LOCAL_DATA_DIR y, por último, el directorio userData existente de Electron. Establece la variable canónica y conserva cualquier alias de compatibilidad existente. La alternativa de escritorio no coincide necesariamente con el valor predeterminado de Python nativo para la plataforma y no traslada una instalación antigua. Usa rutas absolutas para las configuraciones explícitas y conserva tanto el perfil de Electron como cualquier directorio de datos independiente del backend antes de actualizar.

El nombre de paquete con ámbito @gnosi/desktop se vuelve a asociar al nombre histórico de ejecución gnosi; se siguen usando las ubicaciones explícitas de perfil y sesión. El identificador del paquete sigue siendo com.gnosi.cervell-digital.

La protección de perfiles conserva los directorios obsoletos databases como bytes opacos en .<profile-name>.gnosi-electron-recovery/databases.saved, junto a cada perfil. Los movimientos atómicos sin reemplazo y los diarios de operaciones impiden sobrescribir un destino existente. Se comprueban los perfiles separados de datos de usuario y de sesión. Las operaciones primitivas del sistema de archivos no compatibles, los módulos nativos ausentes, las rutas de datos solapadas o los diarios ambiguos detienen el inicio. Se conservan los bytes, no la funcionalidad WebSQL eliminada. No restaures ese árbol con el nombre antiguo mientras se ejecute una versión más reciente de Electron ni borres los diarios para forzar el inicio.

Para los esquemas de cookies conocidos 19–22, la migración prepara únicamente la base de datos de cookies, valida su integridad, esquema, número de filas y un resumen criptográfico de los datos proyectados que respeta su representación en bytes, y activa después el esquema 23 antes de que Chromium la abra. El original exacto se conserva en .Cookies.gnosi-cookie-recovery/original.sqlite, junto a Cookies. Si el almacén es desconocido, está dañado, presenta conflictos o usa un cifrado personalizado, la operación se bloquea por seguridad. No se copia el perfil completo, no se intenta adivinar una clave de descifrado ni se recurre a texto sin cifrar.

La reversión explícita de cookies exige que los clientes estén detenidos y que la migración hacia delante se haya completado. Conserva las cookies más recientes en rollback.current.sqlite, restaura un original verificado mediante su propio diario de operaciones e impide repetir automáticamente la migración. Conserva todos los archivos de recuperación hasta la aceptación; nunca fuerces los números de versión del esquema ni borres bases de datos de cookies. El README describe la recuperación tras interrupciones y las pruebas aisladas de la secuencia antigua → destino → destino. El éxito con datos de prueba no demuestra la migración real de perfiles, del almacén de secretos del sistema operativo ni de la base de datos de la aplicación en otra máquina.

Actualizaciones y acciones del usuario

En producción se comprueban versiones tras el inicio y cada seis horas mientras el actualizador está inactivo. En desarrollo se desactivan las comprobaciones; autoDownload y autoInstallOnAppQuit siguen en false. El botón compacto muestra el porcentaje descargado. Pulsarlo autoriza la descarga, la sustitución verificada y el reinicio. El proceso principal gestiona la secuencia, rechaza acciones repetidas y detiene el backend antes de instalar.

macOS utiliza el puente Sparkle incluido y firmas ad-hoc, sin suscripción Apple Developer. La clave pública fijada verifica el canal firmado y el ZIP antes de extraerlo. Se desactiva la alternativa de un canal sin firma. update-policy.js conserva el DMG de la arquitectura correcta para instalaciones ad-hoc antiguas sin el puente. La primera versión con Sparkle se instala manualmente; Apple aún puede pedir autorización para abrir una aplicación sin notarizar. La verificación correcta con codesign no demuestra una actualización completa de la aplicación.

Windows utiliza la sustitución con NSIS y el reinicio automático. Linux admite la sustitución de AppImage y la instalación DEB con el gestor de paquetes, que puede pedir permisos de administrador. Los instaladores Windows sin firmar pueden recibir avisos o bloqueos. Se mantienen las protecciones del sistema operativo.

La prueba real aislada de macOS sustituye y reinicia una aplicación temporal; un archivo modificado se rechaza antes de instalarlo. Las pruebas de Windows y Linux verifican el comportamiento con la ejecución de procesos simulada. Los instaladores reales, perfiles existentes y migración de datos 2.x requieren aceptación.

El enlace de versión del panel de control abre el historial público localizado en https://ismigar.github.io/changelog.html, con un fragmento para la versión elegida. Las comprobaciones en segundo plano no lo abren. La web solo incluye versiones publicadas.

Herramientas y límites del empaquetado

El espacio de trabajo fija Node 22.22.2 y pnpm 11.19.0. Las dependencias de escritorio fijan actualmente Electron 43.4.1, electron-builder 26.15.3 y ASAR 4.3.0. El entorno de ejecución de Node integrado en Electron es distinto del usado para compilar el espacio de trabajo. El comando explícito install:runtime instala su binario; no habilites todos los scripts de instalación de dependencias para solucionar la ausencia del entorno de ejecución.

Compila el frontend antes de empaquetar la aplicación de escritorio. build-python.sh exige exactamente Python 3.11, acepta GNOSI_PYTHON_CMD cuando se configura explícitamente y crea un entorno temporal único usando el uv.lock congelado de la raíz y el grupo de dependencias desktop. Genera una especificación de PyInstaller, valida el análisis y el paquete, copia el resultado verificado en desktop/dist-python/ y ejecuta la prueba básica aislada del backend empaquetado. No usa un archivo de requisitos independiente ni el entorno existente del desarrollador.

La política de recursos lee el código fuente sin importar la aplicación. Conserva los recursos de Alembic, las instrucciones del agente, las skills de traducción dinámica, los plugins de ejemplo y los estilos bibliográficos. Rechaza recursos ausentes, modificados, no revisados o inseguros, en lugar de incluir recursivamente vaults, bases de datos, configuración, secretos o herramientas generadas. El hook afterPack comprueba el ASAR real y los recursos de Python antes de la firma. El escaneo completo en frío sigue siendo fail-closed y tiene un límite de proceso de diez minutos para que los paquetes Windows recién copiados no terminen durante la primera inspección. Los recursos gráficos pertenecen a desktop/assets/; los paquetes generados, a desktop/dist/ y desktop/dist-python/.

Los esquemas de genogramas cargan backend/domains/genograms/option_labels.json durante el arranque. El plan explícito de recursos incluye este JSON revisado junto a su módulo. Una prueba con el plan trasladado crea los esquemas de personas y relaciones en los cuatro idiomas sin acceso al código original; el ejecutable empaquetado real también debe superar la prueba de arranque en cada plataforma.

El proyecto raíz declara los required-environments de uv para macOS arm64 y x64, Linux arm64 y Windows x64. Regenera uv.lock con uv para que los marcadores de resolución puedan seleccionar distintas versiones de dependencias compatibles con los wheels de cada destino; nunca edites el lock manualmente. Cada dependencia binaria seleccionada debe publicar un wheel para su destino antes de iniciar el empaquetado.

PyInstaller informa de los paquetes de espacio de nombres implícitos con origen -. La política de recursos solo acepta ese centinela para raíces de terceros. Un espacio de nombres desconocido bajo las raíces propias backend, pipeline, config, frontend o extensions sigue fallando de forma cerrada, mientras que un espacio de nombres de una dependencia como jaraco no se clasifica por error como código del repositorio.

El verificador de plugins empaquetado importa la raíz pública de confianza inmutable desde backend/security/plugin_trust_root.py. Las herramientas de release del marketplace reutilizan esa constante, pero el cargador de la clave privada queda fuera del plan de recursos de escritorio. El análisis de PyInstaller debe fallar si el módulo de firma del marketplace entra en el paquete de runtime.

Destino configurado Arquitectura del ejecutor Instaladores y artefactos de actualización
macOS arm64 macOS ARM64 en infraestructura propia Gnosi-<version>-arm64.dmg, ZIP, latest-mac.yml, appcast-arm64.xml
macOS x64 macOS X64 en infraestructura propia Gnosi-<version>-x64.dmg, ZIP, latest-mac.yml, appcast-x64.xml
Linux arm64 Linux ARM64 en infraestructura propia AppImage, DEB, latest-linux-arm64.yml
Windows x64 Windows X64 en infraestructura propia Gnosi-<version>-Setup.exe, latest.yml

La arquitectura del backend congelado debe coincidir con la de destino. Los destinos macOS no deben empaquetar silenciosamente ambas arquitecturas con un único backend nativo del equipo de compilación. Linux pasa --arm64; Windows usa NSIS x64. Estos trabajos no fijan una versión de macOS ni cubren Linux x64 o Windows arm64. Los dos trabajos de macOS se ejecutan en serie; Windows espera a macOS, mientras Linux puede ejecutarse en paralelo. La concurrencia se limita por referencia Git, no mediante un bloqueo global que garantice la capacidad del equipo anfitrión.

Windows recibe una excepción a la política de ejecución de PowerShell limitada al trabajo y prepara Git antes de obtener el código cuando hace falta; no debilites la política de toda la máquina. La compilación del backend pasa entre comillas los argumentos del intérprete, usa estructuras de entornos virtuales temporales específicas de cada plataforma e intenta limpiarlos en la medida de lo posible. El manifiesto de Python restringe actualmente cryptography para macOS x86_64 a la serie 48.x; la invocación actual de uv no impone la instalación exclusiva de binarios. Verifica la procedencia de los paquetes wheel y su ABI en el ejecutor real, sin dar por hecha esa restricción ni sustituir su Python/OpenSSL.

Todos los scripts de compilación de escritorio, incluidos los alias de la raíz package:desktop y build:desktop, desactivan la publicación de electron-builder con --publish never. Preparan artefactos locales; no certifican ni publican una versión.

Preparación de versiones y distribución exclusiva de candidatos

El historial incluido en la aplicación está en frontend/src/features/control-center/releases/releases.json. Los manifiestos de la raíz, del frontend y del escritorio, los metadatos de Python, los archivos de bloqueo, las notas localizadas y el registro de cambios deben coincidir antes del lanzamiento. sync-release-version.cjs prepara las cuatro entradas antes de escribir únicamente sus campos de versión. Las entradas ilegibles, las asignaciones no compatibles y los duplicados ambiguos fallan antes de cualquier escritura. Conserva las versiones dentro de objetos JSON, los comentarios y los finales de línea; una versión idéntica no reescribe ningún archivo. El localizador TOML admite [project].version entre comillas en una sola línea, pero no valida todo el TOML. La actualización del archivo de bloqueo todavía debe validar el proyecto Python. Las escrituras separadas no son una transacción resistente a interrupciones: un fallo de entrada/salida o una interrupción puede dejar cambios parciales. Revisa las diferencias con la base registrada de la rama de preparación antes de reintentar. Siguen siendo necesarias la validación del catálogo y del registro de cambios y la revisión de los archivos de bloqueo actualizados.

desktop/release.sh ofrece los modos explícitos prepare, package y promote. La preparación exige un árbol limpio, cambia únicamente la versión revisada y los metadatos pendientes, genera el changelog de forma transaccional y no altera los locks. El empaquetado exige el árbol limpio y confirmado, consume los locks de pnpm y uv congelados y sin conexión, y no puede modificar versiones, locks, catálogo ni changelog. Las cachés se preparan fuera de este paso inmutable. La promoción es un commit de metadatos posterior a la publicación: exige el tag local coincidente, los cuatro grupos de artefactos verificados y la URL exacta de la release publicada antes de marcarla como estable y añadir el enlace. El paquete etiquetado nunca anuncia así una release estable inexistente.

desktop/release-version.js es el límite compartido de versión de lanzamiento para el actualizador y el recopilador de artefactos. Usa la implementación SemVer fijada con electron-updater, acepta metadatos de compilación canónicos y rechaza espacios adyacentes, prefijos v y versiones no válidas o no canónicas. La política de actualización y el empaquetado no deben introducir un segundo analizador.

Build Release Candidate es un workflow opcional y exclusivamente manual. Enviar una etiqueta de versión no inicia Actions alojadas. Cuando se ejecuta explícitamente, comprueba que la etiqueta solicitada existe y que, al resolverla hasta su commit, coincide exactamente con el github.sha extraído. Las entradas mal formadas, las etiquetas ausentes, los destinos que no son commits o las discrepancias detienen el proceso antes de instalar dependencias. La herramienta de identidad usa Git local y no mueve referencias ni descarga referencias por sí sola. La protección de etiquetas remotas sigue siendo un requisito aparte. La publicación sin presupuesto alojado construye y verifica localmente los cuatro grupos de plataforma y publica solo esos artefactos exactos; no ejecutes el workflow alojado opcional sin aprobación explícita de presupuesto. Como el repositorio es público, cada trabajo del CI compartido solo permite la ejecución en infraestructura propia cuando la rama de una PR pertenece al repositorio canónico. Las PR de forks no pueden llegar a los equipos del propietario; un mantenedor debe revisarlas y reproducir el cambio en una rama interna de confianza antes de ejecutar las comprobaciones protegidas. El mismo preflight también exige que la versión de la etiqueta coincida con los manifiestos de la raíz, del frontend, del escritorio y de Python antes de iniciar la CI o cualquier compilación por arquitectura.

A continuación, el flujo invoca la CI existente en el mismo commit sin heredar secretos. Las compilaciones por arquitectura requieren que la CI finalice correctamente. Incluye documentación, frontend, backend, pruebas básicas nativas y compilaciones de imágenes Docker. La documentación de las PR se comprueba contra su base exacta; los candidatos comprueban los catálogos actuales y todos los portales de idioma en modo estricto en su propio SHA, no mediante una revisión ficticia del impacto de una PR.

La recopilación descarga únicamente los cuatro artefactos de arquitectura designados, excluyendo los candidatos anteriores al repetir una ejecución. Instala las dependencias bloqueadas del recopilador con los scripts de ciclo de vida desactivados, comprueba la versión, las referencias y las huellas SHA-512, rechaza los archivos ausentes o en conflicto y combina los dos manifiestos de actualización de macOS. La generación de índices, la presentación de las notas de versión y la subida del candidato se realizan después de la validación. La generación del marketplace es obligatoria y falla de forma cerrada: la clave de firma debe corresponder a la clave pública gnosi-official incluida. Un verificador independiente previo a la subida comprueba las dos firmas separadas de los índices, todas las firmas y huellas SHA-256 de los paquetes, el conjunto exacto de ZIP anunciados y unas notas de versión no vacías.

El artefacto final de Actions es candidate-<tag>-<sha>-<attempt> y se conserva durante cinco días. Contiene instaladores, metadatos de actualización, índices y notas de versión. No es un almacenamiento confidencial y nunca debe contener datos de usuario ni secretos. El flujo tiene permisos de solo lectura sobre el repositorio y no crea borradores en GitHub, no publica versiones ni modifica artefactos públicos existentes o canales de actualización.

La distribución pública sigue desactivada hasta completar la aceptación del modo nativo, Docker, los instaladores y las actualizaciones desde 2.x, y revisar por separado una vía de publicación. Un candidato correcto no autoriza a publicar 3.0.0.

Clientes web y ofimáticos

El capturador web envía POST /api/public/clip con un token de acceso personal y lee la configuración de los campos solicitados y del destino desde GET /api/public/clip/config. El backend elige el vault de destino; la extensión no obtiene acceso arbitrario al sistema de archivos. Su token y la URL del backend se guardan en el almacenamiento local de la extensión. El empaquetado para navegadores y la aceptación en sus tiendas son independientes de la aceptación del instalador de escritorio.

El panel de tareas de Word está en frontend/public/word-addin/ y usa Office.js. Sus llamadas a la API usan el origen del panel y un token bearer configurado explícitamente; que un endpoint público responda correctamente no demuestra que el acceso a las citas esté autorizado. El origen HTTPS del manifiesto y el certificado de confianza deben coincidir con su despliegue. Las herramientas de extensions/office/word-cite/ modifican referencias del documento o paquete, o la plantilla de Word del usuario, para mantener el panel de forma opcional. Son modificaciones explícitas de documentos o configuración, no una acción normal del inicio de Gnosi.

El cliente de LibreOffice es un gestor de protocolo Python/UNO que usa urllib de la biblioteca estándar. Lee api_token de su propia configuración o de GNOSI_API_TOKEN; no des por hecho que comparte la sesión del navegador. Ambos clientes usan los endpoints de formato de citas del vault y el procesamiento Pandoc/CSL del backend. El formato sensible al contexto necesita las claves del documento en orden, incluidas las citas repetidas. La actualización de Writer recorre tablas anidadas; los encabezados y pies de página aportan claves bibliográficas, pero la actualización ordenada no los reescribe. El comportamiento de la aplicación ofimática anfitriona debe probarse en la aplicación compatible real, no deducirse de pruebas de recorrido con datos simulados.

Aceptación y resolución de problemas

La prueba básica del backend empaquetado exige una respuesta de estado HTTP 200 de tamaño limitado con status: ok, mode: FastAPI y una identidad nueva de la prueba en gnosi_mode. Usa rutas desechables de datos y vaults, desactiva la automatización operativa y recoge su proceso hijo tanto si tiene éxito como si falla. GNOSI_VALIDATION_ROOT valida todos los selectores y bloquea los archivos de entorno locales y compartidos y el acceso al almacén de credenciales. La generación de OpenAPI usa el mismo aislamiento. Nunca establezcas esta opción en el desarrollo normal ni en aplicaciones instaladas.

Los contratos comprobados en el código fuente, los entornos anfitriones simulados y una ejecución de FastAPI desde el código fuente no demuestran que funcione un instalador con el backend congelado ni una actualización real. Antes de distribuir públicamente, verifica en cada destino real la instalación, el primer inicio, el IPC, la conservación de cookies y perfiles, la integridad de la base de datos, la vía de actualización y la recuperación, además de los flujos autenticados del navegador y el inicio y la persistencia de Docker. El éxito local en macOS no puede certificar otro destino.

Síntoma Qué revisar a continuación Qué no hacer
El desarrollo con Electron se queda en blanco Origen HTTP de Vite, PATH del entorno Python congelado y registro de inicio del backend propio Iniciar un segundo backend en el puerto 5002
La protección del perfil detiene el inicio Error exacto, rutas originales y de recuperación, clientes detenidos Borrar diarios de operaciones, cookies o datos antiguos
Falta el backend empaquetado Resultado de PyInstaller y política de recursos finales Recurrir al Python del sistema
macOS ofrece un DMG Puente Sparkle ausente o instalación antigua; arquitectura Considerar la verificación de firma como aceptación de la actualización automática
Office puede consultar el estado, pero las citas fallan Token bearer, origen de la API y respuesta real del recurso protegido Desactivar la autenticación para ocultar un fallo del cliente

Ejecuta las pruebas de contratos de escritorio del repositorio, la comprobación estricta de IPC, la validación documental y los comandos pertinentes de pruebas básicas aisladas. Inspecciona la salida y los registros del navegador y del escritorio, no solo los códigos de salida. Mantén separadas las evidencias de las plataformas de destino y las pruebas sintéticas.

Corrección de la instalación después de 3.0.0

Electron empaquetado selecciona un puerto local libre. Python acepta BACKEND_PORT con una GNOSI_DESKTOP_INSTANCE válida, escucha en 127.0.0.1 y desactiva la recarga. Los servicios nativos conservan sus puertos. La prueba de arranque aporta una configuración contradictoria para verificar que prevalece el puerto del proceso padre y sigue exigiendo la identidad del proceso propio. Una segunda apertura recrea la ventana principal si se había cerrado.

Los trazados del favicon, independientes de las fuentes, generan los iconos en desktop/assets. El DMG tiene un fondo liso y un tamaño de 540 × 320. El disco del escritorio desaparece al expulsarlo; no es un acceso directo. Se mantiene la firma local gratuita, que no equivale a la notarización de Apple. Las instrucciones de instalación están en desktop/README.md.

La release 3.0.1 prepara la corrección integrada de la instalación de escritorio para generar nuevos paquetes nativos en las cuatro plataformas. La preparación mantiene el catálogo sin publicar, conserva los dos archivos de dependencias fijadas y no sustituye ningún archivo de 3.0.0. Se mantiene la distribución gratuita con firma local de macOS.

La versión del backend y el contrato OpenAPI generado deben coincidir con los manifiestos preparados; la validación de la release comprueba su igualdad antes de generar los paquetes.

Ayuda al usuario

El menú Ayuda lateral abre el centro, los primeros pasos, la sección actual y la documentación técnica en el navegador externo. El menú nativo ofrece el centro, los primeros pasos y la documentación de usuario. El idioma opcional de set-application-menu conserva la compatibilidad; el proceso principal valida su tipo y normaliza variantes regionales e idiomas no disponibles. Ambos clientes usan desktop/help-links.json para destinos fijos y temas admitidos. Las URL no incluyen identificadores de registros, nombres de Vaults ni contenido privado. Las secciones desconocidas abren la portada. Catalán, castellano y francés tienen rutas propias; el inglés es la alternativa. El menú participa en la pila de teclado modal para que Escape cierre la ayuda antes que la barra lateral móvil.

Las guías se mantienen en docs/learn/ y se construyen por separado de la documentación técnica. Hay que publicar y verificar el portal antes de distribuir una versión con enlaces nuevos. El sitio redirige /learn/ a /Gnosi/learn/.

La ayuda abierta desde la barra lateral recibe la preferencia de apariencia de Gnosi. El portal respeta los modos claro, oscuro y sistema y conserva la preferencia entre artículos e idiomas. Los enlaces del sitio público se abren en un contexto de navegador separado.

La versión 3.0.2 incluye el centro de ayuda multilingüe, los menús de ayuda contextual y los enlaces que conservan la apariencia. Las versiones de escritorio, interfaz y backend se mantienen sincronizadas; el catálogo sigue pendiente hasta publicar los instaladores verificados.

Primer inicio sin biblioteca

El proceso principal empaquetado lee vault_configured de la respuesta de salud validada de su servicio. Si es falso, vault-startup.js detiene ese proceso y abre el selector nativo de carpetas antes de iniciar la interfaz o las actualizaciones. El usuario puede elegir una biblioteca existente o crear una carpeta. Cancelar cierra la aplicación; volver a abrirla ofrece la configuración. Tras reiniciar correctamente con DIGITAL_BRAIN_VAULT_PATH, guarda solo la selección en GNOSI_DATA_DIR/desktop-vault.json. Las variables explícitas de biblioteca tienen prioridad; una carpeta guardada ausente no se recrea sola.

Las pruebas enfocadas cubren la selección, cancelación, cierre de procesos, reinicio, traducciones y persistencia. La aceptación de la versión también debe instalar el DMG candidato con un perfil vacío y sin biblioteca inyectada, recorrer el selector visible y un segundo inicio, y probar la actualización desde 3.0.1 con datos sintéticos. Preparar la biblioteca antes de arrancar no acredita la aceptación del primer inicio.

Una selección nativa correcta guarda también un selectionId opaco. El preload aislado lo aplica antes de las peticiones de la interfaz: borra solo el ID, slug, nombre y catálogo de la biblioteca activa anterior y su cookie. Las demás preferencias y cookies se conservan. El marcador se aplica una sola vez por perfil, de modo que los cambios normales de biblioteca sobreviven a ventanas nuevas y reinicios. Los archivos antiguos sin marcador siguen siendo válidos. Cancelar la recuperación conserva la selección anterior. Elegir otra carpeta no reescribe las identidades registradas. Hay que repetir la aceptación del DMG para cambio de ruta y actualización con la misma ruta, y reconstruir el backend congelado.

El candidato 3.0.4 incluye la corrección de preservación del guardado automático integrada en la PR 96. Sustituye al candidato no publicado 3.0.3 sin mover su etiqueta ni reutilizar sus validaciones de aceptación. Los cuatro campos de versión están sincronizados, los archivos de dependencias fijadas no cambian y el catálogo permanece sin publicar hasta que los nuevos instaladores superen la aceptación.

La constante del backend GNOSI_VERSION también indica 3.2.0; la prueba del contrato de la API de salud la compara con los cuatro manifiestos de versión.

Hay que regenerar el documento OpenAPI guardado y su SHA-256 después de cambiar la versión del backend. En este candidato, la diferencia revisada del esquema se limita a la versión de la aplicación; las rutas y los datos no cambian.

La CI de Docker reintenta la limpieza de los contenedores de prueba y la repite en un paso independiente que siempre se ejecuta antes de eliminar las imágenes de CI, para evitar que una limpieza fallida bloquee la siguiente construcción.

La lista de recursos revisados de la aplicación de escritorio incluye personal_memory_0002, de modo que las versiones instaladas conservan los recuerdos existentes al añadir memoria por ámbitos y proyectos privados de aprendizaje.

Aceleración limitada de CI

Las copias comprimidas de paquetes Python siguen desactivadas: comprimir todo el entorno había retrasado las comprobaciones obligatorias. CI ahora reutiliza la cache nativa de paquetes uv de cada runner, separada por repositorio, sistema operativo, arquitectura y versión de Python. uv gestiona el acceso concurrente; la preparación nunca borra esta cache. Cada job conserva un entorno virtual nuevo con archivos copiados y dependencias fijadas. Si falta la configuración de cache del runner, se descarga en una cache exclusiva del job. pnpm ya reutiliza su almacén local; las subidas de cache remotas siguen desactivadas. Docker retira las etiquetas de imagen de CI después de limpiar los contenedores de prueba, pero conserva las capas mientras queden al menos 12 GiB libres; si falta espacio, aplica la limpieza limitada existente. La primera ejecución de cada runner descarga las dependencias, y las siguientes solo los artifacts que faltan. Aún hay que medir los tiempos en los runners. La restauración y creación de archivos comprimidos siguen desactivadas.

Si Docker aún no dispone de 12 GiB tras limpiar las capas y las copias antiguas, uv libera las ruedas precompiladas descargadas de la cache de paquetes propia; conserva las ruedas compiladas desde el código fuente. La recuperación usa la orden de cache de uv, rechaza directorios simbólicos o ajenos y se detiene cuando hay espacio suficiente. Un runner pequeño puede tener que descargar paquetes otra vez tras quedarse sin espacio; reutilizar paquetes no sustituye una capacidad de disco adecuada.

ESLint utiliza una caché basada en el contenido y mypy conserva el análisis incremental entre jobs; los cambios de plataforma, dependencias y configuración invalidan la caché. Las pruebas del frontend utilizan dos procesos. La comparación local de 27 pruebas representativas ha pasado con uno y dos procesos; todavía hay que evaluar el tiempo y la memoria de la suite completa en el runner. Se mantiene el orden de los jobs pesados.

Solo las solicitudes de cambio de confianza que modifican exclusivamente Markdown de los cuatro portales de ingeniería pueden omitir los pasos de ejecución. Los cinco nombres de comprobación obligatorios siguen visibles y el job de documentación valida todos los idiomas. Los diffs vacíos o desconocidos, los movimientos de código y los cambios de código, configuración o dependencias requieren la validación completa. Los envíos de commits y las validaciones de versiones siempre conservan todas las comprobaciones de ejecución.

Como el análisis del frontend utiliza los tipos de TypeScript, cualquier cambio de fuentes o reglas locales del frontend invalida toda su caché, incluidos los resultados de los archivos que los importan sin haber cambiado. Los cambios exclusivos del backend pueden reutilizarla. Si se desconoce el estado de las fuentes, se repite el análisis.

La composición de anotaciones PDF ejecuta los 57 contratos en cada uno de dos órdenes de importación aislados. Cada grupo tiene un límite de 300 segundos que cubre la carga inicial del backend y todas las comprobaciones. El progreso detallado, los tiempos de las pruebas más lentas y la pila tras 60 segundos de bloqueo de una prueba individual permiten distinguir un arranque lento de una prueba bloqueada. Un timeout del grupo o cualquier error del proceso hijo sigue haciendo fallar la validación, que incluye la salida parcial.

La validación local previa a la PR y CI invocan el mismo punto de entrada pnpm lint:frontend. El lanzador compartido siempre comprueba todo el frontend sin permitir avisos; solo añade las opciones de caché de contenido cuando se define GNOSI_ESLINT_CACHE. Las rutas de caché se pasan como argumentos literales sin intérprete de órdenes y los errores de análisis siguen siendo fatales. La prueba de paridad previa a la PR sigue rechazando cualquier validación de CI ausente del plan local completo.

La candidata 3.1.0 empaqueta el asistente principal compartido, la selección de modelos según la tarea, la memoria con ámbito definido, el aprendizaje reutilizable y la lectura contextual de fuentes. Los datos existentes se conservan mediante las migraciones revisadas. Todos los manifiestos y GNOSI_VERSION coinciden; el contrato OpenAPI regenerado solo cambia la versión respecto al código preparado. Los dos archivos de dependencias fijadas se mantienen intactos. El catálogo sigue sin publicar hasta que los instaladores del mismo código superen las pruebas de instalación inicial, persistencia y actualización en los cuatro destinos.

La candidata 3.2.0 añade equipos de asistentes y roles especializados, comparación de modelos por proveedor y plantillas multilingües de espacios de trabajo. Coinciden las versiones de la raíz, el frontend, el escritorio, Python y el backend en ejecución. Se regenera OpenAPI con la nueva versión; los dos archivos de dependencias fijadas permanecen intactos. El catálogo sigue sin publicar hasta que los instaladores del mismo código superen la aceptación de instalación inicial, persistencia y actualización en los cuatro destinos compatibles.

Configuración del primer inicio empaquetado

Antes de seleccionar un vault, el servicio empaquetado guarda la configuración y las migraciones de referencias de proveedores en GNOSI_DATA_DIR/config/params.yaml. Los recursos firmados de la aplicación permanecen en solo lectura; las solicitudes posteriores siguen guardando en el archivo .gnosi/params.yaml del vault activo. Las pruebas del primer inicio y del reinicio deben verificar la firma instalada después de salir de la app, ya que un arranque correcto por sí solo no detecta escrituras dentro del paquete.

La imagen Docker del frontend incluye el verificador compartido de recursos PDF que importa Vite y comprueba que se cargue durante la construcción. Esto evita que una imagen construida correctamente falle al iniciar el servidor porque falta el verificador.