You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

20 KiB

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:

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.

Powered by TurnKey Linux.