# `@suaveplan/events` v1.1.0 — Port Missing Capabilities from Suaveplan **Status:** Active **Target:** `@suaveplan/events` 0.0.0 → additive capabilities, no breaking changes **Source:** `/home/ubuntu/web/suaveplan/openspec/changes/events-v1.1.0/` --- ## Why The genesis `EventBus` was a cut-down redesign of suaveplan's `EventEmitter`. While it introduced improvements (interceptor API, `BoundedQueue`, idempotent listeners, deterministic injection), it was missing several capabilities that suaveplan had already proven necessary: - No event buffering for late subscribers — plugins attaching after lifecycle transitions miss historical events. - No wildcard pattern matching — observers must enumerate every event name. - No async iteration — consumers manually manage `on`/`off` instead of `for await`. - No `prependListener` — impossible to insert a listener at the head. - No listener introspection — `listeners()` / `listenerCount()` absent. - No `once()` → `off()` round-trip — `off(type, originalListener)` fails for `once` registrations. - No concurrency control on `emitAsync` — one slow listener blocks the chain. - No `maxListeners` warning — memory leaks go undetected. - No global `errorSink` — caller must inspect `EmitResult.errors` or errors are lost. - No `Symbol.dispose` — no RAII cleanup via `using`. These gaps force consumers to reinvent the missing primitives downstream. --- ## What changes ### Core `EventBus` additions 1. **`bufferSize` option** — replays the last N events to subscribers that attach after emission. 2. **`wildcard` option** — subscribe to `plugin:*` and match all `plugin:ready`, `plugin:error`, etc. 3. **`iter(type, signal?)`** — async iterable over events, compatible with `for await`. 4. **`prepend(type, listener)`** — insert listener at the head of the dispatch queue. 5. **`listeners(type)` / `listenerCount(type)`** — introspection without exposing internals. 6. **`offAll(type?)`** — remove all listeners for a type, or everything. 7. **`once()` WeakMap tracking** — `off(type, originalListener)` works for `once` registrations. 8. **`concurrency` option on `emitAsync`** — `sequential` (default), `parallel`, `allSettled`. 9. **`maxListeners` + `errorSink`** — warnings and centralised error routing. 10. **`Symbol.dispose`** on `EventBus` and `Unsubscribe` handles. 11. **`EVENTS.LISTENER.MAX_EXCEEDED`** error code. ### Non-goals - No breaking changes to existing `EventBus` API. - No `BoundedQueue` integration into `EventBus` dispatch — remains a standalone utility. - No changes to companion packages (`events-otel`, `events-schema`, `events-metrics`, `events-transport`) unless required by API additions. --- ## Impact ### Affected dependents Run `bunx turbo ls --filter=...@suaveplan/events` to enumerate. All additive surface, so no downstream code changes required. Verified by running downstream test suites. - `@suaveplan/crypto-vault` — no action needed (uses `EventBus` directly, doesn't touch changed surface) - `@suaveplan/network` — no action needed (uses `EventBus` + `BoundedQueue`, unchanged) - `@suaveplan/storage` — no action needed - `@suaveplan/packer` — no action needed - `@suaveplan/fsm` — no action needed - `@suaveplan/retry` — no action needed - `@suaveplan/migration` — no action needed (type-only import) - `@suaveplan/config` — no action needed - `@suaveplan/events-schema` — no action needed (type-only import) - `@suaveplan/events-metrics` — no action needed (type-only import) - `@suaveplan/events-otel` — no action needed (type-only import) - `@suaveplan/events-transport` — no action needed (type-only import) --- ## Migration No migration needed — purely additive.