# Auditoria Codex - ecosistema Active + Orca Fecha: 2026-05-04 Workspace: `G:\dev\svelte\active` ## Alcance Se audito el estado actual del ecosistema con foco en el nuevo modulo `src/arts/orca` y sus puntos de acoplamiento con: - `src/arts/active-app` - `src/arts/bus` - `src/arts/session` - `src/arts/cache` - `src/arts/perm` - `src/arts/connection` - documentacion publica en `src/arts/*/README.md` y pagina activa generada. No se modifico codigo existente. El arbol ya tenia cambios previos en: - `src/arts/orca/consts.ts` - `src/arts/orca/result.ts` - `src/arts/orca/types.ts` Esos cambios parecen corregir parte de la deriva de comentarios `v0.1+` respecto a timeout/fatal/gates/compensation, pero no cierran todos los problemas. ## Veredicto `orca` esta bien orientado arquitectonicamente. La decision fuerte, y la que realmente eleva el ecosistema, es mover las reacciones inter-modulo a una capa de orquestacion declarativa situada en `active-app`, no dentro de `cache`, `perm`, `session` o `connection`. Eso reduce acoplamiento y permite testear flujos compuestos como objetos de ejecucion (`OrcaRunResult`). El modulo, sin embargo, ya ha crecido mas rapido que su contrato. El motor actual implementa gates, timeouts de accion, compensacion, transacciones, payloads en tokens, fan-in y politicas de cola. La documentacion mezcla tres versiones a la vez: boceto conceptual, v0 inicial y estado real. Antes de seguir expandiendo `orca`, conviene congelar el contrato real y eliminar ambiguedades. Estado de pruebas focalizadas: ```txt npx vitest run src/arts/orca/test src/arts/active-app/test/presets.test.ts Test Files 4 passed Tests 169 passed ``` ## Hallazgos P1 ### 1. Liberacion de trace no es segura con runs paralelos Referencia: - `src/arts/orca/engine-orca.ts:928` - `src/arts/orca/engine-orca.ts:931` - `src/arts/orca/engine-orca.ts:935` `maybeReleaseTrace()` borra `traceStates` si no quedan eventos en cola. El propio comentario reconoce que no sabe si hay runs en vuelo del mismo trace. Eso era defendible con ejecucion estrictamente secuencial, pero ya existe `ORCA_QUEUE_PARALLEL`. Si dos eventos derivados del mismo trace corren en paralelo, el primero que termine puede borrar el estado de trace mientras el otro sigue vivo. Impacto: - Los contadores `maxDepth`, `maxEventsPerTrace`, `repeatedEventLimit` y `dedupeKey` pueden resetearse antes de tiempo. - Un loop por eventos derivados puede saltarse la proteccion si el trace se borra mientras quedan runs paralelos activos. - La trazabilidad de un flujo enterprise deja de ser confiable justo en el modo mas peligroso: paralelo. Recomendacion: - Mantener `traceInFlightCount` por `traceId`. - Incrementarlo en `spawnRun()`. - Decrementarlo en el `finally` de `executeRun()`. - Liberar el trace solo cuando `queuedCount(traceId) === 0` e `inFlightCount(traceId) === 0`. - Anadir test: dos eventos derivados con `ORCA_QUEUE_PARALLEL` en el mismo trace; el primero termina, el segundo emite otro evento repetido y el guard sigue aplicando. ### 2. `provides` no limita `emits`, asi que la validacion puede mentir Referencia: - `src/arts/orca/types.ts:421` - `src/arts/orca/types.ts:424` - `src/arts/orca/types.ts:425` - `src/arts/orca/engine-orca.ts:1117` - `src/arts/orca/engine-orca.ts:1124` El contrato dice que `provides` es lo que una accion puede producir, y `validate()` usa `provides` para detectar tokens imposibles. Pero el runtime acepta cualquier token que venga en `result.emits`, aunque no este declarado en `provides`. Impacto: - `validate()` no es una garantia fuerte; es una estimacion basada en intencion. - Una accion puede desbloquear otra con un token que el grafo no declaraba. - Un typo en `emits` puede cambiar el pipeline sin que `validate()` lo vea. - El futuro `setupOrca()` tipado pierde parte de su sentido si el runtime permite emisiones fuera de esquema. Recomendacion: - En modo dev, lanzar o registrar `CONFIGURATION_INVALID` cuando una accion emite un token no declarado en `provides`. - En modo prod, al menos registrar diagnostic `orca.configuration.invalid` o descartar el token no declarado segun opcion. - Documentar excepcion solo si se decide permitir tokens dinamicos, pero entonces `validate()` debe llamarse "best effort", no "static graph validation". ### 3. `ORCA_QUEUE_REPLACE` no es `replace-current`, solo reemplaza queued Referencia: - `src/arts/orca/consts.ts:73` - `src/arts/orca/engine-orca.ts:420` - `src/arts/orca/engine-orca.ts:421` - `src/arts/orca/engine-orca.ts:422` - `src/arts/orca/README.md:439` - `src/arts/orca/README.md:1444` Hay dos semanticas distintas usando el mismo nombre mental: - Una seccion del README describe `replace` como "aborta el run activo y empieza uno nuevo", estilo `takeLatest`. - El motor implementa "reemplaza solo entradas queued; no aborta in-flight". - Otra seccion posterior del README ya reconoce esta realidad. Impacto: - Para formularios, busquedas, navegacion o cambio de identidad, un usuario puede esperar "ultima intencion gana", pero el run anterior seguira ejecutandose. - Si la accion vieja muta cache/conexiones despues de la nueva, puede pisar estado. - El nombre `replace` es ambiguo para usuarios que vienen de saga/Rx/RTK. Recomendacion: - Renombrar la politica actual a algo explicito: `ORCA_QUEUE_REPLACE_QUEUED` o `ORCA_QUEUE_LATEST_QUEUED`. - Reservar `ORCA_QUEUE_REPLACE_CURRENT` / `ORCA_QUEUE_TAKE_LATEST` para la variante fuerte que aborta in-flight. - Si se mantiene el nombre actual, borrar del README cualquier promesa de abortar el run activo. ### 4. IDs de run/event/trace usan `Date.now()` y `Math.random()` fuera de `timr` Referencia: - `src/arts/orca/engine-orca.ts:1513` - `src/arts/orca/engine-orca.ts:1514` - `src/arts/orca/engine-orca.ts:1517` - `src/arts/orca/engine-orca.ts:1518` - `src/arts/orca/engine-orca.ts:1521` - `src/arts/orca/engine-orca.ts:1522` - `src/arts/orca/README.md:841` El README establece que `orca` no debe usar `Date.now()` ni `setTimeout()` directamente. Los timestamps del envelope ya pasan por `timers.clock.now()`, pero los IDs de run/event/trace no. Impacto: - Tests y replay no son plenamente deterministas. - En SSR/hydration o tests con clocks controlados, los IDs no siguen el tiempo simulado. - La disciplina "todo tiempo via timr" queda rota justo en el modulo que quiere ser trazable. Recomendacion: - Anadir `idFactory` a `EngineOrcaOptions` o tres factories separadas: `runIdFactory`, `eventIdFactory`, `traceIdFactory`. - Default: contador monotono con prefijo, alimentado por `timers.clock.now()` si se quiere incluir tiempo. - Tests: factory determinista para snapshots. ### 5. `setupOrca()` esta documentado como API recomendada pero no existe Referencia: - `src/arts/orca/README.md:235` - `src/arts/orca/README.md:241` - `src/arts/orca/README.md:271` - `src/arts/orca/README.md:284` - `src/arts/orca/README.md:1271` - `src/arts/orca/index.ts` El README recomienda `setupOrca()` para apps grandes y muestra ejemplos, pero no hay export ni implementacion en `src/arts/orca`. Impacto: - La documentacion invita a usar una API inexistente. - El usuario no sabe si debe usar `App.Orca.onEvent()` directo, presets o un setup tipado futuro. - La promesa de validacion fuerte de tokens/eventos queda sin soporte. Recomendacion: - O implementar un `setupOrca()` minimo, aunque solo envuelva `onEvent` con declaracion de eventos/tokens/actions. - O mover esa seccion a "Futuro / v0.1" y dejar claro que v0 real es `createEngineOrca()` + `App.Orca.onEvent()`. ### 6. La integracion con `connection` no esta cerrada y la documentacion promete mas de lo que existe Referencia: - `src/arts/active-app/presets/standard.ts:28` - `src/arts/active-app/presets/index.ts:5` - `src/arts/active-app/service-factories/connections.ts:9` - `src/arts/connection/README.md:83` - `src/arts/connection/README.md:93` - `src/arts/connection/README.md:100` - `src/arts/connection/session-wiring.ts:27` `applyStandardOrca()` solo registra presets de cache y perm. No hay preset para `connections.reauthenticateAll()` ni para `connections.closeAll()` en cambios de identidad/revoke/expire. A la vez, la documentacion de `connection` habla de `autoReauthOn: 'standard'` y de escuchar `SESSION_EVENT_IDENTITY_CHANGED`. Ademas, `defineActiveConnections()` ya no inyecta `bus` ni `session`; el comentario dice que identidad debe venir por orca preset o por una `session` manual, pero ese preset no existe. Impacto: - Una app que siga la documentacion puede creer que las conexiones se reautentican al cambiar de usuario, pero con `applyStandardOrca(App)` no ocurre. - El caso critico que motivo `orca` ("chat conectado con credenciales del usuario anterior") sigue sin preset estandar. - `connection` conserva un mecanismo interno de `session-wiring` que compite conceptualmente con la nueva regla: los artefactos publican/reciben eventos; la app orquesta reacciones. Recomendacion: - Crear preset en `active-app/presets`: `applyConnectionsReauthOnIdentityChange(App)`. - Definir si el estandar hace `reauthenticateAll()` o `closeAll()` cuando no hay credencial nueva. - Actualizar `applyStandardOrca()` para incluir conexiones cuando `App.connections` exista. - Decidir si `connection.session-wiring` queda como modo local/manual o se depreca a favor del preset de `orca`. ## Hallazgos P2 ### 7. `runActionWithTimeout()` aborta de forma cooperativa, pero la accion puede seguir mutando estado Referencia: - `src/arts/orca/engine-orca.ts:1042` - `src/arts/orca/engine-orca.ts:1052` - `src/arts/orca/engine-orca.ts:1056` - `src/arts/orca/engine-orca.ts:1058` - `src/arts/orca/engine-orca.ts:1070` El timeout hace `actionController.abort()` y resuelve `orcaTimeout(timeoutMs)`, pero la promesa original de la accion sigue viva si la accion no respeta `ctx.signal`. Esto es normal en JS, pero debe tratarse como contrato de seguridad. Impacto: - Una accion timeout puede mutar cache, conexiones o permisos despues de que el run ya haya tomado otra decision. - Los tests pueden pasar porque el resultado es `timeout`, pero el side-effect tardio queda fuera del trace. Recomendacion: - Documentar que toda accion async debe comprobar `ctx.signal.aborted` antes y despues de awaits relevantes. - Anadir helper `ctx.throwIfAborted()` o `orcaAbortIfSignaled(ctx)`. - Anadir test: accion con timeout que intenta mutar despues; demostrar que el patron recomendado lo evita. ### 8. La cola es global para eventos no-parallel, aunque el contrato se lee como per-event Referencia: - `src/arts/orca/engine-orca.ts:526` - `src/arts/orca/engine-orca.ts:527` - `src/arts/orca/engine-orca.ts:529` - `src/arts/orca/engine-orca.ts:531` `canStartRun()` serializa globalmente todos los eventos no-parallel: `nonParallelInFlight === 0`. Eso significa que un evento lento de `cache` puede bloquear un evento no relacionado de `perm`, `connection` o cualquier feature. Impacto: - Semantica mas conservadora y lenta de lo que sugiere "queue policy per event". - Posible cuello de botella en apps grandes con flujos independientes. - Si esta decision es intencional, falta nombrarla como "single lane". Recomendacion: - Decidir explicitamente: - Modelo A: serializacion global por defecto, documentada como garantia simple. - Modelo B: serializacion por evento, con concurrencia entre eventos distintos. - Si se mantiene A, renombrar/comentar como `globalSerialLane`. - Si se pasa a B, usar `inFlightByEvent` para bloquear solo el mismo evento. ### 9. `commit()` congela el grafo; eso choca con features lazy si no se documenta como modo prod Referencia: - `src/arts/orca/types.ts:711` - `src/arts/orca/types.ts:723` - `src/arts/orca/engine-orca.ts:1275` - `src/arts/orca/test/engine-orca.test.ts:4013` El comportamiento actual esta claro en codigo y tests: despues de `commit()`, `onEvent()` y `configureEvent()` lanzan `OrcaFrozenError`. Esto no es un bug por si mismo, pero tensiona el objetivo de registrar acciones desde features lazy-loaded. Impacto: - Si una app llama `App.Orca.commit()` durante bootstrap, una ruta lazy ya no puede registrar sus acciones al cargar. - HMR/devtools pueden quedar bloqueados si no se separa "validar" de "sellar". Recomendacion: - Documentar `commit()` como opcion production/seal, no como paso obligatorio. - Considerar `validate()` para dev y `commit()` solo para builds donde el grafo es completo al arrancar. - Si se quiere lazy + freeze, introducir versionado por evento: cada run usa un snapshot, pero el registro global puede crecer entre runs. ### 10. `ctx.emit()` es correcto, pero la atribucion via `bus.publish()` depende de AsyncLocalStorage Referencia: - `src/arts/orca/engine-orca.ts:133` - `src/arts/orca/engine-orca.ts:204` - `src/arts/orca/engine-orca.ts:864` - `src/arts/orca/als.ts` - `src/arts/orca/README.md:606` - `src/arts/orca/README.md:621` - `src/arts/orca/README.md:1470` El diseno correcto es claro: modulo -> `bus.publish()`, accion -> `ctx.emit()`. El motor intenta interceptar `bus.publish()` dentro de acciones mediante AsyncLocalStorage cuando esta disponible. En navegador puede no estar disponible, por lo que el mismo `bus.publish()` dentro de una accion puede ser hijo en Node y root event en browser. Impacto: - Trazas distintas entre SSR/tests Node y browser. - Reentry guards no aplican igual si un evento derivado sale como root. Recomendacion: - Mantener la regla dura: las acciones usan `ctx.emit()` siempre. - Tratar la interceptacion ALS como bonus diagnostico, no como contrato. - Anadir lint/documentacion: no usar `App.Bus.publish()` dentro de una accion de `orca` salvo que se quiera crear root event explicito. ### 11. `engine-orca.ts` ya es un monolito de responsabilidades Referencia: - `src/arts/orca/engine-orca.ts` (~58 KB) El engine concentra registro, cola, trace state, reentry, ejecucion de waves, timeouts, compensation, validation, ID generation, diagnostics y public API. Impacto: - Dificulta revisar invariantes delicadas como "trace cleanup + parallel". - Hace mas probable que futuras features (`runTimeoutMs`, `setupOrca`, inspector) entren sin frontera clara. - Ya contradice la direccion del ecosistema de reducir monolitos (`connection.ts` se venia refactorizando por el mismo motivo). Recomendacion de split: - `queue.ts`: enqueue, policies, drain, in-flight counters. - `trace.ts`: envelope, trace state, reentry guards, release. - `runner.ts`: stages, waves, action execution, status precedence. - `timeouts.ts`: action timeout helpers y timer keys. - `compensation.ts`: LIFO compensation / transaction compensation. - `validation.ts`: validate/commit helpers. - `ids.ts`: factories deterministas. - `engine-orca.ts`: composicion publica. ### 12. Los presets usan action ids y tokens inline/locales Referencia: - `src/arts/active-app/presets/cache-clear-on-identity-change.ts:6` - `src/arts/active-app/presets/cache-clear-on-identity-change.ts:7` - `src/arts/active-app/presets/cache-clear-on-revoke.ts:6` - `src/arts/active-app/presets/cache-clear-on-revoke.ts:7` - `src/arts/active-app/presets/perm-invalidate-on-identity-change.ts:6` - `src/arts/active-app/presets/perm-invalidate-on-identity-change.ts:7` Los eventos del ecosistema ya estan centralizados como constantes, pero los `ACTION_ID` y `TOKEN_*` de presets quedan como strings locales no exportados. Impacto: - No se pueden reutilizar en tests de integracion, docs, inspector `/test/orca` o setup tipado. - Rompe la regla emergente: "eventos, tokens y action ids como constantes". - El inspector no puede mostrar nombres canonicos importables. Recomendacion: - Crear `src/arts/active-app/presets/consts.ts` o exportar desde cada preset: `APP_ORCA_ACTION_CACHE_CLEAR_ON_IDENTITY_CHANGE`, `APP_ORCA_TOKEN_CACHE_CLEARED_ON_IDENTITY_CHANGE`, etc. - Usar nombres de constantes en README y pagina docs. ## Hallazgos P3 ### 13. Header de `engine-orca.ts` esta obsoleto Referencia: - `src/arts/orca/engine-orca.ts:24` - `src/arts/orca/engine-orca.ts:25` - `src/arts/orca/engine-orca.ts:26` El comentario inicial dice que `after`, `unless`, `abortOn`, `actionTimeoutMs` y `compensate` se aceptan pero se ignoran. El motor ya los implementa. Impacto: - La siguiente persona que lea el archivo empieza con un mapa mental falso. - Ya se corrigieron comentarios en `types.ts`, `consts.ts` y `result.ts`, pero el comentario mas importante del motor sigue atrasado. Recomendacion: - Actualizar el bloque de cabecera para describir el estado real. - Evitar version tags contradictorios dentro del codigo; mover roadmap al README. ### 14. El README de `orca` mezcla contrato actual, boceto y roadmap en un solo flujo Referencia: - `src/arts/orca/README.md:511` - `src/arts/orca/README.md:1411` - `src/arts/orca/README.md:1506` - `src/arts/orca/README.md:1522` Ejemplo claro: una seccion dice que en v0 los tokens son flags sin payload; otra seccion posterior dice que los tokens con payload ya estan implementados. Esto no es solo estetico: afecta al modo en que un desarrollador modela acciones. Impacto: - La documentacion no sirve como contrato normativo. - Los lectores no saben si estan viendo la version deseada o la version real. Recomendacion: - Reestructurar README en tres bloques cerrados: - "Contrato actual implementado" - "Patrones recomendados" - "Roadmap / no implementado" - Eliminar del contrato actual cualquier API no exportada (`setupOrca`) o moverla a roadmap. - Mantener una tabla "Feature -> estado -> archivo/test". ### 15. Falta una prueba compuesta del caso que motivo `orca`: cambio de usuario con cache/perm/connection Referencias: - `src/arts/active-app/test/presets.test.ts` - `src/arts/orca/test/engine-orca.test.ts` Hay buena cobertura unitaria de `orca` y presets basicos. Falta el escenario ecosistema que debe probar el valor real: 1. Usuario A abre sesion. 2. Chat/conexion usa credencial A. 3. Cache actor-scoped guarda datos de A. 4. Perm calcula snapshot de A. 5. Cambia a usuario B. 6. Orca ejecuta clear cache, invalidate perm y reauth/close connection. 7. Ningun dato/credencial de A queda observable. Impacto: - El sistema puede estar correcto por modulo pero fallar justo en composicion. - El caso "chat con credenciales antiguas" sigue sin prueba de regresion. Recomendacion: - Crear test de integracion en `src/arts/active-app/test/ecosystem-orca.test.ts` o equivalente. - Usar fakes de cache/perm/connection con counters y credenciales capturadas. - Verificar orden por `OrcaRunResult`: cache -> perm -> connection si se decide dependencia via tokens. ## Observaciones positivas - `App.Bus`, `App.Timers` y `App.Orca` ya son core siempre presentes en `createActiveApp()`, y `Orca` es inerte hasta registrar acciones. Esa decision encaja con el diseno enterprise sin obligar a cada app a crear singletons manuales. - Los presets viven en `active-app/presets`, no dentro de los artefactos. Esto es correcto: `cache` no debe conocer `session`; `perm` no debe conocer `auth`; `orca` no debe conocer modulos. - `ActiveOrca` es un wrapper fino y razonable: estado reactivo, sin meter logica del engine en Svelte. - La suite focalizada de `orca` ya es grande: 169 tests entre engine/active/result y presets. Para un modulo recien nacido, eso es muy buena base. - `ctx.signal` existe en `OrcaActionContext`; eso habilita cancelacion cooperativa y es la direccion correcta. ## Recomendacion de orden de trabajo 1. Corregir P1.1: trace cleanup con runs paralelos. 2. Cerrar P1.2: `provides` debe ser contrato real o `validate()` debe declararse best-effort. 3. Resolver P1.3: renombrar/split de `replace` para evitar semantica ambigua. 4. Sustituir `Date.now()`/`Math.random()` por factories deterministas. 5. Decidir `setupOrca()`: implementarlo minimo o moverlo fuera de v0. 6. Crear preset de `connection` y test compuesto usuario A -> usuario B. 7. Reordenar README para separar implementado/recomendado/roadmap. 8. Refactorizar `engine-orca.ts` por responsabilidades antes de anadir run/stage timeout, inspector visual o setup tipado. ## Conclusion `orca` merece seguir. No es "otro bus": es el sitio correcto para convertir flujos inter-modulo en artefactos trazables y testeables. Pero precisamente por eso no puede permitirse ambiguedad en nombres, timeouts, tokens y concurrencia. El ecosistema esta cruzando una frontera importante: de librerias coherentes a runtime de aplicacion. La prioridad ahora no es meter mas features, sino hacer que el contrato de `orca` sea tan fiable como su idea.