P1.1 — trace cleanup safe under parallel runs.
`TraceState` gains `inFlightRuns`. `spawnRun` increments it
synchronously before the IIFE awaits `executeRun`, decrements it in
its `finally` and only then attempts `maybeReleaseTrace`. The
release helper waits for both the queue snapshot and `inFlightRuns`
to be empty before dropping the entry. Previously a parallel sibling
finishing first could erase counters another run still relied on
(reentry guards, dedupeKeys, abort flags).
P1.2 — `provides` becomes the actual contract. When an action
declares a non-empty `provides`, `runAction` checks each emitted
token against it and emits `orca.configuration.invalid` for every
undeclared token. Soft enforcement: the token is *not* dropped,
keeping runtime back-compat; the diagnostic flags drift between the
declaration and the runtime so authors notice. A v2 strict-drop
mode can opt in later.
P1.3 — `replace` queue policy renamed. The constant is now
`ORCA_QUEUE_REPLACE_QUEUED` (literal `'replace-queued'`). The old
name implied `takeLatest`-style "abort in-flight + queue new", which
the engine never did. The hard variant lives in Roadmap v2 as
`'replace-current'`. Tests updated; v1 has no external consumers
yet so no back-compat alias.
P1.4 — `idFactory` becomes injectable. New `OrcaIdFactory` type +
`EngineOrcaOptions.idFactory`. Default factory uses the injected
`timers.clock.now()` (no more direct `Date.now()` violating the
"all time via timr" rule); replay/snapshot tests pass a
deterministic counter. Eliminated `generateRunId` /
`generateEventId` / `generateTraceId` standalone helpers.
Cleanup leftovers from the audit:
- `engine-orca.ts` header rewritten — was still claiming
`after`/`unless`/`abortOn`/`actionTimeoutMs`/`compensate` are
"accepted, ignored". Now describes the real surface.
- `README.md` "Estado Del Documento" already updated; this commit
also drops the legacy `## Roadmap` block, removes the `setupOrca`
recommendation (moved to roadmap), rewrites "Tokens Flag" to
cover the with-payload form, refreshes the Diagnostics list to
match `consts.ts`, and replaces the "Tests Requeridos" wishlist
with a snapshot of actual coverage + the pending ecosystem test.
Tests: +5 (149 in engine-orca.test.ts, 16 in active-orca, 0 in
result.test.ts → 165 in orca; 1475 / 1475 across the repo).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Un run es una ejecución concreta de un evento. El pipeline interno
de un run no resuelve por sí solo qué ocurre cuando el mismo evento
entra varias veces mientras una ejecución anterior sigue viva. Esa
decisión es parte del contrato del evento y se configura con
`Orca.configureEvent(event, { queuePolicy })`.
Modos previstos:
Constantes vivas (`consts.ts`):
```ts
export const ORCA_CONCURRENCY_QUEUE = 'queue' as const;
export const ORCA_CONCURRENCY_DROP = 'drop' as const;
export const ORCA_CONCURRENCY_REPLACE = 'replace' as const;
export const ORCA_CONCURRENCY_PARALLEL = 'parallel' as const;
ORCA_QUEUE_FIFO // 'fifo'
ORCA_QUEUE_REPLACE_QUEUED // 'replace-queued'
ORCA_QUEUE_DROP_LATEST // 'drop-latest'
ORCA_QUEUE_PARALLEL // 'parallel'
```
Semantica:
Semántica:
| Modo | Uso |
| ---- | --- |
| `queue` | Default obligatorio. No solapa runs del mismo evento; ejecuta el siguiente al terminar el actual. |
| `drop` | Ignora eventos repetidos mientras hay un run activo. Util para doble click o refresh redundante. |
| `replace` | Aborta el run activo y empieza uno nuevo. Util para ultima intencion gana. |
| `parallel` | Permite runs simultaneos del mismo evento. Footgun; queda fuera de v0. |
| `fifo` (default) | Cada evento encola un run; los runs no-paralelos se serializan globalmente. Garantía simple. |
| `replace-queued` | Si llega un evento mientras hay otro encolado, el queued se descarta y se sustituye por el nuevo. **No aborta in-flight.** Última intención pendiente gana. |
| `drop-latest` | Si hay un run del mismo evento in-flight o encolado, el incoming se descarta. Ignora retriggers durante trabajo. |
| `parallel` | Lanza runs concurrentes; eventos paralelos no toman el lock global. Footgun: solapa side-effects. |
`parallel` no debe ser el default. En orquestaciones destructivas como cambio de
identidad, logout, tenant switch, permisos o cache privada, solapar runs es una
fuente directa de condiciones de carrera.
`replace-queued` deja el run activo terminar (FINALLY incluido) — la
variante "fuerte" que aborta in-flight (`replace-current`, takeLatest)
queda en Roadmap v2.
`replace` debe ejecutar `cleanup` y `finally` del run abortado antes de cerrar
su `RunResult`. Si no lo hace, deja recursos/timers/overlays en un estado
ambiguo.
`parallel` queda documentado como posibilidad futura, pero no entra en v0. Si
se implementa, debe exigir opt-in explicito y diagnostics visibles.
`parallel` no es default por una razón: en orquestaciones destructivas
(cambio de identidad, logout, tenant switch, invalidación de permisos,
cache privada), solapar runs es una fuente directa de condiciones de
carrera. Opt-in explícito por evento y diagnostics visibles.
## Tokens
@ -514,20 +473,40 @@ Esta regla no debe ser configurable en v0. Si se necesita estado persistente,
la fuente de verdad es un artefacto (`sess`, `cach`, `perm`, `stor`) y no
`orca`.
### Tokens Flag En v0
### Tokens Flag Y Tokens Con Payload
En v0, los tokens son flags sin payload. Representan que un hecho ocurrio dentro
del run, no transportan datos.
Los tokens son nombres semánticos (`string`) que un run acumula a medida
que las acciones los emiten. Forma básica — flag puro, sin datos: