Plataforma de reunioes de trabalho por voz entre humanos (PO/dev) e subagents Claude reais com papeis (PO, Dev, QA). O Gemini Live API modera a conversa (STT+TTS bidirecional); quando precisa de analise especializada, delega via function call pra subagents Claude spawnados via CLI (usa sua subscription, sem API key). O mago-board (127.0.0.1:5008) e source-of-truth das tasks/sprints.
Clean Architecture + DDD + alchemy-first (@tecnomancy/alchemy Result/Option/pipe). 4 camadas:
presentation/ --> composition root + WS gateway + web UI (HTML+JS vanilla)
application/ --> use cases + ports (MeetingRepo, AgentBridge, VoiceSession, BoardGateway, EventBus)
domain/ --> Meeting aggregate, AgentPersona, errors (zero IO, tacit)
infrastructure/ --> adapters: Gemini Live, Claude CLI spawn, mago-board REST, in-memory repo/bus
modules/ --> bounded contexts (meetings, osint) plugaveis
Ver CONSTITUTION.md, ARCHITECTURE.md, docs/adrs/, docs/specs/.
Requer Bun >= 1.3.
bun install
cp .env.example .env
# preenche GEMINI_API_KEY (obrigatorio)
# demais envs tem default sensatobun run dev # --watch, TS direto
bun run typecheck # tsc --noEmit
bun test # unit + contract
bun run lint # eslint (rejeita try/catch fora de infra)
bun run build # bundle pra dist/
bun run start # roda o buildGET /— UI HTMLGET /health—{ok:true, tools:N}WS /ws/voice— protocolo JSON bidirecional (verdocs/specs/003-voice-gateway.spec.md)
query_sprint({project?, status?})— lista items do boardget_item_detail({issue_number})— detalhesupdate_item_status({issue_number, status})— move cardcreate_board_item({title, body?, size?, priority?, type?})— cria cardask_agent({role, question})— dispara subagent (po/dev/qa) viaclaudeCLI
run_scan, run_full_recon, get_job_status, list_recent_jobs, lookup_threat_intel, get_entity_info
mic -> WS -> VoiceGateway -> GeminiLiveSession
|
function_call: ask_agent(role, question)
|
application.dispatchToAgent
|
ClaudeCliAgentBridge (spawn claude -p)
|
subagent usa mago-board MCP tools
|
AgentResponse -> Gemini -> audio -> browser
| Var | Default | Descricao |
|---|---|---|
| GEMINI_API_KEY | obrigatorio | Gemini Live API key |
| MAGO_BOARD_URL | http://127.0.0.1:5008 | Board REST base |
| MAGO_API_URL | https://mago.team/mancer/api | OSINT mancer |
| MAGO_API_TOKEN | (opcional) | OSINT auth |
| CLAUDE_BIN | claude | path do CLI |
| CLAUDE_MODEL | sonnet | sonnet/opus/haiku |
| CLAUDE_TIMEOUT_MS | 60000 | timeout do dispatch |
| PORT | 5009 | HTTP+WS port |
| LOG_LEVEL | info | debug/info/warn/error |
src/
domain/ -- Meeting, Participant, Turn, AgendaItem, AgentPersona
application/ -- use cases + ports (interfaces)
infrastructure/ -- Gemini, Board, ClaudeCLI, repo, bus, WS gateway
modules/ -- meetings/, osint/ (bounded contexts)
presentation/ -- server.ts composition root + web/ static UI
shared/ -- alchemy, logger, config, ids
tests/
unit/ -- domain + application (pure)
contract/ -- adapters mocked
docs/
adrs/ -- ADR-000[1-5]
specs/ -- 001-003
bun test roda local sem tocar Gemini/Claude. Os adapters tem contract tests com fetch mock e spawn falso.
Pra smoke boot do servidor sem Gemini real:
GEMINI_API_KEY=fake PORT=5200 bun run dev
curl http://localhost:5200/health # {"ok":true,"tools":11}O handshake do WebSocket falha sem key real, mas a estrutura (HTML, health, fluxo de ports) sobe.