Closes the documented /events limitation: mutations made through the
local CLI (direct file + SQLite writes, no --server) bypassed the
in-process event bus and were invisible to SSE subscribers. A watcher
(e.g. a Windows client) was therefore NOT triggered when another agent
created a task via plain `agenthub task create`.
- src/server/fsWatch.ts: watch the entity dirs (tasks/handoffs/
decisions/memory); on any .md change, parse the entity and emit the
matching AgentHubEvent. Debounced per-file; self-creates dirs so it
attaches even before the first write.
- src/server/events.ts: shared dedup cache (signature = type🆔stamp)
+ emitChange() so the REST path and the watcher deliver each change
exactly once (no echo when REST writes the file the watcher sees).
- src/server/routes.ts: route emits go through emitChange(); update the
stale limitation comment.
- src/server/index.ts: start/stop the watcher with the server lifecycle.
- tests/sse.test.ts: CLI-write -> SSE, CLI-update -> SSE, and REST
dedup (exactly-once). 102/102 green.
Effect: a watcher is auto-triggered the instant any agent creates a
task, with or without --server. Bump 0.1.0 -> 0.1.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- src/server/events.ts: in-process EventEmitter bus (AgentHubEventBus);
singleton per server process, unlimited listeners for SSE fan-out.
- src/server/routes.ts: GET /events SSE endpoint — keepalive every 25 s,
optional ?role= server-side filter, reply.hijack() for clean streaming;
eventBus.publish() called on every successful mutating route (POST tasks/
handoffs/decisions/memory, PATCH tasks/:id).
- src/cli/commands/watch.ts: SSE client using Node fetch + ReadableStream
reader; exports parseSSEBuffer + formatEvent for testability; --once flag
exits 0 after first event (turn-based agent use case); --role for client-
side filtering (additive to server-side filter).
- src/cli/index.ts: register agenthub watch command via resolveContext.
- tests/sse.test.ts: 18 new tests (74 total, all green) — unit tests for
parseSSEBuffer + formatEvent, integration tests for eventBus on each
mutation type, E2E SSE stream + role-filter tests over real HTTP.
Limitation (documented): only REST mutations through the server emit events.
Local-CLI writes (direct file+SQLite) are invisible to subscribers — a
filesystem-watch increment is deferred to a later phase.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>