diff --git a/README.md b/README.md index 40ad90ff..d771585a 100644 --- a/README.md +++ b/README.md @@ -170,27 +170,31 @@ For feature architecture and implementation guidance: ## Comparison -| Feature | Agent Teams | Vibe Kanban | Aperant | Cursor | Claude Code CLI | +| Feature | Agent Teams | Gastown | Paperclip | Cursor | Claude Code CLI | |---|---|---|---|---|---| -| **Cross-team communication** | ✅ | ❌ | ❌ | — | ❌ | -| **Agent-to-agent messaging** | ✅ Native real-time mailbox | ❌ Agents are independent | ❌ Fixed pipeline | ❌ | ✅⚠️ Built-in (no UI) | -| **Linked tasks** | ✅ Cross-references in messages | ⚠️ Subtasks only | ❌ | ❌ | ❌ | -| **Session analysis** | ✅ 6-category token tracking | ❌ | ⚠️ Execution logs | ❌ | ❌ | -| **Task attachments** | ✅ Auto-attach, agents read & attach files | ❌ | ✅ Images + files | ⚠️ Chat session only | ❌ | -| **Hunk-level review** | ✅ Accept / reject individual hunks | ❌ | ❌ | ✅ | ❌ | -| **Built-in code editor** | ✅ With Git support | ❌ | ❌ | ✅ Full IDE | ❌ | -| **Full autonomy** | ✅ Agents create, assign, review tasks end-to-end | ❌ Human manages tasks | ❌ Fixed pipeline | ⚠️ Isolated tasks only | ✅⚠️ (no UI) | -| **Task dependencies (blocked by)** | ✅ Guaranteed ordering | ❌ | ⚠️ Within plan only | ❌ | ✅⚠️ (no UI, no notifications) | -| **Review workflow** | ✅ Agents review each other | ❌ | ⚠️ Auto QA pipeline | ❌ | ✅⚠️ (no UI) | -| **Zero setup** | ✅ | ❌ Config required | ❌ Config required | ✅ | ⚠️ CLI install required | -| **Kanban board** | ✅ 5 columns, real-time | ✅ | ✅ 6 columns (pipeline) | ❌ | ❌ | -| **Execution log viewer** | ✅ Tool calls, reasoning, timeline | ❌ | ✅ Phase-based logs | ✅ | ❌ | -| **Live processes** | ✅ View, stop, open URLs in browser | ❌ | ❌ | ✅ | ❌ | -| **Per-task code review** | ✅ Accept / reject / comment | ⚠️ PR-level only | ⚠️ File-level only | ✅ BugBot on PRs | ❌ | -| **Flexible autonomy** | ✅ Granular settings, per-action approval, notifications | ❌ | ⚠️ Plan approval only | ✅ | ✅ | -| **Git worktree isolation** | ✅ Optional | ⚠️ Mandatory | ⚠️ Mandatory | ✅ | ✅ | -| **Multi-agent backend** | ✅ Codex, Claude, and 75+ providers | ✅ 6+ agents | ✅ 11 providers | ✅ Multi-model | — | -| **Price** | **Free** | Free / $30 user/mo | Free | $0–$200/mo | Provider subscription | +| **Cross-team communication** | ✅ Native cross-team messages | ⚠️ Cross-rig coordination | ⚠️ Company-scoped org work | N/A | ❌ | +| **Agent-to-agent messaging** | ✅ Native real-time mailbox | ✅ Mailboxes + handoffs | ⚠️ Comments + @mentions | ❌ | ✅ Team mailbox, no UI | +| **Linked tasks** | ✅ Cross-refs + dependencies | ⚠️ Beads deps + convoys | ✅ Goals, parents, blockers | ❌ | ✅ Shared task list | +| **Session analysis** | ✅ Task logs + token tracking | ⚠️ Session recall, feed, OTEL | ⚠️ Run transcripts + cost audit | ❌ | ⚠️ Usage command, no UI | +| **Task attachments** | ✅ Auto-attach, agents read & attach files | ❌ Not task-level | ✅ Docs, attachments, work products | ⚠️ Chat session only | ⚠️ Chat images only | +| **Hunk-level review** | ✅ Accept / reject individual hunks | ❌ | ❌ Bring your own review | ✅ | ❌ | +| **Built-in code editor** | ✅ With Git support | ❌ | ❌ Control plane, not editor | ✅ Full IDE | ❌ | +| **Full autonomy** | ✅ Agents create, assign, review tasks end-to-end | ✅ Mayor, convoys, recovery | ✅ Heartbeats + governance | ⚠️ Background agents, not teams | ✅ Experimental CLI teams | +| **Task dependencies (blocked by)** | ✅ Guaranteed ordering | ✅ DAG waves via Beads | ✅ Blockers + execution locks | ❌ | ✅ Team task deps, no UI | +| **Review workflow** | ✅ Agents review each other + human review UI | ⚠️ Refinery merge queue | ✅ Approvals + governance | ⚠️ PR/BugBot only | ✅ Team review, no UI | +| **Zero setup** | ✅ Guided runtime setup | ❌ Go/Git/Dolt/Beads/tmux | ⚠️ `npx` + embedded Postgres | ✅ | ⚠️ CLI + env flag | +| **Kanban board** | ✅ 5 columns, real-time | ❌ Dashboard, not Kanban | ✅ 7 columns, drag-and-drop | ❌ | ❌ | +| **Execution log viewer** | ✅ Tool calls, reasoning, timeline | ⚠️ Feed, OTEL, dashboard | ✅ Run transcripts + ledger | ⚠️ Agent chat + terminal | ❌ | +| **Live processes** | ✅ View, stop, open URLs in browser | ⚠️ Agent health dashboard | ⚠️ Manual services + previews | ⚠️ Native terminal only | ❌ | +| **Per-task code review** | ✅ Accept / reject / comment | ⚠️ Merge queue, no diff UI | ⚠️ PR/work products, no inline diff | ✅ BugBot on PRs | ❌ | +| **Flexible autonomy** | ✅ Per-action approvals + notifications | ✅ Gates, escalation, recovery | ✅ Board approvals, pause, terminate | ⚠️ BG agents auto-run commands | ✅ Permissions + hooks | +| **Git worktree isolation** | ✅ Optional | ✅ Core primitive | ✅ Worktrees / branches | ⚠️ Background branches/VMs | ⚠️ Manual worktrees | +| **Multi-agent backend** | ✅ Claude, Codex + OpenCode teammates | ✅ Claude, Codex, Gemini, Copilot + more | ✅ BYO agents: Claude, Codex, Cursor/OpenCode, HTTP | ⚠️ Multi-model agents, no team backend | ⚠️ Claude-only experimental teams | +| **Org chart / governance** | ⚠️ Roles + approvals, no org chart | ⚠️ Roles + escalation | ✅ Org chart + board governance | ⚠️ Team admin only | ❌ | +| **Budget controls** | ⚠️ Cost/token visibility, no hard caps | ⚠️ Cost tiers + digest, no hard caps | ✅ Per-agent budgets + hard stops | ⚠️ Usage + BG spend limits | ⚠️ `/cost` + workspace limits | +| **Price** | **Free OSS UI**, provider access needed | Free OSS, runtime plans needed | Free OSS, self-hosted + infra | Free + paid usage | Claude plan or API usage | + +Fact sources checked on May 5, 2026: [detailed research notes](docs/research/gastown-paperclip-comparison-2026-05-05.md), [Gastown README](https://github.com/gastownhall/gastown), [Gastown provider guide](https://github.com/gastownhall/gastown/blob/main/docs/agent-provider-integration.md), [Gastown scheduler](https://github.com/gastownhall/gastown/blob/main/docs/design/scheduler.md), [Paperclip README](https://github.com/paperclipai/paperclip), [Paperclip adapters](https://github.com/paperclipai/paperclip/blob/master/docs/adapters/overview.md), [Paperclip budgets](https://github.com/paperclipai/paperclip/blob/master/docs/guides/board-operator/costs-and-budgets.md), [Paperclip runtime services](https://github.com/paperclipai/paperclip/blob/master/docs/guides/board-operator/execution-workspaces-and-runtime-services.md), [Paperclip Kanban source](https://github.com/paperclipai/paperclip/blob/master/ui/src/components/KanbanBoard.tsx), [Cursor Background Agents](https://docs.cursor.com/en/background-agents), [Cursor Diffs & Review](https://docs.cursor.com/en/agent/review), [Cursor Bugbot](https://docs.cursor.com/en/bugbot), [Cursor pricing](https://docs.cursor.com/en/account/usage), [Claude Code agent teams](https://code.claude.com/docs/en/agent-teams), [Claude Code subagents](https://code.claude.com/docs/en/sub-agents), [Claude Code workflows](https://code.claude.com/docs/en/common-workflows), [Claude Code costs](https://code.claude.com/docs/en/costs), [Claude pricing](https://claude.com/pricing). --- diff --git a/docs/research/gastown-paperclip-comparison-2026-05-05.md b/docs/research/gastown-paperclip-comparison-2026-05-05.md new file mode 100644 index 00000000..1570e5a3 --- /dev/null +++ b/docs/research/gastown-paperclip-comparison-2026-05-05.md @@ -0,0 +1,162 @@ +# Gastown и Paperclip comparison для лендинга и README + +> Дата проверки: 2026-05-05 +> Цель: публичная таблица `Agent Teams | Gastown | Paperclip | Cursor | Claude Code CLI` без угадываний по конкурентам. +> Метод: первичные источники, `gh repo view`, official README/docs/releases, локальные клоны `gastownhall/gastown` и `paperclipai/paperclip`. + +## Snapshot + +| Проект | Позиционирование | Статус на 2026-05-05 | Лицензия | +|---|---|---:|---| +| **Gastown** | multi-agent workspace manager для coding agents | `14,962★`, latest `v1.0.1` от `2026-04-25`, push `2026-05-03` | MIT | +| **Paperclip** | control plane для autonomous AI companies | `62,668★`, latest `v2026.428.0` от `2026-04-28`, push `2026-05-05` | MIT | + +## Что важно для публичного сравнения + +### Gastown + +Сильные факты: + +- README позиционирует Gastown как workspace manager для Claude Code, GitHub Copilot, Codex, Gemini и других AI agents. +- Есть built-in mailboxes, identities, handoffs, Beads ledger, git-backed hooks, convoys, Witness/Deacon watchdog, Refinery merge queue. +- Dependencies сильнее, чем просто "convoys": convoy stage/launch строит DAG, считает waves, запускает Wave 1, а последующие waves daemon dispatches автоматически. +- Есть `gt feed`, web dashboard, OpenTelemetry events/metrics, `gt costs record`, cost tier presets, daily cost digest и context-budget guard. +- Agent provider story шире README: provider guide прямо перечисляет Claude, Gemini, Codex, Cursor, AMP, OpenCode, Copilot и loose-coupled tmux integration tiers. +- Scheduler сильнее простого queue: `scheduler.max_polecats` включает deferred dispatch, capacity governor, pause/resume, queued sling context beads и daemon dispatch cycle. + +Ограничения: + +- Это не Kanban product: README описывает dashboard как обзор agents, convoys, hooks, queues, issues, escalations. +- Нет явного built-in editor, hunk-level review или task attachment workflow как продуктовой возможности. +- Бюджеты не равны Paperclip budgets: у Gastown есть cost tiers/logging/guards, но я не нашёл hard monthly caps с automatic pause/cancel. + +Публичная оценка: + +- `Task dependencies` - `✅ Beads DAG waves` +- `Kanban board` - `❌ Dashboard, not Kanban` +- `Per-task code review` - `⚠️ Merge queue, no diff UI` +- `Budget controls` - `⚠️ Cost tiers + digest, no hard caps` + +### Paperclip + +Сильные факты: + +- README: Node.js server + React UI that orchestrates a team of AI agents. Works with OpenClaw, Claude Code, Codex, Cursor, Bash, HTTP. +- README прямо заявляет org charts, budgets, governance, goal alignment, agent coordination. +- README under the hood: issues have company/project/goal/parent links, atomic checkout, execution locks, blocker dependencies, comments, documents, attachments, work products. +- Budget section: scoped budget policies with warning thresholds and hard stops, overspend pauses agents and cancels queued work automatically. +- `ui/src/components/KanbanBoard.tsx` содержит `backlog`, `todo`, `in_progress`, `in_review`, `blocked`, `done`, `cancelled` и drag-and-drop через `@dnd-kit`. +- `packages/shared/src/validators/work-product.ts` содержит work products: `preview_url`, `runtime_service`, `pull_request`, `branch`, `commit`, `artifact`, `document`; statuses include `ready_for_review`, `approved`, `changes_requested`, `merged`. +- Architecture docs: built-in stable adapters listed as Claude Local, Codex Local, Process, HTTP; adapter overview also lists OpenCode, Cursor, OpenClaw Gateway, Pi, Hermes and experimental Gemini. +- Execution policy docs: runtime enforces comment-required, review and approval stages; decisions are audited; reviewers/approvers can be agents or users. +- Workspace/runtime docs: services and jobs are manually controlled from UI, execution workspaces isolate checkout/branch/runtime state, and services are not auto-started by issue execution. +- Issue API docs: @mentions in comments trigger heartbeats and issue-thread interactions can request confirmations, ask questions, or suggest tasks through UI cards. + +Ограничения: + +- README явно говорит: Paperclip is not a code review tool. It orchestrates work, not pull requests. +- Нет hunk-level accept/reject UI и нет built-in code editor уровня нашего workbench. +- Это broader company/org control plane, а не coding cockpit. +- Work products are real in code, but public roadmap still has "Artifacts & Work Products" as future work, so public `Per-task code review` should stay `⚠️`, not `✅`. + +Публичная оценка: + +- `Kanban board` - `✅ 7 columns, drag-and-drop` +- `Per-task code review` - `⚠️ PR/work products, no inline diff` +- `Hunk-level review` - `❌ Bring your own review` +- `Budget controls` - `✅ Per-agent budgets + hard stops` + +## Маркетинговая позиция + +Честный framing для нас: + +- Против Gastown продаём не "мы мощнее как orchestration OS", а **coding-team workbench**: review, logs, editor, live processes, attachments, operator UX. +- Против Paperclip продаём не "у нас больше governance", а **agentic IDE / coding cockpit**: hunk-level review, task-scoped developer logs, built-in editor, live process controls. +- `Multi-agent backend` у нас больше не надо показывать как "In development": публично корректнее писать `Claude, Codex + OpenCode teammates`. + +## Второй глубокий проход + +Что поменял после повторной проверки: + +- Убрал Gemini из нашей публичной строки. Теперь у нас: `Claude, Codex + OpenCode teammates`. +- Paperclip `Agent-to-agent messaging` точнее как `Comments + @mentions`, а не как полноценный mailbox. @mentions будят агентов, но это не прямой peer mailbox как у нас или Gastown. +- Paperclip `Execution log viewer` усилил до `Run transcripts + ledger`: в UI есть `RunTranscriptView` и `IssueRunLedger`, а architecture docs описывают capture stdout, cost/session state и run records. +- Paperclip `Live processes` уточнил до `Manual services + previews`: runtime services/jobs есть в UI, но docs прямо говорят, что issue execution не стартует и не стопает их автоматически. +- Gastown `Session analysis` уточнил до `Session recall, feed, OTEL`: это сильная ops/observability модель, но не наш task-scoped analysis cockpit. +- Gastown `Budget controls` уточнил до `Cost tiers + digest, no hard caps`: есть model tiering, `gt costs record`, daily digest bead, но не нашёл Paperclip-style hard budget pause. + +Вывод не поменялся: публично выгоднее и честнее продавать наш **coding workbench** - hunk review, task logs, editor, live processes, attachments, team UI. Не надо притворяться, что мы глубже Gastown как orchestration OS или глубже Paperclip как governance/budget company control plane. + +## Третий глубокий проход по тексту таблицы + +Что уточнил после проверки README/docs/source: + +- Paperclip `Cross-team communication` заменил на `Company-scoped org work`: README говорит про multi-company isolation и org charts, но не про свободную коммуникацию между независимыми компаниями. +- Paperclip `Agent-to-agent messaging` заменил на `Comments + @mentions`: docs называют comments primary channel, а @mentions будят агента через heartbeat. Это не peer mailbox. +- Gastown `Linked tasks` заменил на `Beads deps + convoys`: source сильнее, чем просто "convoys", потому что stage/launch строит DAG по dependency edges. +- Gastown `Session analysis` заменил на `Session recall, feed, OTEL`: публично понятнее, чем термин `Seance`, но всё ещё отражает session discovery, TUI feed и OpenTelemetry. +- Gastown `Full autonomy` заменил на `Mayor, convoys, recovery`: не спорим с их глубокой autonomy моделью, но не перегружаем публичную таблицу внутренними health терминами. +- Paperclip `Zero setup` заменил на `npx + embedded Postgres`: quickstart реально идёт через `npx paperclipai onboard --yes`, и docs говорят, что embedded PostgreSQL создаётся автоматически. +- Paperclip `Price` уточнил до `OSS, self-hosted + infra`: честнее, потому что Paperclip account не нужен, но self-hosting и agent/provider runtime costs всё равно остаются. + +## Четвёртый глубокий проход: Claude Code CLI и Cursor + +Что поменял после проверки официальных docs Cursor и Claude Code: + +- Claude Code CLI нельзя честно держать как слабый baseline: официальные `agent teams` уже дают direct teammate messaging, shared task list, mailbox, task dependencies, team review scenarios и hooks for quality gates. Поэтому я поднял Claude CLI в строках `Agent-to-agent messaging`, `Linked tasks`, `Full autonomy`, `Task dependencies`, `Review workflow`. +- Но Claude Code agent teams всё ещё experimental, disabled by default, требуют `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`, работают в CLI/terminal display modes и имеют known limitations. Поэтому наш selling point против Claude CLI - не "у них нет teams", а **у них нет полноценного product UI/cockpit**: kanban, task attachments, hunk review UI, task logs, live process section, cross-team UI, cost/context dashboard. +- Claude Code `Multi-agent backend` теперь точнее как `Claude-only experimental teams`, а не просто `Claude-only teams`. +- Claude Code `Git worktree isolation` точнее как `Manual worktrees`: official workflows рекомендуют git worktree для параллельных sessions, но это не автоматическая продуктовая isolation как у нас/Gastown/Paperclip. +- Cursor `Full autonomy` точнее как `Background agents, not teams`: background agents сильные, но это не team backend with shared task list/mailbox. +- Cursor `Execution log viewer` и `Live processes` понижены до `⚠️`: есть agent chat/terminal/background terminals, но нет task-scoped execution timeline и process URL section как у нас. +- Cursor `Flexible autonomy` понижен до `⚠️`: official background-agent security docs прямо говорят, что background agents auto-run terminal commands, в отличие от foreground approvals. +- Cursor `Git worktree isolation` понижен до `⚠️ Background branches/VMs`: docs говорят про isolated remote machines and separate branches, не про встроенный local worktree strategy. +- Cursor `Price` заменил с `$0-$200/mo` на `Free + paid usage`, потому что pricing/usage docs теперь акцентируют included API usage, usage dashboard, Bugbot pricing и background-agent spend limits. + +Итоговая позиция после четвёртого прохода: + +- Против Claude Code CLI мы не врём, что у него нет multi-agent primitives. У него они есть, но experimental and CLI-first. Мы продаём **операторский UI и review/workbench layer**. +- Против Cursor мы не врём, что у него нет background agents или review. У него есть сильный IDE/PR story. Мы продаём **team/task orchestration, task-scoped logs, cross-agent workflow and review cockpit**. + +## Scores + +| Критерий | Agent Teams | Gastown | Paperclip | +|---|---:|---:|---:| +| Coding cockpit | **9.2** | 5.6 | 6.8 | +| Orchestration depth | 7.6 | **9.2** | 8.8 | +| Governance / budget control | 6.7 | 6.0 | **9.4** | +| Review UX | **9.3** | 5.8 | 6.2 | +| Setup simplicity | **8.4** | 4.7 | 7.1 | + +Вывод по 10-балльной уверенности: + +- Agent Teams против Gastown: 🎯 9 🛡️ 8 🧠 5 - сравнение честное, потому что мы отдаём Gastown orchestration depth, но забираем workbench. +- Agent Teams против Paperclip: 🎯 9 🛡️ 8 🧠 6 - сравнение честное, потому что Paperclip сильнее в budgets/governance, но слабее как code-review/editor cockpit. +- Agent Teams против Cursor: 🎯 9 🛡️ 9 🧠 5 - сравнение честное, потому что Cursor сильнее как IDE, но не как multi-agent team/task OS. +- Agent Teams против Claude Code CLI: 🎯 9 🛡️ 9 🧠 6 - сравнение честное только после повышения Claude CLI по official agent teams primitives; наш выигрыш теперь UI/workbench, не наличие базовой team механики. +- Публичная таблица после Claude/Cursor прохода: 🎯 9 🛡️ 9 🧠 5 - около 55 строк изменения в README/landing плюс локали. + +## Источники + +- Gastown repo: +- Gastown v1.0.1: +- Gastown convoy implementation: +- Gastown convoy skill docs: +- Gastown provider guide: +- Gastown scheduler docs: +- Paperclip repo: +- Paperclip v2026.428.0: +- Paperclip Kanban source: +- Paperclip work products source: +- Paperclip architecture docs: +- Paperclip execution policy docs: +- Paperclip costs and budgets docs: +- Paperclip runtime services docs: +- Cursor Background Agents: +- Cursor Diffs & Review: +- Cursor Bugbot: +- Cursor usage/pricing: +- Claude Code agent teams: +- Claude Code subagents: +- Claude Code common workflows: +- Claude Code costs: diff --git a/docs/research/real-competitors-comparison.md b/docs/research/real-competitors-comparison.md index b966a535..26121cae 100644 --- a/docs/research/real-competitors-comparison.md +++ b/docs/research/real-competitors-comparison.md @@ -1,5 +1,7 @@ # Реальные конкуренты для Comparison в README +> ⚠️ Update 2026-05-05: публичная таблица README/landing теперь сравнивает нас с `Gastown` и `Paperclip`, а не с `Claude Code Agent Teams` и `GoClaw`. Актуальная research-опора: [gastown-paperclip-comparison-2026-05-05.md](gastown-paperclip-comparison-2026-05-05.md). Ниже оставлен старый broader draft как исторический контекст. + > Дата проверки: 2026-04-13 > Статус: внутренний comparison draft > Цель: заменить в нашем внутреннем thinking `Vibe Kanban` и `Aperant` на реальные ориентиры - `Gastown`, `Claude Code Agent Teams`, `GoClaw` @@ -55,7 +57,7 @@ | **Per-task code review** | ✅ Per-task diff review with accept / reject / comment flow | ❌ | ❌ | ⚠️ Task approval exists, but not inline code diff review | | **Flexible autonomy** | ✅ Granular approvals, notifications, autonomy controls | ✅ Strong human gates, escalation and intervention, mostly via CLI/TUI | ⚠️ Plan approval, hooks and permissions exist, but control plane is thin | ✅ Team settings, approval workflows, exec approval, task approval | | **Git worktree isolation** | ✅ Optional per-agent worktree strategy | ✅ Core architectural primitive | ⚠️ Manual worktrees exist in Claude Code, but not as the native team model | ❌ Not a core team isolation model | -| **Multi-agent backend** | ⚠️ Claude is mature; Codex/Gemini plumbing exists in code but is still emerging as product surface | ✅ Claude Code, Codex, Gemini, Copilot and other runtimes | ❌ Claude-first only, models per teammate but no real multi-provider backend | ✅ 20+ providers including Claude CLI and ChatGPT OAuth | +| **Multi-agent backend** | ⚠️ Claude is mature; Codex/OpenCode plumbing exists in code but is still emerging as product surface | ✅ Claude Code, Codex, Gemini, Copilot and other runtimes | ❌ Claude-first only, models per teammate but no real multi-provider backend | ✅ 20+ providers including Claude CLI and ChatGPT OAuth | | **Price** | Free OSS UI, but a Claude Code plan is still needed today | Free OSS, but you still pay for the underlying runtime plans/seats you use | Claude subscription | Free self-hosted OSS, but infra + provider/API/subscription costs remain | ## Самые важные выводы по matrix @@ -435,7 +437,7 @@ GoClaw выигрывает у нас по: ## Места, где надо быть особенно честными про нас -- `Multi-agent backend` у нас пока не так зрел, как это можно прочитать из одной строки README. В коде есть мосты и статусы для `Anthropic`, `Codex`, `Gemini`, но продуктово основной путь всё ещё Claude-first. +- `Multi-agent backend` у нас пока не так зрел, как это можно прочитать из одной строки README. В коде есть мосты и статусы для `Anthropic`, `Codex`, `OpenCode`, но продуктово основной путь всё ещё Claude-first. - `Zero setup` у нас честно сильный именно для Claude Code path. - `Cross-team communication` у нас сильнее, чем у этих конкурентов, но cross-team attachments не выглядят как полностью общий happy path. diff --git a/landing/components/sections/ComparisonSection.vue b/landing/components/sections/ComparisonSection.vue index c9c1ce6a..9c22083e 100644 --- a/landing/components/sections/ComparisonSection.vue +++ b/landing/components/sections/ComparisonSection.vue @@ -10,8 +10,8 @@ interface CellValue { interface ComparisonRow { feature: string us: CellValue - vibeKanban: CellValue - aperant: CellValue + gastown: CellValue + paperclip: CellValue cursor: CellValue claudeCli: CellValue } @@ -20,161 +20,177 @@ const rows = computed(() => [ { feature: t('comparison.features.crossTeam'), us: { status: 'yes' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'no' }, + gastown: { status: 'partial', note: 'Cross-rig coordination' }, + paperclip: { status: 'partial', note: 'Company-scoped org work' }, cursor: { status: 'na' }, claudeCli: { status: 'no' }, }, { feature: t('comparison.features.agentMessaging'), us: { status: 'yes', note: 'Native real-time mailbox' }, - vibeKanban: { status: 'no', note: 'Agents are independent' }, - aperant: { status: 'no', note: 'Fixed pipeline' }, + gastown: { status: 'yes', note: 'Mailboxes + handoffs' }, + paperclip: { status: 'partial', note: 'Comments + @mentions' }, cursor: { status: 'no' }, - claudeCli: { status: 'partial', note: 'Built-in (no UI)' }, + claudeCli: { status: 'yes', note: 'Team mailbox, no UI' }, }, { feature: t('comparison.features.linkedTasks'), - us: { status: 'yes', note: 'Cross-references in messages' }, - vibeKanban: { status: 'partial', note: 'Subtasks only' }, - aperant: { status: 'no' }, + us: { status: 'yes', note: 'Cross-refs + dependencies' }, + gastown: { status: 'partial', note: 'Beads deps + convoys' }, + paperclip: { status: 'yes', note: 'Goals, parents, blockers' }, cursor: { status: 'no' }, - claudeCli: { status: 'no' }, + claudeCli: { status: 'yes', note: 'Shared task list' }, }, { feature: t('comparison.features.sessionAnalysis'), - us: { status: 'yes', note: '6-category token tracking' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'partial', note: 'Execution logs' }, + us: { status: 'yes', note: 'Task logs + token tracking' }, + gastown: { status: 'partial', note: 'Session recall, feed, OTEL' }, + paperclip: { status: 'partial', note: 'Run transcripts + cost audit' }, cursor: { status: 'no' }, - claudeCli: { status: 'no' }, + claudeCli: { status: 'partial', note: 'Usage command, no UI' }, }, { feature: t('comparison.features.taskAttachments'), us: { status: 'yes', note: 'Auto-attach, agents read & attach' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'yes', note: 'Images + files' }, + gastown: { status: 'no', note: 'Not task-level' }, + paperclip: { status: 'yes', note: 'Docs, attachments, work products' }, cursor: { status: 'partial', note: 'Chat session only' }, - claudeCli: { status: 'no' }, + claudeCli: { status: 'partial', note: 'Chat images only' }, }, { feature: t('comparison.features.hunkReview'), us: { status: 'yes', note: 'Accept / reject individual hunks' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'no' }, + gastown: { status: 'no' }, + paperclip: { status: 'no', note: 'Bring your own review' }, cursor: { status: 'yes' }, claudeCli: { status: 'no' }, }, { feature: t('comparison.features.codeEditor'), us: { status: 'yes', note: 'With Git support' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'no' }, + gastown: { status: 'no' }, + paperclip: { status: 'no', note: 'Control plane, not editor' }, cursor: { status: 'yes', note: 'Full IDE' }, claudeCli: { status: 'no' }, }, { feature: t('comparison.features.fullAutonomy'), us: { status: 'yes', note: 'Create, assign, review end-to-end' }, - vibeKanban: { status: 'no', note: 'Human manages tasks' }, - aperant: { status: 'no', note: 'Fixed pipeline' }, - cursor: { status: 'partial', note: 'Isolated tasks only' }, - claudeCli: { status: 'partial', note: 'No UI' }, + gastown: { status: 'yes', note: 'Mayor, convoys, recovery' }, + paperclip: { status: 'yes', note: 'Heartbeats + governance' }, + cursor: { status: 'partial', note: 'Background agents, not teams' }, + claudeCli: { status: 'yes', note: 'Experimental CLI teams' }, }, { feature: t('comparison.features.taskDeps'), us: { status: 'yes', note: 'Guaranteed ordering' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'partial', note: 'Within plan only' }, + gastown: { status: 'yes', note: 'DAG waves via Beads' }, + paperclip: { status: 'yes', note: 'Blockers + execution locks' }, cursor: { status: 'no' }, - claudeCli: { status: 'partial', note: 'No UI, no notifications' }, + claudeCli: { status: 'yes', note: 'Team task deps, no UI' }, }, { feature: t('comparison.features.reviewWorkflow'), us: { status: 'yes', note: 'Agents review each other' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'partial', note: 'Auto QA pipeline' }, - cursor: { status: 'no' }, - claudeCli: { status: 'partial', note: 'No UI' }, + gastown: { status: 'partial', note: 'Refinery merge queue' }, + paperclip: { status: 'yes', note: 'Approvals + governance' }, + cursor: { status: 'partial', note: 'PR/BugBot only' }, + claudeCli: { status: 'yes', note: 'Team review, no UI' }, }, { feature: t('comparison.features.zeroSetup'), - us: { status: 'yes' }, - vibeKanban: { status: 'no', note: 'Config required' }, - aperant: { status: 'no', note: 'Config required' }, + us: { status: 'yes', note: 'Guided runtime setup' }, + gastown: { status: 'no', note: 'Go/Git/Dolt/Beads/tmux' }, + paperclip: { status: 'partial', note: 'npx + embedded Postgres' }, cursor: { status: 'yes' }, - claudeCli: { status: 'partial', note: 'CLI install required' }, + claudeCli: { status: 'partial', note: 'CLI + env flag' }, }, { feature: t('comparison.features.kanban'), us: { status: 'yes', note: '5 columns, real-time' }, - vibeKanban: { status: 'yes' }, - aperant: { status: 'yes', note: '6 columns (pipeline)' }, + gastown: { status: 'no', note: 'Dashboard, not Kanban' }, + paperclip: { status: 'yes', note: '7 columns, drag-and-drop' }, cursor: { status: 'no' }, claudeCli: { status: 'no' }, }, { feature: t('comparison.features.execLog'), us: { status: 'yes', note: 'Tool calls, reasoning, timeline' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'yes', note: 'Phase-based logs' }, - cursor: { status: 'yes' }, + gastown: { status: 'partial', note: 'Feed, OTEL, dashboard' }, + paperclip: { status: 'yes', note: 'Run transcripts + ledger' }, + cursor: { status: 'partial', note: 'Agent chat + terminal' }, claudeCli: { status: 'no' }, }, { feature: t('comparison.features.liveProcesses'), us: { status: 'yes', note: 'View, stop, open URLs' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'no' }, - cursor: { status: 'yes' }, + gastown: { status: 'partial', note: 'Agent health dashboard' }, + paperclip: { status: 'partial', note: 'Manual services + previews' }, + cursor: { status: 'partial', note: 'Native terminal only' }, claudeCli: { status: 'no' }, }, { feature: t('comparison.features.perTaskReview'), us: { status: 'yes', note: 'Accept / reject / comment' }, - vibeKanban: { status: 'partial', note: 'PR-level only' }, - aperant: { status: 'partial', note: 'File-level only' }, + gastown: { status: 'partial', note: 'Merge queue, no diff UI' }, + paperclip: { status: 'partial', note: 'PR/work products, no diff UI' }, cursor: { status: 'yes', note: 'BugBot on PRs' }, claudeCli: { status: 'no' }, }, { feature: t('comparison.features.flexAutonomy'), - us: { status: 'yes', note: 'Granular settings, notifications' }, - vibeKanban: { status: 'no' }, - aperant: { status: 'partial', note: 'Plan approval only' }, - cursor: { status: 'yes' }, - claudeCli: { status: 'yes' }, + us: { status: 'yes', note: 'Per-action approvals + notifications' }, + gastown: { status: 'yes', note: 'Gates, escalation, recovery' }, + paperclip: { status: 'yes', note: 'Board approvals, pause, terminate' }, + cursor: { status: 'partial', note: 'BG agents auto-run commands' }, + claudeCli: { status: 'yes', note: 'Permissions + hooks' }, }, { feature: t('comparison.features.worktree'), us: { status: 'yes', note: 'Optional' }, - vibeKanban: { status: 'partial', note: 'Mandatory' }, - aperant: { status: 'partial', note: 'Mandatory' }, - cursor: { status: 'yes' }, - claudeCli: { status: 'yes' }, + gastown: { status: 'yes', note: 'Core primitive' }, + paperclip: { status: 'yes', note: 'Worktrees / branches' }, + cursor: { status: 'partial', note: 'Background branches/VMs' }, + claudeCli: { status: 'partial', note: 'Manual worktrees' }, }, { feature: t('comparison.features.multiAgent'), - us: { status: 'soon', note: 'In development', noteLink: 'https://github.com/Alishahryar1/free-claude-code' }, - vibeKanban: { status: 'yes', note: '6+ agents' }, - aperant: { status: 'yes', note: '11 providers' }, - cursor: { status: 'yes', note: 'Multi-model' }, - claudeCli: { status: 'na' }, + us: { status: 'yes', note: 'Claude, Codex + OpenCode teammates' }, + gastown: { status: 'yes', note: 'Claude, Codex, Gemini, Copilot + more' }, + paperclip: { status: 'yes', note: 'BYO agents: Claude, Codex, Cursor/OpenCode, HTTP' }, + cursor: { status: 'partial', note: 'Multi-model agents, no team backend' }, + claudeCli: { status: 'partial', note: 'Claude-only experimental teams' }, + }, + { + feature: t('comparison.features.orgGovernance'), + us: { status: 'partial', note: 'Roles + approvals, no org chart' }, + gastown: { status: 'partial', note: 'Roles + escalation' }, + paperclip: { status: 'yes', note: 'Org chart + board governance' }, + cursor: { status: 'partial', note: 'Team admin only' }, + claudeCli: { status: 'no' }, + }, + { + feature: t('comparison.features.budgetControls'), + us: { status: 'partial', note: 'Cost/token visibility, no hard caps' }, + gastown: { status: 'partial', note: 'Cost tiers + digest, no hard caps' }, + paperclip: { status: 'yes', note: 'Per-agent budgets + hard stops' }, + cursor: { status: 'partial', note: 'Usage + BG spend limits' }, + claudeCli: { status: 'partial', note: '/cost + workspace limits' }, }, { feature: t('comparison.features.price'), - us: { status: 'free' }, - vibeKanban: { status: 'text', note: 'Free / $30/mo' }, - aperant: { status: 'free' }, - cursor: { status: 'text', note: '$0–$200/mo' }, - claudeCli: { status: 'text', note: 'Claude subscription' }, + us: { status: 'free', note: 'OSS, provider access needed' }, + gastown: { status: 'free', note: 'OSS, runtime plans needed' }, + paperclip: { status: 'free', note: 'OSS, self-hosted + infra' }, + cursor: { status: 'text', note: 'Free + paid usage' }, + claudeCli: { status: 'text', note: 'Claude plan or API usage' }, }, ]) const competitors = [ { key: 'us', name: 'Agent Teams', highlight: true }, - { key: 'vibeKanban', name: 'Vibe Kanban' }, - { key: 'aperant', name: 'Aperant' }, + { key: 'gastown', name: 'Gastown' }, + { key: 'paperclip', name: 'Paperclip' }, { key: 'cursor', name: 'Cursor' }, { key: 'claudeCli', name: 'Claude Code CLI' }, ] @@ -197,7 +213,7 @@ function getStatusIcon(status: string): string { case 'yes': return '\u2713' case 'no': return '\u2717' case 'partial': return '\u25D2' - case 'na': return '\u2014' + case 'na': return 'N/A' case 'free': return 'Free' case 'soon': return '\uD83D\uDCC5' default: return '' diff --git a/landing/locales/ar.json b/landing/locales/ar.json index 316ffad0..295142a1 100644 --- a/landing/locales/ar.json +++ b/landing/locales/ar.json @@ -83,6 +83,8 @@ "flexAutonomy": "استقلالية مرنة", "worktree": "عزل Git worktree", "multiAgent": "خلفية متعددة الوكلاء", + "orgGovernance": "الهيكل التنظيمي / الحوكمة", + "budgetControls": "ضوابط الميزانية", "price": "السعر" } }, diff --git a/landing/locales/de.json b/landing/locales/de.json index 7373d66b..76257315 100644 --- a/landing/locales/de.json +++ b/landing/locales/de.json @@ -83,6 +83,8 @@ "flexAutonomy": "Flexible Autonomie", "worktree": "Git-Worktree-Isolation", "multiAgent": "Multi-Agenten-Backend", + "orgGovernance": "Organigramm / Governance", + "budgetControls": "Budgetkontrollen", "price": "Preis" } }, diff --git a/landing/locales/en.json b/landing/locales/en.json index dc79746f..da3c26cb 100644 --- a/landing/locales/en.json +++ b/landing/locales/en.json @@ -83,6 +83,8 @@ "flexAutonomy": "Flexible autonomy", "worktree": "Git worktree isolation", "multiAgent": "Multi-agent backend", + "orgGovernance": "Org chart / governance", + "budgetControls": "Budget controls", "price": "Price" } }, diff --git a/landing/locales/es.json b/landing/locales/es.json index f911ff4f..5cb5c78d 100644 --- a/landing/locales/es.json +++ b/landing/locales/es.json @@ -83,6 +83,8 @@ "flexAutonomy": "Autonomía flexible", "worktree": "Aislamiento Git worktree", "multiAgent": "Backend multi-agente", + "orgGovernance": "Organigrama / gobernanza", + "budgetControls": "Controles de presupuesto", "price": "Precio" } }, diff --git a/landing/locales/fr.json b/landing/locales/fr.json index 0af848a1..3566ed88 100644 --- a/landing/locales/fr.json +++ b/landing/locales/fr.json @@ -83,6 +83,8 @@ "flexAutonomy": "Autonomie flexible", "worktree": "Isolation Git worktree", "multiAgent": "Backend multi-agents", + "orgGovernance": "Organigramme / gouvernance", + "budgetControls": "Contrôle budgétaire", "price": "Prix" } }, diff --git a/landing/locales/hi.json b/landing/locales/hi.json index 4fb4ad8a..ff06e28a 100644 --- a/landing/locales/hi.json +++ b/landing/locales/hi.json @@ -83,6 +83,8 @@ "flexAutonomy": "लचीली स्वायत्तता", "worktree": "Git worktree आइसोलेशन", "multiAgent": "मल्टी-एजेंट बैकएंड", + "orgGovernance": "ऑर्ग चार्ट / गवर्नेंस", + "budgetControls": "बजट नियंत्रण", "price": "कीमत" } }, diff --git a/landing/locales/ja.json b/landing/locales/ja.json index efe26554..04b1c92c 100644 --- a/landing/locales/ja.json +++ b/landing/locales/ja.json @@ -83,6 +83,8 @@ "flexAutonomy": "柔軟な自律性", "worktree": "Git worktree分離", "multiAgent": "マルチエージェントバックエンド", + "orgGovernance": "組織図 / ガバナンス", + "budgetControls": "予算管理", "price": "価格" } }, diff --git a/landing/locales/pt.json b/landing/locales/pt.json index ba1c26ca..f13006b6 100644 --- a/landing/locales/pt.json +++ b/landing/locales/pt.json @@ -83,6 +83,8 @@ "flexAutonomy": "Autonomia flexível", "worktree": "Isolamento Git worktree", "multiAgent": "Backend multi-agente", + "orgGovernance": "Organograma / governança", + "budgetControls": "Controles de orçamento", "price": "Preço" } }, diff --git a/landing/locales/ru.json b/landing/locales/ru.json index f57612bf..bde5b30e 100644 --- a/landing/locales/ru.json +++ b/landing/locales/ru.json @@ -83,6 +83,8 @@ "flexAutonomy": "Гибкая автономность", "worktree": "Изоляция Git worktree", "multiAgent": "Мультиагентный бэкенд", + "orgGovernance": "Оргструктура / управление", + "budgetControls": "Бюджетные лимиты", "price": "Цена" } }, diff --git a/landing/locales/zh.json b/landing/locales/zh.json index bd56e97f..712972a3 100644 --- a/landing/locales/zh.json +++ b/landing/locales/zh.json @@ -83,6 +83,8 @@ "flexAutonomy": "灵活自主", "worktree": "Git worktree 隔离", "multiAgent": "多智能体后端", + "orgGovernance": "组织架构 / 治理", + "budgetControls": "预算控制", "price": "价格" } }, diff --git a/runtime.lock.json b/runtime.lock.json index 481af2ff..d7894dfa 100644 --- a/runtime.lock.json +++ b/runtime.lock.json @@ -1,27 +1,27 @@ { - "version": "0.0.17", - "sourceRef": "v0.0.17", + "version": "0.0.18", + "sourceRef": "v0.0.18", "sourceRepository": "777genius/agent_teams_orchestrator", "releaseRepository": "777genius/claude_agent_teams_ui", "releaseTag": "v1.2.0", "assets": { "darwin-arm64": { - "file": "agent-teams-runtime-darwin-arm64-v0.0.17.tar.gz", + "file": "agent-teams-runtime-darwin-arm64-v0.0.18.tar.gz", "archiveKind": "tar.gz", "binaryName": "claude-multimodel" }, "darwin-x64": { - "file": "agent-teams-runtime-darwin-x64-v0.0.17.tar.gz", + "file": "agent-teams-runtime-darwin-x64-v0.0.18.tar.gz", "archiveKind": "tar.gz", "binaryName": "claude-multimodel" }, "linux-x64": { - "file": "agent-teams-runtime-linux-x64-v0.0.17.tar.gz", + "file": "agent-teams-runtime-linux-x64-v0.0.18.tar.gz", "archiveKind": "tar.gz", "binaryName": "claude-multimodel" }, "win32-x64": { - "file": "agent-teams-runtime-win32-x64-v0.0.17.zip", + "file": "agent-teams-runtime-win32-x64-v0.0.18.zip", "archiveKind": "zip", "binaryName": "claude-multimodel.exe" } diff --git a/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts b/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts index 21d8d7c7..5cb1e78e 100644 --- a/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts +++ b/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts @@ -40,9 +40,11 @@ vi.mock('../../../../src/main/services/infrastructure/NotificationManager', () = }, })); +const allowConnectedClaudeAccount = + process.env.MEMBER_WORK_SYNC_CLAUDE_ALLOW_CONNECTED_ACCOUNT === '1'; const liveDescribe = process.env.MEMBER_WORK_SYNC_CLAUDE_STOP_HOOK_LIVE === '1' && - Boolean(process.env.ANTHROPIC_API_KEY?.trim()) + (hasLiveAnthropicApiKey() || allowConnectedClaudeAccount) ? describe : describe.skip; @@ -103,9 +105,7 @@ liveDescribe('Member work sync Claude Stop hook live e2e', () => { beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'member-work-sync-claude-stop-live-')); tempClaudeRoot = path.join(tempDir, '.claude'); - tempHome = path.join(tempDir, 'home'); await fs.mkdir(tempClaudeRoot, { recursive: true }); - await fs.mkdir(tempHome, { recursive: true }); setClaudeBasePathOverride(tempClaudeRoot); previousCliPath = process.env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH; @@ -117,6 +117,12 @@ liveDescribe('Member work sync Claude Stop hook live e2e', () => { previousHistFile = process.env.HISTFILE; previousUserProfile = process.env.USERPROFILE; + const shouldUseConnectedAccountHome = allowConnectedClaudeAccount && !hasLiveAnthropicApiKey(); + tempHome = shouldUseConnectedAccountHome + ? resolveConnectedClaudeHome(previousHome) + : path.join(tempDir, 'home'); + await fs.mkdir(tempHome, { recursive: true }); + process.env.HOME = tempHome; process.env.HISTFILE = '/dev/null'; process.env.USERPROFILE = tempHome; @@ -531,3 +537,19 @@ async function cleanupScopedClaudeStopHookLiveTempDirs(): Promise { } } } + +function hasLiveAnthropicApiKey(): boolean { + return Boolean(process.env.ANTHROPIC_API_KEY?.trim()); +} + +function resolveConnectedClaudeHome(previousHome: string | undefined): string { + const explicit = process.env.MEMBER_WORK_SYNC_CLAUDE_CONNECTED_HOME?.trim(); + if (explicit) { + return path.resolve(explicit); + } + const previous = previousHome?.trim(); + if (previous) { + return path.resolve(previous); + } + return os.userInfo().homedir; +} diff --git a/test/main/services/team/MemberWorkSyncCodex.live.test.ts b/test/main/services/team/MemberWorkSyncCodex.live.test.ts index 0681b51c..88f7ef26 100644 --- a/test/main/services/team/MemberWorkSyncCodex.live.test.ts +++ b/test/main/services/team/MemberWorkSyncCodex.live.test.ts @@ -56,6 +56,7 @@ liveDescribe('Member work sync Codex live e2e', () => { let previousCliFlavor: string | undefined; let previousControlUrl: string | undefined; let previousCodexHome: string | undefined; + let previousCodexIgnoreUserConfig: string | undefined; let codexHomeDir: string; let ownsCodexHomeDir: boolean; let codexAccountFeature: { @@ -100,6 +101,7 @@ liveDescribe('Member work sync Codex live e2e', () => { previousCliFlavor = process.env.CLAUDE_TEAM_CLI_FLAVOR; previousControlUrl = process.env.CLAUDE_TEAM_CONTROL_URL; previousCodexHome = process.env.CODEX_HOME; + previousCodexIgnoreUserConfig = process.env.CLAUDE_CODE_CODEX_NATIVE_IGNORE_USER_CONFIG; const shouldUseConnectedAccountHome = allowConnectedChatGptAccount && !hasLiveCodexApiKey(); if (shouldUseConnectedAccountHome) { @@ -117,6 +119,7 @@ liveDescribe('Member work sync Codex live e2e', () => { process.env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim() || DEFAULT_ORCHESTRATOR_CLI; process.env.CLAUDE_TEAM_CLI_FLAVOR = 'agent_teams_orchestrator'; process.env.CODEX_HOME = codexHomeDir; + process.env.CLAUDE_CODE_CODEX_NATIVE_IGNORE_USER_CONFIG = 'true'; codexAccountFeature = null; providerConnectionService = null; @@ -141,6 +144,7 @@ liveDescribe('Member work sync Codex live e2e', () => { restoreEnv('CLAUDE_TEAM_CLI_FLAVOR', previousCliFlavor); restoreEnv('CLAUDE_TEAM_CONTROL_URL', previousControlUrl); restoreEnv('CODEX_HOME', previousCodexHome); + restoreEnv('CLAUDE_CODE_CODEX_NATIVE_IGNORE_USER_CONFIG', previousCodexIgnoreUserConfig); setClaudeBasePathOverride(null); if (process.env.MEMBER_WORK_SYNC_CODEX_KEEP_TEMP === '1') { console.info(`[MemberWorkSyncCodex.live] preserved temp dir: ${tempDir}`); @@ -254,7 +258,7 @@ liveDescribe('Member work sync Codex live e2e', () => { prompt: [ 'Keep launch work minimal.', 'If you receive a task, follow task instructions exactly.', - 'Before going idle with unfinished assigned work, call member_work_sync_status and member_work_sync_report.', + 'Do not call member_work_sync_status until a task instruction or member_work_sync_nudge provides exact teamName, memberName, and controlUrl.', ].join(' '), members: [], }, @@ -292,19 +296,16 @@ liveDescribe('Member work sync Codex live e2e', () => { ].join('\n'), }); feature.noteTeamChange({ type: 'task', teamName, taskId: task.id }); + + const preRelayStatus = await feature.refreshStatus({ teamName, memberName }); + expect(preRelayStatus.memberName).toBe(memberName); + expect(preRelayStatus.providerId).toBe('codex'); + expect(preRelayStatus.agenda.items.some((item) => item.taskId === task.id)).toBe(true); + expect(preRelayStatus.shadow?.wouldNudge).toBe(true); + const relay = await activeService.relayInboxFileToLiveRecipient(teamName, memberName); expect(relay.relayed).toBeGreaterThan(0); - await waitUntil(async () => { - const status = await feature!.getStatus({ teamName: teamName!, memberName }); - return ( - status.memberName === memberName && - status.providerId === 'codex' && - status.agenda.items.some((item) => item.taskId === task.id) && - status.shadow?.wouldNudge === true - ); - }, 30_000); - await waitUntil(async () => { const fatalRuntimeMessage = await readFatalRuntimeMessage(teamName!); if (fatalRuntimeMessage) {