33 Commits

Author SHA1 Message Date
chahinebrini
353c139796 feat: review-gate (task review/reopen) + autonomous role guides
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>
2026-06-27 16:48:42 +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
9f3dc28030 fix(cli): memory add no longer prompts when --category is supplied (non-interactive agents)
Local-mode branch of 'memory add' omitted category when calling memoryAdd, so it always fell through to an interactive select() prompt — which throws in non-TTY agent contexts and breaks the reporting loop. Forward category; add tests for the non-interactive flag path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:59:37 +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
074b75f909 feat(cli): add agenthub update self-updater + non-blocking update hint
agenthub update: fetch + reset install to origin/<branch> + reinstall + rebuild, so users never touch git or pnpm. Robust to a dirty working tree (the 'commit before pull' wall) by resetting to remote; guards unpushed local commits and refuses to discard them. Adds a daily, non-blocking update hint on startup (detached background fetch + instant local comparison, like gh/npm/brew) that never auto-applies. Tests for the non-git-install path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 22:24:53 +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
c073f9a213 fix(network-mode): wrap remote calls for errors, skip Content-Type on empty body, use program CLI in E2E 2026-06-25 13:21:10 +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
fb3da93f59 feat(cli): add RemoteClient for network mode 2026-06-25 12:32:11 +02:00
chahinebrini
e69e81135a feat(services): add memory service and refactor CLI 2026-06-25 12:23:45 +02:00
chahinebrini
fff8a61ad9 feat(services): add decision service and refactor CLI 2026-06-25 12:23:23 +02:00
chahinebrini
6c8ee37a08 feat(services): add handoff service and refactor CLI 2026-06-25 12:23:02 +02:00
chahinebrini
4a8f5cbb8e feat(services): add task service module 2026-06-25 12:18:49 +02:00
chahinebrini
37ddaae043 fix(cli): handle missing status, clean imports, record delegated agent 2026-06-24 23:57:22 +02:00
chahinebrini
1197d85fdc test(e2e): add basic integration test 2026-06-24 23:47:12 +02:00
chahinebrini
be9161d7d1 feat(cli): add task create/list/show/claim/done commands 2026-06-24 23:40:23 +02:00
chahinebrini
cd6add215d feat(cli): add init command with agent instruction generation 2026-06-24 23:39:19 +02:00
chahinebrini
830e7af0c7 feat(templates): add agent instruction templates 2026-06-24 23:37:54 +02:00
chahinebrini
421420040a feat(status): add status aggregation and latest.md generation 2026-06-24 23:36:58 +02:00
chahinebrini
2b9e409b8b feat(index): add sqlite index with fts5 search 2026-06-24 23:35:53 +02:00
chahinebrini
c5af4c7b6a feat(config): add config read/write and defaults 2026-06-24 23:33:27 +02:00
chahinebrini
57bb572bf5 feat(files): add markdown entity read/write 2026-06-24 23:32:14 +02:00
chahinebrini
dd27e8caba feat(counter): add sequential id generator 2026-06-24 23:31:14 +02:00
chahinebrini
b3dea07352 feat(paths): add agenthub path helpers 2026-06-24 23:30:15 +02:00
chahinebrini
2b5696de82 fix(schema): enforce 4-digit ids 2026-06-24 23:29:32 +02:00
chahinebrini
c00ec16c84 feat(schema): add zod schemas for all entities 2026-06-24 23:27:59 +02:00