# Tasks: enterprise-browser-web-workers **Change ID**: enterprise-browser-web-workers **Package**: `@suaveplan/web-workers` **Target path**: `browser/platform/web-workers` **Prerequisite packages on Verdaccio**: `@suaveplan/events`, `@suaveplan/error`, `@suaveplan/logger` --- ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] Create directory tree per `proposal.md`. - [ ] `package.json` v0.0.0, `"sideEffects": false`. - `dependencies`: `@suaveplan/events workspace:^`, `@suaveplan/error workspace:^`, `@suaveplan/types workspace:^`, `@suaveplan/logger workspace:^`, `@suaveplan/schema-registry workspace:^`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`, `tslib catalog:build` - `devDependencies`: `vitest catalog:testing`, `@vitest/coverage-istanbul catalog:testing`, `happy-dom catalog:testing`, `@suaveplan/testing workspace:^` - Subpath exports: `"."`, `"./worker-manager"`, `"./shared-worker-manager"`, `"./worker-pool"`, `"./message-bus"`, `"./helpers/vite-worker"` - [ ] `tsconfig.json`, `vitest.config.ts` (pool: forks, happy-dom environment). --- ## 2. Error codes - [ ] `WORKER_NOT_FOUND`, `WORKER_QUEUE_FULL`, `WORKER_REQUEST_TIMEOUT`, `WORKER_CIRCUIT_OPEN`. - [ ] `registerWebWorkerErrorCodes()` — call eagerly. --- ## 3. Types (`src/types/web-workers.types.ts`) - [ ] `WorkerConfig`, `WorkerStatus`, `WorkerFactory`, `WorkerLike`, `WorkerMessage`, `WorkerPoolConfig`, `WorkerTask`, `PoolMetrics`, `MessageBusEventMap`, `WorkerManagerEventMap`, `RequestOptions`, `SharedWorkerFactory`. - [ ] Write `web-workers.types.md`. --- ## 4. `BaseWorkerManager` (`src/core/base-manager/`) - [ ] `base-manager.ts` — shared correlation-ID map, timeout logic, event emission, `AbortSignal` wiring. - [ ] `WorkerManager` and `SharedWorkerManager` both extend this. - [ ] Write `base-manager.md`. --- ## 5. Circuit breaker (`src/worker-manager/circuit-breaker/`) - [ ] `circuit-breaker.ts` — state machine (closed → open → half-open); injectable clock; `record(success)`, `isOpen()`, `reset()`. - [ ] Write `circuit-breaker.test.ts` (open on N failures, half-open after cooldown, reset on success). Write `circuit-breaker.md`. --- ## 6. `WorkerManager` (`src/worker-manager/worker-manager/`) - [ ] `worker-manager.ts` — extends `BaseWorkerManager`; `create`, `postMessage` (with transfer list), `sendRequest` (with `AbortSignal` + backpressure ceiling), `terminate`, `terminateAll`, `has`, `getStatus`, `getWorkerNames`, `onError`. - [ ] Wire circuit breaker and OTel metrics. - [ ] Wire `@suaveplan/events` runtime emission. - [ ] Write `worker-manager.test.ts` (create, postMessage, sendRequest, abort, backpressure, circuit open). Write `worker-manager.md`. --- ## 7. `SharedWorkerManager` (`src/shared-worker-manager/shared-worker-manager/`) - [ ] `shared-worker-manager.ts` — `new SharedWorker(url)`; one `MessagePort` per named connection; `connect`, `disconnect`, `sendRequest` (AbortSignal). - [ ] Write `shared-worker-manager.test.ts` (connect, message, disconnect). Write `shared-worker-manager.md`. --- ## 8. `WorkerPool` (`src/worker-pool/worker-pool/`) - [ ] `worker-pool.ts` — FIFO task queue, round-robin dispatch, `minIdle`/`maxIdle`, health checks, per-task timeout, drain. - [ ] `getMetrics()` returning `PoolMetrics` (size, idle, pending, completed, failed). - [ ] Write `worker-pool.test.ts` (submit, saturation, backpressure, drain, health-check eviction). Write `worker-pool.md`. --- ## 9. `MessageBus` (`src/message-bus/message-bus/`) - [ ] `message-bus.ts` — topic pub/sub, `subscribeOnce`, `broadcast`, `request` (AbortSignal), `registerHandler`, subscriber count, topic enumeration. - [ ] Wire `@suaveplan/events` runtime emission via `MessageBusEventMap`. - [ ] Write `message-bus.test.ts` (subscribe, publish, request/response, abort, broadcast). Write `message-bus.md`. --- ## 10. Streaming RPC (`src/streaming/stream/`) - [ ] `stream.ts` — `sendStream(manager, name, type, payload): AsyncIterable` using correlation IDs and `MessagePort` transfer. - [ ] Write `stream.test.ts`. Write `stream.md`. --- ## 11. Vite worker helper (`src/helpers/vite-worker/`) - [ ] `vite-worker.ts` — `defineWorker(url, options?)` using `new URL(url, import.meta.url)`; exports factory and type. - [ ] Write `vite-worker.test.ts`. Write `vite-worker.md`. --- ## 12. Integration test (`tests/integration.test.ts`) - [ ] `WorkerManager` + `MessageBus` together: publish from worker, subscribe in main. - [ ] `WorkerPool` saturation test with 10 concurrent tasks and `maxIdle: 3`. - [ ] `AbortSignal` cancels in-flight `sendRequest`. - [ ] Transfer `ArrayBuffer` via transfer list (verify zero-copy). --- ## 13. Docs + verify - [ ] Write `.md` per module (≥200 words, API reference, examples). - [ ] Write `README.md` with subpath table, pool guide, streaming RPC example, circuit-breaker reference. - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/web-workers` — green. - [ ] `bunx turbo test:coverage` — 100%. - [ ] No `@ts-expect-error` in `src/` or tests. No `vi.stubGlobal`. - [ ] `SharedWorkerManager` and `WorkerPool` fully implemented (no stubs). - [ ] `bun scripts/publish.ts --package @suaveplan/web-workers`. - [ ] Archive to `openspec/archive/2026-04-24-enterprise-browser-web-workers/`.