29 Commits

Author SHA1 Message Date
chahinebrini
49bc39d42d feat(team): Paperclip-style org chart with traveling-pulse connectors
Rebuild /team as a real org chart: architect at the root, workers below,
with an SVG connector layer whose edges carry a traveling green pulse
(getTotalLength + WAAPI stroke-dash motion) that flows from the architect
down each edge and lights up the node it reaches (onArrive → .arrive glow),
looping. Live busy state (SSE) keeps working agents lit blue; edges + nodes
re-layout on resize. Node cards restyled (icon box + name + role·model +
status). Kept data-agent / agent-card / claimed markers for the live sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 03:58:02 +02:00
chahinebrini
8dbbd0d10c fix(server): no-store Cache-Control on hub HTML pages
Browsers were caching /board and /team, so a stale page kept showing old
markup and didn't reflect live task/agent state (looked like the pre-redesign
team page + tasks appearing unclaimed though the server had them claimed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 03:37:25 +02:00
chahinebrini
7ca6c859f2 feat(board+team): interactive board, animated team tree, token budget, mDNS, realtime architect review + codex/kimi autostart
Board (/board):
- Drag an AGENT chip onto a task card to (re)assign it (realtime-notified).
- Drag a task card to a column to change status; open→in_progress auto-assigns
  from the title's "<agent>:" prefix — no manual agent picking.
- "+ New task" composer (agent dropdown removed; agent comes from the title).
- Live Cost & Budget panel.

Team (/team): live SSE sync of busy state + always-on ambient animation
(connector shimmer, idle glow) that brightens to a busy pulse when an agent
works. Org-chart hierarchy stays.

Token accounting: new budgetService/rosterService + GET /budget and /agents.
Real doneTokens + time-on-task estimate capped at 45 min/task (avoids the
wall-clock overcount that produced multi-million-token totals), blended
per-model EUR cost + optional budget bars. All estimates flagged "~".

Autostart: `agent setup` writes deterministic SessionStart hooks for Codex
(~/.codex/config.toml) and Kimi (~/.kimi-code/config.toml), not just Claude
Code. Verified: both auto-enter the agenthub_work loop.

Realtime architect review: agenthub_work is role-aware — architect/reviewer
blocks on SSE and wakes when a task hits review (no manual watcher re-arm).

mDNS: server advertises agenthub.local (bonjour-service) so the hub is
reachable in a browser on the LAN without an IP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 03:23:48 +02:00
chahinebrini
8b17baae96 fix(sse): /events keepalive heartbeat — keeps idle agenthub_work alive across short MCP client timeouts (TSK-0042)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 01:52:46 +02:00
chahinebrini
10f3184ea2 feat(board): task-detail transparency — activity log + decisions & reasoning + token/duration badges; cards stay slim (TSK-0041)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 01:52:32 +02:00
chahinebrini
caa009b66a feat(board): lean board + /activity page (TSK-0032 rework, realtime folded in)
codex reworked the board per the user's "keep it simple": /board now shows only
the compact KPI cards + the kanban (half-donut removed), with realtime SSE folded
in (TSK-0030). Recent Activity + Done Archive moved to a new /activity page; nav is
Board · Team · Activity · Decisions. team.ts / ui-shared.ts touched for nav + a
tier data-role hook. Tests green (133). The /team + /activity 500s seen on review
were a local better-sqlite3 ABI mismatch (native module rebuilt for Node 24), not a
code bug — all pages 200 after rebuild.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 05:43:25 +02:00
chahinebrini
844db1fd2b feat(board): dashboard — KPI cards + half-donut + activity + /decisions + /archive (TSK-0032)
codex built the dashboard redesign (TSK-0032): KPI metric cards, half-donut status
distribution, recent-activity feed, /decisions page, /archive page, task-detail
handoffs. Architect follow-up: the KPI cards were oversized (stretched to the side
panel height) — reworked to a compact full-width top row (auto-fit, fixed ~84px
height, label over value, small status-colored icon) per the user's reference.

Committed together to lock TSK-0032 in before TSK-0030 (realtime) touches the same files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 05:05:02 +02:00
chahinebrini
ed6c5b01d0 feat(messaging): read receipts + ack convention
Closes the fire-and-forget gap the user hit: the sender now sees when a message
is read. When markMessageRead fires, the read event carries the reader, and the
watch stream renders it as a receipt:

  AgentHub: ✓ Read         MSG-0002  read by windows-claude

Plus an ack convention in the implementer guide: when you act on a message-
request, send a brief "on it …" + a result message — so the sender sees progress,
not silence. (Board-side activity feed with messages is folded into TSK-0032.)

Bump 0.8.0 -> 0.8.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 04:04:04 +02:00
chahinebrini
07afa717ac feat(messaging): agent messaging — agenthub_message / agenthub_inbox (cross-agent via MCP)
Direct messages between agents through the hub — architect↔agent and agent↔agent
questions, clarifications and pings that handoffs/memories don't cover. Built as
MCP tools so kimi + codex get it too (not Claude-only), plus REST + CLI.

- Message entity (MSG-NNNN): schema, counter, messages/ dir, messageService
  (createMessage / listInbox / listMessages / markMessageRead).
- REST: POST /messages, GET /messages[?agent&unread], POST /messages/:id/read,
  with SSE emit. fsWatch + statusRefresh wired ('message' events; status skips them).
- MCP: agenthub_message {from,to,text,taskId?} + agenthub_inbox {agent,unreadOnly?}.
  agenthub_work now surfaces + drains unread messages and wakes on message events,
  so an agent sees messages inside its work loop. (18 tools total.)
- CLI: `agenthub message <to> <text> --from <agent>` + `agenthub inbox --agent`.
  watch stream shows "Message" events (architect-visible).
- Architect-visible by design: the hub stays the coordination point.

Bump 0.7.5 -> 0.8.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 03:20:38 +02:00
chahinebrini
4672677bf5 feat(team): roster-driven team page — provider grouping + brand logos (TSK-0028)
Architect implementation of the reopened TSK-0028 (option B). The team page now
reads config.agents (the roster) as the source of truth instead of inferring
role/identity from tasks:
- one fixed role per agent (fixes "codex in architect+implementer+tester")
- implementers grouped by provider with official Simple Icons brand logos
  (Anthropic / OpenAI / Moonshot) + the model behind each agent (Opus 4.8,
  Sonnet 4.6, GPT-5 Codex, Kimi K2)
- demo/throwaway agents gone (not in the roster)
- architect tier (claude) on top, implementer provider columns, tester tier
  (ahmed); free/busy + live timer from in-progress tasks
- ui-shared: providerLogo()/providerMeta() with verified brand SVG paths

Bump 0.7.4 -> 0.7.5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 02:24:00 +02:00
chahinebrini
96fdf0dbd4 Fix board card expansion layout 2026-06-29 01:31:45 +02:00
chahinebrini
15f139429e Polish AgentHub board UI 2026-06-29 00:55:55 +02:00
chahinebrini
986639a5f3 TSK-0028: AgentHub UI foundation + /team page
- Add src/server/ui-shared.ts: design tokens, agentAvatar(), statusPill(),
  escapeHtml(), liveTimerJs(), pageHeader(). No emojis, no deps.
- Add src/server/team.ts: role hierarchy renderer (architect -> implementer/
  reviewer/tester) with per-agent free/busy state derived from in-progress tasks.
- Wire GET /team route in src/server/routes.ts.
- Add tests/team.test.ts and tests/ui-shared.test.ts.

Build: npm run build clean. Tests: 132 passed (was 122).
2026-06-29 00:24:39 +02:00
chahinebrini
78bbebf435 feat(task): agenthub task assign — architect addresses an open task to an agent
Closes the addressing gap that left a waiting `agenthub work` blocked: the
remaining Win tasks were titled "Win L2: …" / unassigned, so they matched
no agent and the daemon waited forever.

`agenthub task assign <id> --agent <name>` sets assignedTo WITHOUT claiming
(status stays open) and fires task/updated — so an agent's blocked `work`
re-checks, matches via assignedTo, and auto-claims it. The architect can now
route a specific open task to a specific agent and have its daemon pick it up.

- taskService.assignTask; PATCH /tasks/:id handles assignedTo-without-status;
  remoteClient.assignTask; CLI `task assign`.
- test: assign keeps status open + sets assignedTo; start/work then claims it
  via the assignedTo match. 122/122 green.

Bump 0.5.0 -> 0.6.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 00:12:50 +02:00
chahinebrini
961675ac40 fix(server): auto-regenerate status snapshot on every change
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>
2026-06-27 17:27:19 +02:00
chahinebrini
45070222d0 feat: zero-config auto-connect + agent presence (join-announce)
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>
2026-06-27 16:33:03 +02:00
chahinebrini
ff79cbb639 feat(cli): brand all AgentHub console output with "AgentHub:" prefix
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>
2026-06-27 16:09:15 +02:00
chahinebrini
722388cb00 feat(server): emit SSE for CLI/file writes via filesystem watcher (TSK-0006)
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>
2026-06-27 15:43:33 +02:00
chahinebrini
9c749beacb feat(activity): per-task timeline endpoint, board expand, --task/--tokens/--duration/--by flags
GET /tasks/:id/activity returns a time-sorted ActivityItem[] assembled from existing data (task created, handoffs by taskId, memory by relatedTasks, current status). memory add + task done gain optional tokens/duration/by metadata surfaced in the timeline. Board cards expand inline to show the timeline. Index gains taskId + relatedTasks columns with migrations. 74 -> 97 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 14:49:47 +02:00
chahinebrini
4e5e5ae6bb feat(realtime): SSE event channel + agenthub watch (TSK-0006 part 1)
- 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>
2026-06-26 00:16:16 +02:00
chahinebrini
b405b268a5 feat(board): fix gaps A+B — full task status transitions + handoff who→whom
GAP A: extend PATCH /tasks/:id to support all five TaskStatus values
(open, in_progress, review, done, cancelled). Add reviewTask, cancelTask,
reopenTask helpers in taskService. Claim semantics preserved: in_progress
requires assignedTo. Board columns for review and cancelled now reachable
via the API.

GAP B: index fromRole/toRole/fromAgent/toAgent on handoff upsert. SQLite
migration guard adds columns to pre-existing DBs without data loss. Board
renderHandoffs shows "fromRole[@agent] → toRole[@agent]" via &rarr; arrow.
GET /handoffs now carries the routing fields in every index entry.

Tests: +14 (56 total, 21 files, all green). Covers every new status
transition, index field presence, board markup assertions, and a guard for
the claim-without-assignedTo 400.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 23:41:54 +02:00
chahinebrini
d0e45230bc feat(server): add static Trello-like task board at GET /board
Serves a single self-contained HTML page (inline CSS+JS, no build step,
no framework, no npm deps) that polls /tasks, /handoffs and /decisions on
the same origin and renders a column board by task status
(open/in_progress/review/done/cancelled). Each card shows id, title, role
and assignedTo; small handoffs + decisions panels below; auto-refresh
every 4s with a connection indicator. Purely additive and read-only — the
CLI core path is untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 23:35:28 +02:00
chahinebrini
79f5c8afde feat(cli): single-instance guard, ambient discovery, graceful errors, cwd-robust
Make the network MVP simple to operate: server start refuses a second instance on a port already serving AgentHub (single source of truth, prevents discovery split-brain); commands auto-discover a LAN server when run outside any project so the CLI works from any directory with zero config; walk up to the nearest .agenthub project (cwd-robust) and serve the project root; replace raw stack traces with actionable messages; add tests for findProjectRoot and the single-instance guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 22:15:14 +02:00
chahinebrini
9b8d587e9d feat(discovery): auto-discover LAN server during init; zero-config network mode 2026-06-25 13:46:39 +02:00
chahinebrini
efd0c7edfd test(e2e): add network mode end-to-end test; log actual server URL 2026-06-25 12:41:48 +02:00
chahinebrini
7eff25129f fix(server): 404/400 error handling and consistent delegate behavior; add server route tests 2026-06-25 12:40:11 +02:00
chahinebrini
b5e854fb10 feat(server): add full CRUD endpoints for network mode 2026-06-25 12:33:21 +02:00
chahinebrini
c2e3b0298e feat(server): support --host for LAN binding and export buildApp 2026-06-25 12:33:04 +02:00
chahinebrini
5adaaad216 feat(server): add optional fastify api 2026-06-24 23:45:20 +02:00