Manual de operaciones¶
Esta guía describe los contratos revisados en el código público. La fecha de verificación corresponde a esa revisión, no a una instalación, migración o publicación validada en todas las plataformas. Las órdenes siguientes son instrucciones para el operador, no pruebas de que se hayan ejecutado.
La comprobación de disponibilidad del navegador utiliza la misma instantánea
global del proceso que las sondas nativas: una cookie, cabecera o consulta del
vault activo no activa su resolución en la ruta exacta GET /api/health.
Las demás rutas y métodos mantienen el enrutamiento habitual. La autodetección
de la política de autenticación comparte solo lecturas pendientes; los seguidores
HTTP esperan una tarea en vez de ocupar workers bloqueados. El TTL existente
de cinco segundos sigue comenzando con la lectura original; un restablecimiento
retira la generación pendiente, las variables explícitas del entorno se mantienen
actualizadas, las sesiones explícitas de base de datos evitan la reutilización
y los errores siguen exigiendo autenticación.
El modo personal local se abre sin registro para cualquier perfil. Los registros adicionales de cuentas no activan la autenticación: las solicitudes anónimas reutilizan el propietario del espacio personal, priorizando los propietarios establecidos sobre las identidades generadas y después la pertenencia más antigua. Antes de crear el espacio personal se reutiliza la cuenta establecida más antigua; una instalación vacía crea la identidad local. Los despliegues de organización o expuestos y las opciones explícitas de autenticación mantienen el requisito de credenciales.
La configuración agrupa los editores de los complementos en Plugins y elimina las entradas duplicadas del menú general. La lista de complementos, las instalaciones de terceros, el catálogo y las actualizaciones siguen el orden alfabético del nombre visible en el idioma de la interfaz. Los accesos existentes a Referencias abren directamente su complemento; los demás editores mantienen las acciones de configuración y un botón para volver a Plugins.
Desarrollo nativo como primera opción¶
Ejecute el backend FastAPI y el frontend Vite de forma nativa. Docker, Electron, el almacenamiento en la nube y los LaunchAgents de macOS son opcionales. Utilice Python 3.11, Node 22.22.2 y pnpm 11.19.0; la CI actual y el backend Docker fijan uv 0.9.15. Desde la raíz del repositorio, prepare las dependencias a partir de los archivos de bloqueo versionados:
Inicie el backend y el frontend en terminales separados, ambos en la raíz del repositorio:
El wrapper del backend utiliza el entorno existente de la raíz mediante
uv run --project "$BASE" --frozen --no-sync, llama a las funciones canónicas
de Python load_env() y resolve_data_dir() e inicia uvicorn en loopback con
recarga limitada a backend/. No sincroniza ni instala dependencias.
No interpreta dotenv en el shell ni fuerza un vault OneDrive, un proveedor,
HOME_HOST_PATH, una zona horaria, un modelo o un endpoint de traducción.
El wrapper del frontend establece COREPACK_ENABLE_NETWORK=0 y ejecuta
corepack pnpm --filter @gnosi/frontend dev; pnpm y las dependencias fijadas
ya deben estar disponibles. El ejemplo pasa una configuración Vite explícita
y una dirección loopback; sin --host, se aplica el host configurado en Vite.
Establezca VITE_BACKEND_HOST y VITE_BACKEND_PORT explícitamente para otro
backend (valores predeterminados: 127.0.0.1 y 5002). Vite carga sus dotenv;
el wrapper no exporta un VITE_FRONTEND_PORT predeterminado que los oculte.
Ambos wrappers validan los puertos proporcionados entre 1 y 65535, transmiten
los argumentos y propagan los códigos de salida. El frontend conserva las
etiquetas explícitas del checkout y avisa si ya se ha integrado y ha quedado
por detrás de origin/main.
Para el uso nativo habitual, compile una vez y sirva la aplicación compilada:
corepack pnpm --dir frontend run build
GNOSI_NATIVE_FRONTEND_MODE=preview bash scripts/runtime/run_native_frontend.sh
Preview utiliza el mismo puerto estricto, certificados HTTPS, redirección de
HTTP a HTTPS y proxy del backend. Sirve una copia aislada de frontend/dist,
por lo que una compilación posterior no puede eliminar recursos de la aplicación
en ejecución. Al detenerse elimina solo la copia de ese proceso. Vuelva a compilar
y reinicie para aplicar cambios de código; el valor predeterminado
GNOSI_NATIVE_FRONTEND_MODE=dev mantiene las actualizaciones del código en directo.
La ausencia de una compilación o un modo inválido producen un error explícito.
Un LaunchAgent gestionado puede seleccionar preview con esa variable de entorno;
recargue la tarea después de cambiar su entorno almacenado.
Las compilaciones incluyen un manifiesto Vite. Preview lo utiliza para identificar los recursos públicos exactos con hash de contenido y servirlos con caché inmutable del navegador en respuestas GET/HEAD correctas, incluida la validación 304. HTML, respuestas API, recursos inexistentes, archivos públicos no enumerados y otros métodos mantienen su política de caché. Cambiar el contenido cambia su URL compilada; la entrada HTML sigue revalidándose para descubrir la compilación actual. Las compilaciones antiguas sin manifiesto mantienen la política original de Vite. Esto elimina revalidaciones repetidas después de que el navegador reciba las nuevas cabeceras; no elimina la latencia de la primera descarga ni de las API.
El arranque deja pasar las peticiones de enrutamiento y salud por su middleware asíncrono antes de programar las descargas de la ruta y la interfaz principal. Cede un turno al navegador sin esperar ninguna respuesta; la representación sigue respetando la preparación del enrutamiento y del idioma. La compilación agrupa solo los 51 iconos de la interfaz principal revisados explícitamente. Los demás iconos y las rutas pesadas siguen siendo diferidos, y las dependencias compartidas de los iconos mantienen su ubicación automática. Después de cambiar el grupo, revise el grafo de importaciones compiladas para detectar ciclos nuevos o dependencias iniciales inesperadas, además de los límites de bytes.
Una cookie de sesión opcional inválida se ignora cuando el acceso personal
local está permitido, por lo que una sesión caducada no introduce ningún registro
ni inicio de sesión. Cuando se requieren credenciales, /auth/me distingue una
cookie inválida de un 401 anónimo habitual. La interfaz ofrece una acción explícita
de recuperación: llama al endpoint existente de cierre de sesión, borra los
metadatos locales de identidad solo si tiene éxito y recarga la aplicación. Si
falla, la recuperación sigue disponible. Esto no cambia la política de
autenticación ni el acceso a páginas compartidas públicas.
Un 401 explícito de una ruta protegida con Authentication required es un caso
diferente: cuando /api/auth/me informa de un usuario anónimo, muestre Login en
vez de diagnosticar una cookie caducada o pedir el cierre de sesión. La respuesta
del servidor al catálogo de complementos prevalece sobre una instantánea anterior
de salud que indique autenticación desactivada. La corrección
authenticationRequired de usePlugins y App tiene 17 pruebas focalizadas,
una comprobación focalizada de tipos, lint de los archivos existentes y una
compilación correctos. Una prueba adicional de integración de App verifica que
iniciar sesión en el mismo vault recarga los complementos y abandona Login;
su lint también pasa. La activación con TLS de confianza y la pantalla real de
Login están verificadas; no se ha iniciado ni cerrado ninguna sesión real ni
se han leído credenciales. Consulte el trabajo de tiempos del calendario en la
auditoría de latencia de navegación.
El perfilado Python con privilegios no es la única vía de diagnóstico. La
instrumentación opcional de duraciones del calendario mediante
X-Gnosi-Calendar-Timing: 1 y Server-Timing está implementada y activada en
las rutas de calendarios y eventos. Informa de tiempos de cola, resolución de
credenciales y HTTP sin exponer credenciales ni contenido del calendario. Solo
se propaga el contexto CalendarTiming; los contextos de vault y autenticación
y los resultados de las consultas no cambian. Los tiempos son inclusivos y
pueden ser concurrentes, por lo que no deben sumarse para reconstruir el total.
cal_total excluye middleware y validación de respuesta y no es la duración HTTP
completa. cal_service incluye el acceso a la capa de servicio, las importaciones
de discovery anteriores a las credenciales anidadas y la construcción del cliente;
no es tiempo puro de build. Han pasado la batería de 35 pruebas del calendario,
la repetición de sus 9 pruebas nuevas, Ruff y mypy. La verificación real con acceso
a datos devolvió HTTP 200 con un calendario y dos eventos visibles después de
10.557 s. No se reprodujo la espera anterior de 47–52 s en el servidor; quedan
intervalos locales sin explicar, y este cambio de diagnóstico no demuestra una
mejora global atribuible de latencia. Esta vía no requiere autorización administrativa.
Hay un muestreador Python dentro del proceso para peticiones del grafo con
X-Gnosi-Graph-Profile: 1, y para peticiones de eventos del calendario con
X-Gnosi-Calendar-Profile: 1 y X-Gnosi-Calendar-Timing: 1 a la vez. Permite un
muestreador simultáneo, durante un máximo de 15 s a 20 Hz, que observa el hilo
principal y los workers registrados explícitamente. Solo registra nombres
normalizados de archivos de código, nombres de función y números de línea,
sin variables locales, globales, argumentos, nombres de hilos, datos del usuario
ni trazado del correo. La salida agregada se limita a 256 pilas de 32 frames e
incluye el identificador del proceso y el instante de inicio monotónico. El archivo
con modo 0600 /tmp/gnosi-request-profile-<id>.json se guarda al llegar al
límite de 15 s aunque la petición siga pendiente. La parada espera como máximo
250 ms; la respuesta incluye X-Gnosi-Request-Profile-Id cuando la persistencia
ya ha terminado. No se necesita autorización administrativa. Han pasado la
batería de 35 pruebas del muestreador, calendario y grafo, Ruff, mypy y la activación
del backend. Las capturas del grafo y del calendario se completaron sin privilegios
administrativos. La captura del grafo tenía 39 observaciones dentro de una ventana
máxima de 15 s, 33 pilas agregadas y ninguna descartada. El intervalo nominal de
50 ms no fue constante en la práctica: no multiplique los recuentos por ese
intervalo para obtener duraciones. Un frame del runner de uvloop no distingue
inactividad de trabajo nativo en C. La captura posterior del calendario tenía
34 observaciones, 19 pilas y ninguna descartada; los frames de espera de workers
y de caché de discovery son observaciones, no duraciones aditivas. Estos límites
describen la recogida de diagnóstico, no una corrección de latencia. Las correcciones
de decodificación JSON, admisión limitada en la caché de metadatos y discovery
estático de Google están implementadas y validadas: han pasado 80 casos de prueba
únicos, Ruff, mypy y la comprobación del diff. La activación del backend terminó
en 185.3 s. Las aperturas directas posteriores, solo con tiempos y recursos
compilados en caché, mostraron el grafo después de 22.128 s y datos frescos del
calendario después de 16.081 s. Estas medidas no demuestran una mejora global
de latencia ni el objetivo de 0.5 s. La navegación final en caliente mostró
datos del grafo después de 7.447 s y datos frescos del calendario después de
5.392 s; los datos ya cargados del calendario eran visibles a los 398 ms.
Mantenga separados los tiempos de visibilidad y de datos frescos. La verificación
y la limpieza están completas, mientras que el objetivo de latencia sigue parcial.
Se restauró el HTML de la copia nativa, se eliminaron el script de tiempos y
las dos capturas, y el calendario accesible de loopback volvió a la vista mensual
sin consulta de auditoría. HTTPS devolvió 200 con verificación TLS correcta y
HTML no-cache; HTTP redirigió con 307 a HTTPS, y los recursos compilados mantuvieron
un año de caché inmutable.
Para un vault local, configure su directorio real y seleccione
GNOSI_FILES_PROVIDER=local; no hace falta ningún servicio auxiliar de
descarga. Distinga el vault activo del directorio padre que contiene varios
vaults. DIGITAL_BRAIN_VAULT_PATH tiene prioridad sobre VAULT_HOST_PATH;
esta segunda variable también interviene en la detección del proveedor.
Si el entorno no establece una ruta, el backend puede utilizar el vault
seleccionado en Configuración.
| Servicio | Dirección predeterminada | Comprobación |
|---|---|---|
| Frontend | http://localhost:5173 |
Se muestra el inicio de sesión o la interfaz de la aplicación; la navegación funciona. |
| Backend | http://127.0.0.1:5002 |
/api/health y, después, peticiones autorizadas de configuración y del vault. |
Vite utiliza strictPort: true: resuelva los conflictos de puerto en vez
de aceptar un puerto alternativo. HTTPS es opcional: el modo automático utiliza
certificados locales legibles; VITE_DEV_HTTPS=false fuerza HTTP y
VITE_DEV_HTTPS=true exige certificados. Reinicie Vite si cambian los
certificados. El código se recarga; los cambios de dependencias requieren
sincronizar los archivos de bloqueo y reiniciar el proceso afectado. Reinicie
el frontend para actualizar los valores de versión inyectados durante el arranque.
El frontend nativo gestionado establece pnpm_config_verify_deps_before_run=warn
por defecto y conserva cualquier valor explícito. Reiniciar un servicio no debe
activar una reinstalación implícita de dependencias cuando otra tarea cambia los
manifiestos del workspace. Instale y sincronice las dependencias explícitamente
antes de reiniciar el servidor afectado; el aviso no demuestra que las dependencias
instaladas coincidan con el archivo de bloqueo.
Para HTTPS local de confianza, instale mkcert y ejecute
bash scripts/runtime/setup-https-dev.sh; después reinicie el frontend.
La configuración instala una autoridad de certificación local en el almacén de
confianza de la máquina y genera certificados ignorados en frontend/certs/.
Con esos certificados, https://localhost:5173 sirve la aplicación y HTTP
redirige a la misma ruta y consulta mediante HTTPS. Los archivos de certificado
por sí solos no bastan si el navegador no confía en la autoridad local.
El desarrollo nativo utiliza notificaciones del sistema de archivos. Establezca
CHOKIDAR_USEPOLLING=true solo para sistemas de archivos o montajes bind de
contenedores que necesiten sondeo. Vite prepara la interfaz principal, Conocimiento
y el Centro de control al arrancar; las demás pantallas siguen siendo diferidas
y se precargan cuando existe intención de navegar a ellas.
El idioma inicial y el formato de registros utilizan /api/config/interface,
una respuesta pequeña de preferencias visuales limitada al vault y con el mismo
control de permisos que la configuración. No lee el estado de las credenciales;
/api/config sigue siendo la respuesta completa de configuración, incluidos los
indicadores de credenciales. Los editores y el Centro de control leen
/api/config/editor, que conserva los campos editables y extensiones, normaliza
referencias de proveedores y valores predeterminados, y excluye credenciales en
texto plano e indicadores de disponibilidad de solo lectura sin consultar almacenes
de credenciales. Guardar la configuración invalida las cachés correspondientes del
frontend. Las lecturas de editores comparten solo peticiones solapadas por vault;
las posteriores se revalidan inmediatamente. Configuración carga sus documentos
editables una vez por apertura del modal, incluso cuando el modo de desarrollo
repite los efectos de montaje. Cerrar y volver a abrir sigue pidiendo documentos
frescos de configuración, integración e identidad. Los selectores de campos y
registros reutilizan un comparador de configuración regional por ordenación.
La configuración de Planificación conserva las tablas, proyectos y tareas ordenados
hasta que cambian sus datos o la configuración regional, por lo que editar campos
no relacionados no vuelve a ordenar cientos de opciones.
El enrutamiento del vault resuelve las consultas iniciales SQLite y de carpetas en la nube en workers. Las peticiones concurrentes de la misma identidad comparten una consulta; los cambios de vault invalidan la caché de identidad de 60 segundos, incluidas las consultas en curso. El contexto del vault activo se establece en la tarea de petición después de consultar, antes de llamar al endpoint. Los lectores HTTP solapados esperan una tarea compartida en vez de ocupar workers mientras otro resuelve la misma identidad. Desconectar un lector no puede cancelar la consulta que necesitan otras peticiones.
Los lectores de configuración reutilizan preparaciones correctas de directorios
durante un máximo de 30 segundos, con un límite de 256 rutas. YAML, selección de
vault y lecturas de archivos mantienen las comprobaciones habituales de frescura
y permisos. Las preparaciones fallidas se reintentan, y las llamadas directas a
get_paths() siguen comprobando y reparando inmediatamente. Si se elimina un
directorio preparado, una lectura de configuración puede aplazar su recreación
hasta que expire ese intervalo.
Las lecturas de cuentas de correo resuelven credenciales solo para la cuenta
seleccionada o las cuentas habilitadas durante la sincronización, excluyendo
integraciones ajenas. Las lecturas de carpetas de correo, los recordatorios del
calendario y la construcción del grafo se ejecutan en workers, incluida la carga
de configuración y registro. Configuración carga datos auxiliares de modelos,
calendario, lector y redes sociales al abrir la sección que los utiliza. El grafo
muestra inmediatamente los datos disponibles, sin un retraso mínimo de carga,
y reutiliza la ruta resuelta de configuración del vault al leer metadatos
gestionados de cada nodo. Si existe un índice de páginas, el descubrimiento del
grafo utiliza sus rutas y fechas de modificación, evitando un segundo recorrido
del sistema de archivos de la nube. Los nodos sin cambios conservan los enlaces
completos del cuerpo en caché; los nodos cambiados se vuelven a analizar. Un índice
antiguo ausente o ajeno provoca el recorrido del sistema de archivos. La frescura
del índice sigue el observador y la actualización en segundo plano existentes.
La caché en disco de nodos analizados se escribe solo después de que cambie un
nodo. La persistencia codifica una instantánea y utiliza el escritor atómico en
vez de millones de pequeñas escrituras JSON. Los lectores iniciales concurrentes
esperan una carga completa; los cambios que llegan durante un guardado permanecen
pendientes y los guardados fallidos se reintentan en la siguiente reconstrucción.
Las cachés persistentes de nodos del grafo se particionan por ruta de vault bajo
LOCAL_CACHE/graph_nodes/. Un vault sin caché propia lee una vez sus entradas del
antiguo graph_node_cache.json y escribe su partición; el archivo antiguo queda
intacto para los demás vaults. El estado cargado y pendiente de guardar se controla
por separado por vault, de modo que abrir uno no exige decodificar todas las
entradas antiguas de los demás.
Un archivo adyacente de metadatos vincula los nodos analizados con su clasificación,
colores y sidecars gestionados mediante un resumen del JSON real de los nodos.
Las cachés antiguas o los marcadores que no coinciden requieren una regeneración.
Los marcadores se publican solo después de una construcción completa y un guardado
correctos; las lecturas fallidas o parciales siguen siendo reintentables.
El visor del grafo permite a Sigma representar por lotes las actualizaciones de
topología, visibilidad y posición sin forzar una segunda reindexación completa
por paso de distribución. Los cambios al pasar el cursor siguen invalidando
su estado visual. La proyección inicial y los filtros de visibilidad se aplican
antes de construir Sigma, de modo que su primer índice recibe la topología
preparada. La línea temporal utiliza su límite inicial efectivo antes de
confirmarlo en el estado, evitando una segunda simulación D3 inicial para los
mismos datos y filtros; los cambios posteriores siguen actualizando la distribución.
El minimapa agrupa los eventos del grafo, la cámara y el renderizador en un dibujo
por frame, dibuja los círculos de nodos por lotes, cambia de tamaño solo cuando
es necesario y cancela el trabajo en cola al sustituirse o desmontarse. Los ajustes
aplazados de cámara también se cancelan al cerrar o cambiar su vista del grafo.
Los recuentos de filtros de campos reutilizan el grafo de filtrado ya normalizado
y recorren sus nodos una vez para todos los campos configurados. Los metadatos
se normalizan una sola vez por nodo; el recuento conserva la clasificación de
tablas, la búsqueda de campos sin distinguir mayúsculas, los valores repetidos
y el orden estable cuando los recuentos coinciden.
La página obtiene el índice global de títulos solo si lo necesitan los filtros
de campos configurados. Estos filtros conservan la prioridad de títulos del índice
canónico. Las consultas de grafo, tablas, configuración e índice se limitan al
vault activo; las vistas de grafo incrustadas comparten la consulta del grafo
y la invalidación por prefijo.
Cada lote del grafo en el backend también resuelve una vez los nombres y alias
de campos de relación de una tabla, incluidas las tablas sin relaciones. Esta
caché pertenece solo al lote; la siguiente construcción lee el esquema actual
del registro, y los metadatos de página en caché nunca se modifican al convertir
wikilinks de relación en identificadores.
La API del grafo conserva un cuerpo JSON validado para la instantánea actual,
comprobando el objeto actual del servicio antes de reutilizarlo. Las reconstrucciones
e invalidaciones sustituyen ese objeto, nunca se retienen grafos parciales y una
validación fallida no puede publicar un cuerpo. La codificación se ejecuta en
el worker de la petición; las cabeceras de respuesta y tareas en segundo plano
siguen siendo independientes para cada petición.
Las lecturas de raíces, árbol, álbumes, vistas y páginas multimedia también se
ejecutan en workers para que la latencia de carpetas de la nube no bloquee otras
peticiones. Una página multimedia resuelve cada vault/raíz una vez dentro de la
petición; ese ámbito se descarta tanto si tiene éxito como si falla. Las lecturas
concurrentes del mismo árbol multimedia confinado comparten solo el trabajo
pendiente. Los listados de directorios padre e hijo comparten un límite global
de cuatro escaneos, conservando los filtros de carpetas y la ordenación estable.
No hay TTL para el árbol: las peticiones posteriores leen los directorios actuales
y las fallas no se retienen para una petición posterior.
Los índices multimedia persistidos conservan cadenas de ruta validadas y fechas
de modificación en una secuencia inmutable. La paginación predeterminada construye
objetos Path solo para la página seleccionada, no para cada archivo indexado.
La carga sigue validando el índice completo; los filtros y la ordenación
personalizada siguen inspeccionando cada entrada aplicable. El formato JSON y
el intervalo de frescura de 24 horas mantienen la compatibilidad. Cuando ese
intervalo expira, la API del navegador devuelve la instantánea almacenada mientras
un máximo de dos workers la actualizan; la cola conjunta de trabajo en curso
y pendiente se limita a ocho tareas. Las peticiones del mismo índice comparten
ese trabajo. Un primer índice sin datos almacenados utilizables sigue esperando
su escaneo inicial.
GET /api/vault/media informa de X-Gnosi-Media-Index (fresh, refreshing
o failed), un X-Gnosi-Media-Index-Revision opaco y X-Gnosi-Media-Next-Offset.
El cuerpo mantiene su contrato. Los archivos eliminados desde la instantánea se
omiten de los elementos, pero las posiciones y el total permanecen estables;
los consumidores avanzan con la cabecera del siguiente desplazamiento, incluidas
las ventanas vacías. Las actualizaciones fallidas conservan la instantánea
almacenada y devuelven una espera Retry-After de hasta 30 segundos. La galería
consulta una actualización cada cinco segundos, hasta 60 veces, y después ofrece
un reintento manual. Conserva las fotos cargadas y sustituye todo su prefijo
cargado solo tras comprobar revisiones coincidentes entre páginas. Los cambios
de raíz, álbum, filtros o vault y los desmontajes cancelan peticiones y temporizadores.
Los escaneos parciales no pueden sustituir un índice completo. La invalidación retira la generación de publicación y la persistencia sustituye atómicamente un archivo temporal codificado. Un índice leído por completo sigue siendo utilizable en memoria si falla la escritura de su caché. Los consumidores Python antiguos conservan lecturas bloqueantes y los resultados parciales disponibles, pero no publican escaneos parciales. El formato JSON histórico no puede certificar retrospectivamente que un índice antiguo estuviera completo; su estructura se valida al cargarlo. Una caché que no puede escribirse no sobrevive a un reinicio del proceso.
La configuración social resuelve solo su propia sección de integración, conservando listas explícitamente vacías y valores predeterminados sin abrir credenciales no relacionadas.
Las notificaciones de errores no controlados se ejecutan en un worker para que su E/S de bases de datos, archivos y notificaciones nativas no bloquee otras peticiones HTTP. El arranque diferido del planificador también se ejecuta en un worker. La cancelación espera a que termine su arranque en curso antes de que el cierre llame a stop, evitando que un planificador se inicie después de haberse detenido. Estos límites conservan los ContextVars de la petición y la respuesta 500 segura existente.
La configuración de complementos carga los complementos instalados y los permisos independientemente del mercado. El catálogo y los datos de confianza se cargan al abrir su sección, y una lectura pendiente de confianza no oculta un catálogo disponible. Las lecturas fallidas muestran una acción de reintento antes de permitir editar la configuración. El backend reutiliza el estado decodificado de complementos solo si coinciden las fechas de modificación y cambio, el tamaño y el inode del archivo; guardarlo lo invalida, y cada documento devuelto es una copia independiente limitada a su ruta de archivo.
La entrada del navegador inicia el enrutamiento del vault y la descarga de la pantalla solicitada antes de cargar React DOM y la interfaz principal. Comparte la lectura pendiente de enrutamiento con esa interfaz, que sigue esperando el enrutamiento y el idioma antes de representarse. La entrada establece la cookie del vault activo antes de cualquier petición inicial. La lectura de enrutamiento comienza antes de las importaciones especulativas de pantallas y tiene una prioridad alta de petición; la programación del navegador debe medirse en el host de destino. Los límites de compilación acotan por separado el código necesario para iniciar esas peticiones y conservan el arranque dinámico requerido en el presupuesto completo. El catálogo de vaults lee el modo y el almacenamiento predeterminado de una instantánea de configuración por petición; las posteriores siguen leyendo la configuración actual.
Los selectores de planificación de proyectos solicitan todos los identificadores
y títulos de página al endpoint references de la tabla. Utiliza el mismo filtro
de plantilla y carga de títulos que la respuesta completa, pero no transfiere
metadatos sin utilizar. Las lecturas concurrentes comparten solo un vault, tabla
y filtro idénticos; las posteriores se revalidan inmediatamente. Un editor de
configuración abierto cancela sus lecturas de tablas y referencias al cambiar
de vault y no muestra resultados del anterior, aunque coincidan los identificadores
de tabla. En el conjunto local de 748 tareas y 45 proyectos, las dos respuestas
decodificadas sumaban 67,381 bytes en lugar de 1,130,202 bytes (94.04% menos),
con los mismos identificadores y títulos ordenados. Las peticiones de referencias
medidas tardaron 118 ms y 22 ms; esto no establece el tiempo hasta que se puede
utilizar el formulario completo de configuración.
El calendario monta la cuadrícula mientras se cargan las notas locales y las
preferencias, para que el intervalo visible real de FullCalendar pueda iniciar
concurrentemente las lecturas de eventos externos. La cuadrícula se oculta y
queda inerte solo en la primera lectura local sin datos utilizables. Las fuentes
locales completas residen en una consulta limitada al vault y se revalidan en
cada apertura (staleTime: 0). Volver a abrir muestra esa instantánea y los eventos
completos del mismo intervalo mientras un indicador de actividad identifica las
actualizaciones pendientes; el intervalo de frescura de eventos externos sigue
siendo de 30 segundos. Una actualización parcial no puede sobrescribir la última
instantánea local completa. Un primer resultado parcial aún puede mostrar notas
útiles, con un error explícito y reintento. Las listas, intervalos, consultas de
recordatorios e invalidaciones por mutación del calendario se limitan al vault;
los datos provisionales del intervalo anterior nunca atraviesan vaults. La
visibilidad guardada se aplica antes de seleccionar calendarios que llegan pronto.
Actualizar las notas conserva la instancia de la cuadrícula, el periodo seleccionado
y la vista. Las pruebas con respuesta aplazada ejercitan el remontaje real de
FullCalendar con un resultado envejecido del mismo intervalo; el contenido visible
en caché y los datos recién actualizados deben medirse por separado en el navegador
del host.
Configuración ya no importa el registro completo de componentes Lucide. El selector de iconos de agentes carga nombres buscables al abrirse y representa solo los iconos solicitados, incluidos los alias numerados guardados. La compilación comprueba las importaciones estáticas transitivas de Configuración, no solo el tamaño de su archivo de entrada, para evitar miles de pequeñas descargas de iconos. El guardado automático establece su base solo después de que se carguen todos los documentos editables; abrir o cerrar una sesión de configuración que carga lentamente no debe activar escrituras. La misma respuesta de configuración proporciona los parámetros saneados de proveedores de IA. La carga no obtiene una segunda vez todo el catálogo de proveedores y modelos solo para conseguir esos campos; se conservan las referencias de credenciales, indicadores de disponibilidad y extensiones de proveedores. Los editores de configuración se cargan con la sección seleccionada y los diálogos secundarios solo al abrirlos. La lista de complementos instalados también aplaza cada editor integrado hasta que se abre su configuración. Los indicadores de carga permanecen dentro del contenido seleccionado para que la navegación de Configuración y el botón de cierre sigan disponibles.
La bandeja de correo carga su lector y redactor solo al abrir un mensaje o borrador. Su panel de detalle vacío es independiente del editor de texto enriquecido y de las herramientas de calendario; la bandeja y una acción de cierre permanecen disponibles mientras se carga cualquiera de los módulos. Los formularios de eventos, herramientas de disponibilidad y búsqueda global también se cargan al abrirse, sin cambiar el guardado automático de borradores, la visibilidad de eventos ni el manejo de recurrencias. Las vistas previas de títulos aplazan la tarjeta de página y el renderizador Markdown hasta pasar el cursor sobre un título o abrirlo desde el teclado. La entrada del puntero inicia la carga del módulo durante el retardo existente; salir sigue cancelando la apertura y la navegación permanece utilizable. Los límites de compilación cubren los grafos completos de importaciones estáticas del correo y el calendario, incluido el código compartido de arranque, para que una entrada de ruta pequeña no oculte un editor cargado anticipadamente.
Las suscripciones push del correo esperan de forma asíncrona; las pestañas inactivas ya no ocupan el conjunto compartido de workers entre eventos. Las notificaciones originadas en hilos conservan los filtros de cuenta, la ordenación limitada y la limpieza al cancelar o desconectar. Las consultas de vistas y etiquetas locales del correo utilizan la ejecución síncrona en workers de FastAPI, conservando el contexto del vault activo y dejando disponible el bucle de peticiones. Las importaciones iniciales del proveedor híbrido también se ejecutan en workers y se omiten en lecturas de mensajes almacenados en caché.
Las actualizaciones de integraciones conservan las referencias al almacén seguro
y resuelven solo las credenciales cambiadas. Las lecturas de configuración que
solo obtienen referencias no esperan detrás de un lector que desbloquea credenciales.
La sincronización IMAP resuelve la cuenta seleccionada desde cualquiera de las
dos secciones admitidas, en lugar de desbloquear todas las cuentas de correo.
El enrutamiento al proveedor de calendario lee metadatos de cuentas sin desbloquear
credenciales. Los clientes Google y CalDAV resuelven solo las identidades
coincidentes de calendario/correo; Google también filtra por proveedor y autenticación
OAuth antes de acceder al almacén seguro. La prioridad de calendario sobre correo
y las lecturas frescas de credenciales no cambian. Las lecturas concurrentes de
credenciales de Google Calendar comparten solo el trabajo aún pendiente para el
mismo correo, documento de configuración e instantánea de revisión/referencias.
Las lecturas completas o fallidas se eliminan inmediatamente; las llamadas
posteriores vuelven a resolver credenciales. Cada consumidor recibe datos de
credenciales independientes y construye su propio cliente. Las rutas de estado
de recordatorios de reuniones utilizan directamente resolve_data_dir(), sin
cargar parámetros del vault ni crear directorios durante la resolución de rutas.
El escritor atómico prepara el directorio padre local cuando debe guardarse el estado.
La configuración reutiliza YAML decodificado de archivos sin cambios, comprobando el dispositivo, inode, tamaño, fechas de modificación/cambio y permisos en cada lectura. Los lectores concurrentes comparten una lectura inicial del mismo archivo; los vaults no relacionados mantienen lecturas independientes y todos los consumidores reciben documentos independientes. Las lecturas fallidas o inestables no se reutilizan. La caché conserva como máximo 16 documentos de hasta 1 MiB cada uno. El entorno y la selección del vault activo se mantienen actualizados. El descubrimiento de rutas reutiliza solo la ubicación del checkout del módulo y comprueba los directorios existentes antes de intentar crearlos; los directorios eliminados y los selectores de datos/vault cambiados mantienen el comportamiento normal de reparación.
La disponibilidad de credenciales resuelve los alias de entorno de proveedores
a partir de la instantánea actual del catálogo, metadatos locales descargados
o metadatos incluidos en el paquete. No actualiza models.dev, no consulta Ollama
ni espera una actualización en curso del catálogo de modelos. Las lecturas
explícitas del catálogo siguen actualizándose normalmente. Los índices locales
de alias son limitados y se releen después de sustituir o modificar archivos;
la resolución de secretos y los indicadores saneados has_api_key conservan su
prioridad. Las comprobaciones concurrentes de credenciales comparten la
decodificación inicial de cada archivo de catálogo sin cambios. Los archivos
diferentes y las sustituciones avanzan independientemente; las lecturas fallidas
se liberan y reintentan en la consulta siguiente sin retener una entrada fallida
en caché.
La navegación de Configuración y los editores de complementos integrados utilizan transiciones de React para mantener disponibles los controles actuales mientras se carga otro editor. Las lecturas concurrentes de tablas y páginas de tabla comparten una petición por vault, tabla y filtro, incluidos los remontajes de desarrollo; las lecturas posteriores siempre se revalidan, y cerrar un consumidor no puede abortar otro.
Las lecturas de páginas de tabla preparan nombres actuales de campos, identificadores inmutables y alias una vez por lote. Las filas cuyas claves no necesitan cambiar de nombre se copian sin contabilizar colisiones. Se conservan la prioridad de nombre/identificador/alias, el orden original de claves, los metadatos locales opacos y la validación HTTP de metadatos. Los mapas preparados permanecen dentro de una lectura de tabla; las consultas posteriores los reconstruyen para que los cambios de nombre y esquemas de distintos vaults sean independientes.
El grafo solicita solo su propio documento de configuración en /api/config/graph.
La lectura hereda el control de permisos de configuración y el contexto del vault,
pero nunca inspecciona credenciales de proveedores de IA ni de contraseña del
sistema. El documento completo de Configuración conserva el comportamiento
saneado del estado de credenciales. Las actualizaciones de preferencias del grafo
siguen leyendo la configuración actual después de los cambios.
Tras la proyección, la construcción del grafo limpia el almacenamiento temporal
de adyacencia y atributos de NetworkX, incluso con resultados parciales o fallos.
De lo contrario, sus vistas en caché pueden retener ese almacenamiento hasta una
recogida cíclica global del proceso; la respuesta proyectada y la caché de nodos
analizados conservan sus datos independientemente. Los grafos de vault incrustados
utilizan sus opciones explícitas de vista y no obtienen un documento global de
configuración sin utilizar al montarse, cambiar la configuración o reintentar
resultados parciales.
La entrada de Configuración, la navegación entre secciones y los botones de configuración de complementos integrados preparan el módulo del editor seleccionado cuando existe intención mediante el puntero, foco del teclado o toque. Los mismos cargadores de importaciones sirven a React.lazy; la preparación nunca monta una sección, lee documentos editables ni guarda configuración. Las descargas especulativas fallidas se ignoran para que abrir la sección siga controlando la carga y los errores habituales. Mida el tiempo desde el clic hasta los controles poblados y habilitados por separado de la preparación del módulo y del primer frame del modal; adelantar una descarga antes del clic no demuestra que la carga de datos cumpla el objetivo de latencia de navegación.
Antes de aceptar peticiones, el arranque visita en un worker los contextos de validación de rutas incluidas de FastAPI sin generar el esquema público opcional de la API ni ejecutar dependencias de los endpoints. Esto evita construir rutas de forma diferida en la primera petición del navegador, dejando la generación y caché del esquema en su vía habitual bajo demanda. El arranque de integraciones sigue aplazado hasta que termine la preparación de rutas; la autenticación y la validación de parámetros siguen ejecutándose en cada petición aplicable.
Las revisiones de esquema de vault vault_0005–vault_0006 añaden índices del
Lector para fecha de publicación, estado de lectura y fuente. Esto evita escanear
cuerpos de artículos y ordenar toda la tabla antes de aplicar el límite del
listado. El ejecutor habitual de migraciones respalda la base de datos y verifica
el esquema, integridad y recuentos de filas; se conservan el contenido de los
artículos y los campos de respuesta del listado. Un índice de cobertura de
inventario evita que la agregación de fuentes y recuentos abra cuerpos de artículos.
Las pruebas del plan de consultas cubren las cuatro variantes del listado y la
agregación de inventario. La interfaz del Lector solicita include_content=false
para su lista de artículos, conservando metadatos, filtros y orden mientras
excluye los cuerpos almacenados de la consulta SQL y de la carga HTTP. Abrir un
artículo obtiene su cuerpo completo por separado; una selección nueva cancela
la petición anterior y los fallos ofrecen reintento. La API predeterminada del
listado y los enlaces directos a artículos mantienen el contrato de contenido completo.
Planificación trata un archivo de estado/historial existente pero ilegible, o
un documento de estado corrupto, como no disponible, nunca como un plan nuevo
vacío. Las líneas individuales malformadas del historial siguen el comportamiento
existente de omisión. Los errores temporales del proveedor devuelven 503 con
planning_storage_pending y Retry-After; las consultas de lectura reintentan
dentro de una ventana limitada, mientras que las mutaciones nunca se repiten
automáticamente. Las claves de consulta de Planificación incluyen el vault activo,
y los datos provisionales del proyecto anterior solo se reutilizan dentro de
ese vault. El proyecto seleccionado se resuelve a partir de referencias compactas
de páginas antes de cargar su programación y líneas base.
Las respuestas de imagen distinguen las descargas del proveedor aún pendientes
de los fallos confirmados mediante X-Gnosi-File-Availability. La miniatura
reintenta solo después de un error real de imagen, respeta la espera de reintento,
cancela al desmontarse y reutiliza los bytes de la respuesta correcta. Las descargas
fallidas muestran un reintento manual tras una espera corta. Una petición de
preparación o un bloque de archivo asignado no demuestra disponibilidad: el
proveedor comprueba la legibilidad en un worker. Completar la descarga de la nube
sigue dependiendo del proveedor de archivos y debe verificarse con archivos reales.
Un timeout del catálogo de complementos mantiene cerrados los controles de acceso a funciones y muestra una acción explícita de reintento en la interfaz principal y en el control de la ruta de complementos. Una lectura fallida del catálogo no demuestra que se hayan desactivado los complementos; no sustituya su estado no disponible por un catálogo vacío correcto. Las lecturas y respuestas pendientes de activación/configuración se limitan al vault activo; un éxito o una reversión tardíos de un vault anterior no pueden sustituir el estado actual.
Las reconstrucciones del grafo se agrupan por vault; los aciertos de caché evitan reconstruir el registro. Tras 30 segundos, el servicio revalida rutas y fechas de modificación indexadas, datos del registro, columnas de contactos, propuestas pendientes, configuración y sidecars gestionados. Una instantánea completa sin cambios conserva su objeto de grafo y cuerpos codificados. Las lecturas pequeñas y correctas de sidecars reutilizan una LRU de como máximo 512 documentos de 64 KiB cada uno, tras comprobar dispositivo, inode, modo, fechas, tamaño y asignación. Nunca se retienen lecturas fallidas o inestables; los documentos devueltos son copias independientes. Una instantánea cambiada se reconstruye a partir de las entradas capturadas y se comprueba otra vez antes de publicarla. Las entradas no fiables no pueden renovar una respuesta correcta. Las lecturas de sidecars son estrictas y se limitan al vault de la petición; los cambios semánticos también actualizan los nodos analizados de ese vault. Sin índice canónico, la reconstrucción periódica habitual sigue siendo la alternativa. La compresión JSON del grafo se ejecuta en un worker y reutiliza bytes de la misma instantánea inmutable, conservando la invalidación y el manejo de resultados parciales. Los recuentos de carpetas de correo utilizan una conexión separada y de vida corta para que su escaneo no serialice el listado de mensajes en la misma conexión. El listado de cabeceras obtiene solo los campos que consume; las credenciales se resuelven de manera fresca al utilizar el proveedor. Configuración carga tablas y bases de datos concurrentemente y conserva cualquier resultado correcto si el otro falla. El arranque solapa la lectura de salud con la preparación de ruta, compartiendo su petición pendiente con el control de autenticación y la barra lateral.
Las lecturas de mensajes conservan su campo de error explícito cuando el proveedor no puede conectarse, seleccionar o buscar en la carpeta, u obtener cabeceras. Esas respuestas nunca sustituyen una caché válida de listado ni renuevan su frescura. Los recuentos devuelven 503 reintentable si fallan o superan el límite global de lectura de 30 segundos; una lectura compartida puede terminar en segundo plano para otro consumidor. Los GET de listado y recuento de Microsoft también utilizan un timeout de red de 20 segundos, de modo que el worker subyacente está limitado. La interfaz publica los recuentos correctos de las cuentas a medida que llegan e identifica las cuentas pendientes o no disponibles y los recuentos anteriores conservados. Un listado visible o una respuesta de mensajes HTTP200 por sí solos no demuestran una lectura fresca correcta de todas las cuentas. Invalidar recuentos también retira las identidades de lecturas en curso, evitando que un worker antiguo publique o renueve un recuento anterior a la mutación. La paginación publica cada página de cuenta independientemente. Las páginas fallidas conservan su cursor y mensajes visibles, y la acción de reintento pide solo esas páginas.
Mida tanto las primeras lecturas como las repetidas, y distinga las respuestas API completas del contenido representado utilizable. Un listado en caliente por debajo de 500 ms no establece un presupuesto de navegación de 500 ms: los escaneos iniciales de la nube, catálogos externos, miniaturas y representación del navegador aún requieren medidas separadas.
Build del frontend y enlaces directos¶
Ejecute corepack pnpm build:frontend desde la raíz del repositorio. Las
comprobaciones previas incluyen el contrato de la configuración real de Vite.
Por defecto, los recursos utilizan /: los enlaces profundos y las recargas
resuelven JavaScript, estilos e iconos desde la raíz del origen. El mismo
artefacto sirve para el alojamiento web HTTP y el protocolo estándar app://gnosi de
Electron; Electron no necesita una base relativa ./.
VITE_BASE_PATH se mantiene como configuración explícita de la base de recursos.
El valor ./ reintroduce la resolución relativa en rutas anidadas. Un prefijo
de recursos no configura la base del enrutador ni demuestra soporte para montar
toda la app bajo un prefijo de URL. Mantenga el valor por defecto para las
estructuras web y desktop estándar. El servidor HTTP debe devolver la entrada
SPA para las rutas de la app, servir los recursos reales y enviar /api al
backend. Vite preview ya incluye ese proxy de API; es un servidor de validación,
no una prueba de aceptación del despliegue en producción.
Configuración y datos persistentes¶
La carga del entorno del backend sigue este orden para cada variable: entorno
del proceso, .env local del repositorio y archivo compartido seleccionado
explícitamente mediante GNOSI_SHARED_ENV_FILE. No se busca implícitamente
ningún .env_shared en los directorios padre. El archivo compartido pertenece
al operador y la limpieza del entorno de Gnosi no lo modifica. El almacenamiento
seguro nativo puede aportar credenciales que faltan; no sustituye un valor
ya establecido.
Después de cargar el entorno, la resolución del directorio de datos toma el
primer valor no vacío en este orden: GNOSI_DATA_DIR, GNOSI_LOCAL_DATA,
LOCAL_DATA_DIR y valor predeterminado de la plataforma. Ambos alias están
obsoletos, pero siguen admitidos durante toda la serie 3.x. Configure el nombre
canónico de forma coherente: un valor canónico en conflicto prevalece sobre un
alias, aunque este proceda de una fuente de entorno de mayor prioridad.
Prefiera rutas absolutas: las relativas se resuelven respecto al directorio
de trabajo del proceso.
| Entorno del backend | Directorio de datos predeterminado si no se ha configurado |
|---|---|
| macOS | ~/Library/Application Support/Gnosi |
| Linux | $XDG_DATA_HOME/gnosi o, si no está definido, ~/.local/share/gnosi |
| Windows | %APPDATA%\Gnosi o, si no está definido, ~/AppData/Roaming/Gnosi |
| Docker | /data; Compose monta ahí el volumen con nombre gnosi_local_data. |
El antiguo directorio local_data dentro del checkout no es el valor
predeterminado nativo. El contenido del vault y su configuración .gnosi/
están separados del estado de cada dispositivo. Mantenga GNOSI_DATA_DIR
en almacenamiento local no sincronizado, fuera del árbol de código.
Conserve system/management.sqlite, system/tool_registry.sqlite,
system/checkpoints, secrets y el resto del estado necesario antes de
reinstalar o migrar. No copie archivos SQLite en uso a un vault sincronizado
ni ejecute instancias independientes de Gnosi sobre el mismo directorio de
datos. En otro dispositivo puede ser necesario volver a conectar OAuth,
porque las credenciales y el almacenamiento seguro son locales.
Para trasladar los datos de forma deliberada, revise
scripts/migrate-data-dir.py: ofrece plan, migrate, status,
rollback y finalize. La planificación puede crear el directorio padre
de destino; por tanto, no es un diagnóstico puramente de lectura. Detenga
todos los procesos que escriben antes de migrar o revertir;
--writers-stopped es una confirmación del operador, no un detector de
procesos. El servicio registra el progreso en un diario, comprueba la
integridad SQLite y consolida el WAL. Realiza un cambio de nombre dentro del
mismo volumen o una copia provisional verificada entre volúmenes; en el
segundo caso conserva el origen. Guarde el diario y la copia de seguridad,
verifique el destino y configure GNOSI_DATA_DIR antes de reiniciar.
Cambiar solo la variable no traslada los datos existentes.
Primera secuencia de diagnóstico¶
- Identifique el entorno elegido, el checkout, el propietario del proceso y quién escucha en cada puerto antes de iniciar o reiniciar nada.
- Revise los registros del backend y del frontend de ese entorno; no presuponga las rutas de los LaunchAgents.
- Consulte
/api/health:status,mode,gnosi_mode,require_authyvault_configured. Una respuesta de salud no demuestra que el vault se pueda leer. - Utilice una sesión autorizada para
/api/configy/api/vault/pages. Distinga los errores de autenticación o permisos de un vault vacío o un error de E/S; oculte credenciales y rutas privadas antes de compartir diagnósticos. - Confirme el vault activo, el directorio de datos efectivo y el proveedor seleccionado. No restablezca la configuración ni sustituya bases de datos para corregir una ruta equivocada.
- Reproduzca la acción afectada de la interfaz mientras revisa la consola del navegador y los registros del backend; después ejecute la prueba más específica.
- Tras la reparación, verifique tanto los datos devueltos como la acción visible; reiniciar un proceso no es, por sí solo, prueba de recuperación.
Disponibilidad de archivos y recuperación específica del proveedor¶
Empiece por el adaptador seleccionado en backend/platform/files.
GNOSI_FILES_PROVIDER selecciona explícitamente un proveedor reconocido;
en caso contrario, la detección utiliza VAULT_HOST_PATH.
LocalProvider no realiza ninguna hidratación. El nombre de un proveedor
o una interfaz compartida no acreditan el comportamiento de todos los
clientes de nube en todos los sistemas operativos.
En almacenamiento File Provider de macOS, EDEADLK o EAGAIN pueden
indicar archivos no disponibles que solo están en la nube. Estos errores,
por sí solos, no demuestran un fallo del proveedor ni del analizador Markdown:
compruebe la ruta exacta, los indicadores del archivo, los bloques descargados
y el estado del cliente. Reintente el ámbito afectado más pequeño con intentos
limitados y secuenciales; no convierta una exploración de recuperación parcial
en un índice completo ni sustituya contenido ilegible por archivos vacíos.
Mantener los directorios críticos descargados localmente puede evitar que
el problema se repita.
El adaptador actual de archivos bajo demanda utiliza open por defecto en
macOS nativo y delega las lecturas en una aplicación gráfica mediante
LaunchServices; las lecturas directas desde un proceso launchd pueden no
activar la descarga. El modo daemon llama a un servicio auxiliar del host
configurado, con los valores predeterminados
http://127.0.0.1:5009/warmup en nativo o
http://host.docker.internal:5009/warmup desde Docker. Ese servicio debe
estar realmente configurado para el entorno elegido; el puerto 5009 no es
un requisito general de arranque ni una prueba de que la hidratación funcione
con cualquier nube.
Solo el adaptador de OneDrive activa el reinicio del cliente OneDrive después
de un intento open fallido. ONEDRIVE_AUTO_RESTART=0 desactiva esa acción;
el intervalo mínimo predeterminado entre reinicios es de 300 segundos.
Trate los reinicios del cliente y la configuración de los servicios auxiliares
del host como cambios operativos separados. No aplique las instrucciones de
recuperación de OneDrive a otros proveedores.
Configuración opcional del host macOS¶
Los 15 scripts históricos del runtime del host (instaladores, watchdogs y
herramientas del host), junto con los lanzadores obsoletos run_brain.sh y
run_prod.sh, se han retirado del repositorio público. Las operaciones del host
pertenecen al repositorio privado WorkspaceTools. Ejecute pnpm check:runtime
tras preparar los cambios revisados: CI rechaza scripts retirados, enlaces
simbólicos y estado local en el índice Git. Las instalaciones existentes
pueden escribir registros en ~/Library/Logs/Gnosi; revise su configuración real. Son
facilidades opcionales del host, no el contrato de arranque portable. Las
definiciones de servicios específicas de cada máquina, las rutas privadas y
el historial de incidentes pertenecen al repositorio privado WorkspaceTools,
no a los requisitos públicos.
Esta limpieza del checkout no modifica, migra ni desinstala los servicios
instalados del host. Los wrappers portables anteriores no instalan ni eliminan
servicios existentes del host. El instalador histórico install_native_startup.sh
detiene los procesos que escuchan en 5002/5173 y recarga LaunchAgents.
No ejecute los instaladores o watchdogs conservados como diagnóstico; revise
la configuración real instalada y los procedimientos privados.
Si una instalación aún utiliza una copia conservada de native_watchdog.sh, revise
~/.gnosi_native_watchdog.log para detectar bucles de reinicio. El margen
de arranque (GNOSI_NATIVE_STARTUP_GRACE) y el intervalo mínimo entre
reinicios (GNOSI_NATIVE_WATCHDOG_COOLDOWN) son de 600 segundos por defecto.
Deje tiempo suficiente para un arranque en frío o una recarga y mantenga el
intervalo al menos tan largo como el tiempo de arranque medido. Una señal
reciente de actividad del clon puede aplazar el reinicio. El script también
mata procesos multiprocessing coincidentes e invoca launchd: la selección
de procesos es amplia; no lo ejecute como diagnóstico genérico ni lo instale
sin revisar las otras cargas Python del host.
Despliegue Docker opcional¶
Docker es un destino de autoalojamiento compatible y opcional. El archivo base
docker-compose.yml no necesita ningún directorio de vault del host ni rutas
propias del mantenedor:
| Contenido persistente | Volumen con nombre | Ruta en el contenedor |
|---|---|---|
| Bases de datos y credenciales por dispositivo | gnosi_local_data (clave conservada) |
/data, mediante GNOSI_DATA_DIR |
| Vaults | gnosi_vaults (volumen nuevo) |
/vaults, mediante GNOSI_VAULTS_ROOT; activo predeterminado /vaults/default |
Los vaults existentes del host no se copian automáticamente al volumen nuevo.
Conserve el nombre del proyecto Compose al actualizar: determina la identidad
de los volúmenes con nombre. Cambiarlo puede seleccionar volúmenes vacíos
mientras los datos anteriores siguen existiendo. Haga copias de seguridad de
las bases de datos, credenciales y vaults antes de cualquier cambio. Nunca
utilice docker compose down -v ni una purga generalizada de volúmenes para
reparar dependencias.
Los puertos publicados son 127.0.0.1:5002 y 127.0.0.1:5173 por defecto.
GNOSI_BIND_ADDRESS, GNOSI_BACKEND_PORT y GNOSI_FRONTEND_PORT configuran
la publicación en el host; los puertos internos siguen siendo 5002/5173 y el
frontend actúa como proxy hacia backend:5002. Compose fuerza HTTP en el
frontend. Revise la autenticación, TLS y el acceso de red antes de cambiar la
dirección de escucha para exponer el servicio.
Proporcione un GNOSI_JWT_SECRET privado y robusto mediante el shell o el
.env local para la interpolación de Compose. Un env_file del servicio no
satisface, por sí solo, la expresión obligatoria. Compose establece
explícitamente GNOSI_REQUIRE_AUTH=1; no desactive la autenticación para
superar una prueba básica.
Compose lee un env_file compartido opcional seleccionado mediante
GNOSI_SHARED_ENV_FILE (alternativa .env.shared.disabled) y después el
.env opcional; este último prevalece en las claves repetidas. Las entradas
explícitas de environment del servicio prevalecen sobre ambos archivos.
Son reglas del entorno del contenedor: las variables arbitrarias del shell
del host no se transmiten automáticamente. Compose lee los archivos en el
host, sin montarlos ni incluirlos en las imágenes, y vacía
GNOSI_SHARED_ENV_FILE dentro del backend para no volver a cargar una ruta
del host. No exige implícitamente ningún .env_shared de los directorios padre.
El conjunto incluye el translation-server de Zotero internamente en 1969,
sin publicarlo en el host. GNOSI_TRANSLATION_IMAGE selecciona su imagen;
TRANSLATION_SERVER_URL toma http://translation-server:1969 solo si no
está definida y conserva un valor vacío explícito. La traducción es opcional
para Gnosi, pero este archivo Compose declara el servicio auxiliar sin un
perfil opcional.
Para utilizar directorios existentes del host, añada explícitamente
compose.vaults.yml:
Antes de esa orden, proporcione VAULT_HOST_PATH (vault activo existente)
y VAULTS_ROOT_HOST_PATH (directorio padre existente) a la interpolación de
Compose. Ambas rutas son obligatorias; los dos montajes utilizan
create_host_path: false para rechazar directorios inexistentes. Prefiera
rutas absolutas; las relativas se resuelven desde el directorio del Compose
base. La sobrescritura sustituye el volumen de /vaults según el destino en
el contenedor, añade el montaje activo en /vault y establece
DIGITAL_BRAIN_VAULT_PATH=/vault. Conserva gnosi_local_data:/data y
transmite las dos rutas del host seleccionadas para traducir las acciones
sobre archivos. No copia datos ni configura servicios auxiliares del host.
El conjunto base no monta código fuente, dependencias del host, directorio
personal, árbol privado .antigravity, directorio de secretos ni socket
Docker. La sobrescritura de vaults añade solo los dos directorios
seleccionados. El CLI Docker de la imagen del backend no da acceso al motor
del host sin un socket o un endpoint configurado por separado. El código y las
dependencias pertenecen a las imágenes: no hay recarga del código del host ni
volúmenes anónimos de node_modules que renovar. Reconstruya las imágenes si
cambian el código o los archivos de bloqueo; conserve los volúmenes persistentes.
Dockerfile.frontend utiliza Node 22.22.2, pnpm 11.19.0 y
--frozen-lockfile, y sirve Vite en el puerto estricto 5173. El backend exporta
uv.lock con --frozen, instala el wheel fijado de Torch solo para CPU y
después los requisitos exportados; uvicorn se ejecuta sin --reload.
La disponibilidad del wheel, las compilaciones y el arranque requieren
validación por plataforma. Los tests estáticos de código y contratos no
sustituyen la fusión real de Compose, las compilaciones en el motor, las pruebas
básicas de los contenedores ni la aceptación por plataforma.
Aceptación autenticada y límites de la QA¶
La aceptación nativa debe probar el registro real, la creación de un workspace
y del primer vault, el inicio de sesión, /api/auth/me, las cookies HttpOnly
y la preparación de autenticación de Playwright, con arranque y parada limpios.
En el navegador hay que crear y editar una página desechable, recargarla y
reabrirla para verificar la persistencia del título y del cuerpo, revisar la
consola y comprobar el cierre de sesión. Superar la fixture y el flujo de
navegador no acredita toda la suite E2E, la matriz Docker/Electron ni una publicación.
La preparación E2E exige GNOSI_TEST_EMAIL y GNOSI_TEST_PASSWORD explícitos
de una cuenta de prueba desechable ya creada antes de acceder a la red.
Inicia sesión y la verifica con /api/auth/me; no registra cuentas ni inventa
una identidad de administrador. GNOSI_TEST_WORKSPACE_ID debe corresponder
a una pertenencia verificada; omítalo solo si hay exactamente una.
GNOSI_TEST_VAULT_ID es opcional y no concede permisos. Mantenga privado el
estado de sesión, preferiblemente en un GNOSI_TEST_STORAGE_STATE temporal,
y no active trazas, capturas, vídeo ni registros de diagnóstico de la
preparación que puedan contener credenciales.
backend/tests/test_vault_creation_membership.py cubre la creación del
primer vault con pertenencia autenticada owner/admin/editor, rechaza
peticiones sin autenticar, de solo lectura o de otros workspaces, y comprueba
el confinamiento de rutas y el listado de organización sin registrar el vault
personal. Esta cobertura de regresión no sustituye la validación real de la
aplicación y del navegador. El responsable de integración mantiene las
comprobaciones completas de navegador, CI, SOP y aceptación por plataforma.
Desde la raíz del repositorio, corepack pnpm test:e2e:contracts ejecuta los
contratos de autenticación, JSON y rutas de API sin red, y después comprueba
estrictamente los tipos de todos los archivos TypeScript E2E activos y de apoyo:
pruebas funcionales, anónimas, de accesibilidad y visuales. El alias específico
typecheck:auth sigue disponible. No inicia la aplicación ni sustituye la
aceptación real de inicio de sesión y navegador; las pruebas JavaScript archivadas
quedan fuera de esta comprobación.
Empaquetado Electron opcional¶
Electron utiliza el valor heredado de GNOSI_DATA_DIR, después
GNOSI_LOCAL_DATA y después LOCAL_DATA_DIR; si no hay ninguno, pasa su
perfil userData al backend incluido. No presuponga que ese perfil coincide
con el directorio predeterminado de Python nativo en todos los sistemas
operativos. Conserve el perfil y también los datos del backend configurados
por separado antes de actualizar.
El workspace fija la versión de Electron y desactiva la descarga automática
del binario. corepack pnpm --filter @gnosi/desktop install:runtime es el
paso explícito de instalación del binario para ejecutar Electron localmente.
Compile el frontend antes de empaquetar. desktop/build-python.sh requiere
Python 3.11 y uv, crea un entorno temporal y utiliza
uv sync --frozen --no-default-groups --group desktop con el archivo de
bloqueo del repositorio. Comprueba los límites de los recursos, ejecuta
PyInstaller, verifica el paquete y ejecuta la prueba básica del backend
empaquetado. Actualmente no se fija pip 25.3; diagnostique los errores de
proxy o del índice de paquetes en el runner afectado en vez de recuperar
aquella solución histórica.
| Destino declarado en el workflow de publicación | Artefactos configurados |
|---|---|
| macOS arm64 | DMG y ZIP |
| macOS x64 | DMG y ZIP |
| Linux arm64 | AppImage y DEB |
| Windows x64 | Instalador NSIS |
Son destinos configurados, no resultados de aceptación. La arquitectura del backend Python empaquetado debe coincidir con el destino Electron. Los jobs de publicación actuales no cubren Linux x64 ni Windows arm64. Los contratos estáticos o una compilación del frontend no acreditan una instalación limpia, el primer arranque, la actualización, la reversión, la firma ni la conservación de datos reales en ningún destino. Exija pruebas reales de cada plataforma antes de publicar; la validación de Docker es una comprobación separada.
Mapa de síntomas habituales¶
| Síntoma | Área probable | Siguiente evidencia |
|---|---|---|
| Frontend en blanco | Error JavaScript, fragmento antiguo, inicialización de la autenticación | Consola del navegador, registro de Vite, compilación de producción. |
| La salud responde, pero el vault falla | Ruta del vault, permisos, disponibilidad de archivos | Configuración autorizada, registros del vault, ruta exacta que falla. |
| La configuración se revierte | Destino de params incorrecto, escritura fallida, migración | Contexto del vault activo y origen de los parámetros. |
| Una integración aparece desconectada | Credencial local ausente o selección de cuenta obsoleta | Estado de la cuenta con secretos ocultos y almacenamiento de secretos configurado. |
| El agente no tiene herramientas | Conexión MCP, validación del catálogo, asignación de skills | Registros de descubrimiento y endpoints de skills autorizados. |
| El correo deja de actualizarse | Proceso de la cuenta o autenticación del proveedor | Estado del proceso de cada cuenta y sincronización incremental. |
| El escritorio muestra una versión antigua | Renderer/backend antiguo o manifests incoherentes | Checkout/paquete realmente en ejecución y versiones de los paquetes. |
Documentación y aprendizaje de los incidentes¶
Utilice el workflow pre-PR de documentación descrito en
Mantenimiento de la documentación.
Revise manualmente los cuatro idiomas; actualice de forma determinista solo
los catálogos generados. El responsable de integración ejecuta las
comprobaciones pre-PR, las compilaciones estrictas de los cuatro portales y
la QA en el navegador cuando los workers hayan terminado. Mantenga
site/engineering y los subdirectorios de idiomas fuera del control de versiones.
El workflow de Pages está configurado para publicar los cambios de
documentación de main en el
portal de ingeniería.
Si falla, revise la validación de las referencias generadas, la trazabilidad
y las compilaciones estrictas de los idiomas antes del artefacto Pages.
Compruebe la fuente real de publicación de Pages y los permisos del entorno
github-pages; el código del workflow no demuestra que el despliegue haya funcionado.
Registre las causas de los incidentes, los intentos fallidos y la recuperación
verificada. Mantenga los detalles privados de las máquinas y las directivas
de desarrollo en WorkspaceTools; publique solo lecciones portables con
pruebas de código y tests. Corrija la implementación y añada pruebas de
regresión específicas cuando proceda. Una recuperación realizada solo en
el terminal, sin verificación ni documentación, no completa una reparación operativa.
Regeneración del logo de la aplicación¶
frontend/public/favicon.svg es el logo canónico de Gnosi. La G blanca tiene
una curva inferior derecha sin el extremo vertical descendente. Mantenga este
logo como trazados vectoriales para que los iconos de las releases no dependan de las fuentes instaladas.
Después de cambiar el SVG, instale desktop/scripts/requirements-icons.txt en
un entorno Python y ejecute python desktop/scripts/generate-icons.py desde
la raíz del repositorio. En macOS, el proceso Python debe poder encontrar Cairo
(para una instalación Homebrew, DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib).
El generador actualiza los recursos PNG/ICNS/ICO de escritorio, los PNG de la PWA y el favicon ICO, los iconos del capturador web (16, 32, 48, 128 y 512 píxeles) y los del complemento Word (16, 32, 64 y 80 píxeles). Guarde el SVG canónico y todos los recursos generados juntos en el repositorio antes de empaquetar una release. Los iconos ilustrados de las funcionalidades no derivan del logo de la aplicación.