Drei vom Architekten abgenommene Tasks, gebündelt als Checkpoint:
- TSK-0242: Agent-Alias-Mapping (kimi-ah → kimi kanonisiert, Rollen → preferredAgent),
reopenTask räumt claimedBy ab, fsWatch reindiziert direkte Datei-Edits,
work-Default 300s → 50s, task_list mit Limit.
- TSK-0245: zwei Agent-Klassen (dispatch loop|architect). Watchdog mahnt
architekt-getriebene Agenten nur noch EINMAL statt im Minutentakt;
`task dispatch` startet sie explizit, `task record` trägt extern
erledigte Arbeit mit origin=external nach.
- TSK-0249: Lifecycle wird serverseitig erzwungen (open→review scheitert mit
klarer Meldung), claimedBy/doneBy überleben bis done, Presence pro Agent,
Review-Watchdog, GET /architect/pulse (1.4 kB statt 34 kB, since-Cursor,
omitted statt stillem Abschneiden), unbekannter Agent → 400 statt 500.
Alle Punkte live am laufenden Hub nachgemessen, nicht aus Agenten-Logs übernommen.
Tests: 242 → 279 grün, tsc sauber.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closes the architect-side gap: the auto-claim daemon wakes implementers on
new tasks, but the architect had no signal when an implementer submitted.
`agenthub watch --await-review` exits (after printing) the moment a task
enters `review` — including any task already in review on connect (initial
check) — so the architect can run it in the background and be re-invoked by
the harness the instant a submission needs a verdict.
- watch.ts: awaitReview option, initial fetchReviewTasks() check + SSE exit
on task→review.
- index.ts: --await-review flag.
- tests: returns immediately on already-pending review; exits on a review
transition while watching. 121/121 green.
Bump 0.4.0 -> 0.5.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The status snapshot (.agenthub/status/latest.md) was only refreshed on an
explicit `status --update`, so it drifted stale and misled agents that
follow golden rule #2 ("read status/latest.md") — e.g. an implementer
seeing an old task list and picking the wrong task.
- src/server/statusRefresh.ts: subscribe to the event bus and regenerate
the snapshot on every task/handoff/decision/memory change (REST and
filesystem-watch paths), debounced 300 ms. Presence ('agent') events
are skipped; the snapshot lives outside the watched dirs so it can't
feed back into the watcher.
- wired into startServer lifecycle (start + stop on close).
- test: status/latest.md reflects a new task shortly after POST /tasks.
117/117 green.
Bump 0.3.0 -> 0.3.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the architect-controlled workflow: implementers submit work
for review, only the architect closes tasks.
- CLI: `agenthub task review <id>` (implementer submits → status review)
and `agenthub task reopen <id>` (architect re-triggers → status open).
Server already supported both statuses; now exposed on local + --server
paths, with remoteClient.reviewTask/reopenTask.
- templates: AGENTS.md + role guides rewritten so agents self-drive the
CLI on open (hello → claim → implement → task review → wait), with the
hard rule that ONLY the architect runs `task done`. Implementer guides
(codex/kimi) never call done; architect guide documents done/reopen.
- tests: review/reopen SSE events + formatEvent "Task review"/"Task
reopened" lines. 113/113 green.
Bump 0.2.0 -> 0.2.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Agents now connect to the hub with no manual env/flag, and announce
themselves on join — restoring the agreed onboarding flow.
Auto-connect (resolveContext):
- An initialized project WITHOUT a configured serverUrl now falls
through to LAN auto-discovery (previously it went straight to local
mode, so agents in an initialized repo never found the server). The
discovered URL is persisted to the project config, so the next
command is instant.
- IP-change self-heal: when a configured server is unreachable,
runRemote re-discovers the live server and updates the config so the
next command reconnects automatically.
Presence (join-announce):
- POST /announce broadcasts an ephemeral 'agent/joined' event (not
written to disk). New `agenthub hello --agent <name> --role <role>`
posts it; watchers print "AgentHub: <agent> joined (<role>)".
- AgentHubEvent extended with type 'agent' + actions 'joined'/'left';
formatEvent renders presence lines; remoteClient.announce() added.
Tests: formatEvent agent lines + /announce SSE e2e. 109/109 green.
Bump 0.1.2 -> 0.2.0 (CLI --version too).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every user-facing line — the watch stream and each command's success
line, on both the local and --server (remote) paths — now carries an
"AgentHub:" prefix so it's recognizable in any agent's console
(Claude / Codex / Kimi), independent of the board.
- watch: formatEvent rewritten to verb-based, branded lines
("AgentHub: Task received <id> <title> [status]",
"AgentHub: Task done <id> by <agent>", "AgentHub: Handoff …"),
plus an "AgentHub: connected" line on stream start.
- task/handoff/decision/memory/delegate/init + server-listening lines
branded on the local command path.
- cli/index.ts: same branding on the --server remote path (the path
agents actually hit), so CLI line and SSE stream now match.
- tests: formatEvent assertions updated to the branded format
(regex-tolerant of column padding). 106/106 green.
codex + kimi stay implementers by convention (role=implementer +
assignedTo) — no schema change. Bump 0.1.1 -> 0.1.2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>