docs(plans): add Autensa benchmark tasks to automation foundation roadmap
Map reliability, operator UX, and spend-control follow-ons onto epics 1–9 so worker, webhooks, and fleet work have bead-scale task briefs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2f6adf4382
commit
35def387ae
20 changed files with 886 additions and 34 deletions
|
|
@ -7,7 +7,7 @@ status: done
|
||||||
priority: P1
|
priority: P1
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_epic_id: null
|
cursor_epic_id: null
|
||||||
updated_at: "2026-07-03"
|
updated_at: "2026-08-03"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Epic objective
|
# Epic objective
|
||||||
|
|
@ -55,6 +55,12 @@ Each job calls `resolveModel(workspace, roleId, convoy, brief)` and passes `Reso
|
||||||
- [x] [Task-shared-orchestrator-driver](./Task-shared-orchestrator-driver.md)
|
- [x] [Task-shared-orchestrator-driver](./Task-shared-orchestrator-driver.md)
|
||||||
- [x] [Task-apps-orchestrator-service](./Task-apps-orchestrator-service.md)
|
- [x] [Task-apps-orchestrator-service](./Task-apps-orchestrator-service.md)
|
||||||
|
|
||||||
|
## Follow-on tasks (Autensa benchmark)
|
||||||
|
|
||||||
|
| Task | Link |
|
||||||
|
|------|------|
|
||||||
|
| Agent health auto-nudge & zombie recovery | [Task-orchestrator-auto-nudge](./Task-orchestrator-auto-nudge.md) |
|
||||||
|
|
||||||
## Note
|
## Note
|
||||||
|
|
||||||
Supersedes [Epic-optional-orchestrator](../../Plan-agent-coordination/Epic-optional-orchestrator/Epic-optional-orchestrator.md) deferred stub with a concrete Echodo-native design.
|
Supersedes [Epic-optional-orchestrator](../../Plan-agent-coordination/Epic-optional-orchestrator/Epic-optional-orchestrator.md) deferred stub with a concrete Echodo-native design.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: orchestrator-auto-nudge
|
||||||
|
title: Orchestrator agent health — auto-nudge and zombie recovery
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: apps-orchestrator
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Extend stall detection beyond marking convoys `blocked`: detect zombie agent runs, optionally re-dispatch or nudge, and emit health events for mission control / fleet feed.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa agent health monitoring with auto-nudge and convoy health panel. Echodo already has `ORCHESTRATOR_STALL_MINUTES` and `detectStalledConvoys` — this task adds **recovery actions** and observability.
|
||||||
|
|
||||||
|
### Health states
|
||||||
|
|
||||||
|
| State | Trigger | Default action |
|
||||||
|
|-------|---------|----------------|
|
||||||
|
| **Stalled** | No heartbeat on open `agent_run` for N minutes | Mark convoy `blocked`; surface in gate inbox sidebar |
|
||||||
|
| **Zombie** | Run open but worker process gone | Re-enqueue job with `resume_from_checkpoint` when Epic 7 checkpoint task ships |
|
||||||
|
| **Nudge** | Soft stall (configurable) | Log `convoy_events` health event; optional Redis ping to worker |
|
||||||
|
|
||||||
|
### Config (env)
|
||||||
|
|
||||||
|
- `ORCHESTRATOR_NUDGE_MINUTES` (optional, < stall threshold)
|
||||||
|
- `ORCHESTRATOR_AUTO_REDISPATCH` (default false — opt-in for unattended dogfood)
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
Append `convoy_events` with `event_type: health` and metadata `{ reason, action, agent_run_id }` for activity feed (Epic 9).
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 6 orchestrator service (shipped)
|
||||||
|
- [Task-worker-checkpoint-resume](../Epic-apps-worker-v1/Task-worker-checkpoint-resume.md) for meaningful re-dispatch
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Extend `detectStalledConvoys` with nudge vs hard-stall tiers
|
||||||
|
- [ ] Optional re-dispatch path on zombie detection
|
||||||
|
- [ ] `convoy_events` health event writer
|
||||||
|
- [ ] Document in `docs/orchestrator.md`
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Stalled run moves convoy to `blocked` and writes health event
|
||||||
|
- [ ] With `ORCHESTRATOR_AUTO_REDISPATCH=1`, zombie run triggers new job enqueue
|
||||||
|
- [ ] No unbounded re-dispatch loops (max retries per brief configurable)
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-apps-orchestrator.md`
|
||||||
|
|
@ -7,7 +7,7 @@ status: in_progress
|
||||||
priority: P1
|
priority: P1
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_epic_id: null
|
cursor_epic_id: null
|
||||||
updated_at: "2026-07-03"
|
updated_at: "2026-08-03"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Epic objective
|
# Epic objective
|
||||||
|
|
@ -25,11 +25,13 @@ Role prompt = `.cursor/agents/role-*.md` + brief path. Model endpoint points at
|
||||||
- `WorkerSession` adapter interface (for future optional OpenHands plug-in).
|
- `WorkerSession` adapter interface (for future optional OpenHands plug-in).
|
||||||
- `pnpm lint && pnpm test` in allowlisted commands.
|
- `pnpm lint && pnpm test` in allowlisted commands.
|
||||||
- Branch + PR draft output (forge adapter from Epic 3).
|
- Branch + PR draft output (forge adapter from Epic 3).
|
||||||
|
- Checkpoint/resume and operator mid-build notes (Autensa benchmark — see tasks below).
|
||||||
|
|
||||||
**Out of scope**
|
**Out of scope**
|
||||||
|
|
||||||
- Browser automation, multi-agent delegation.
|
- Browser automation, multi-agent delegation.
|
||||||
- Feature parity with OpenHands.
|
- Feature parity with OpenHands.
|
||||||
|
- OpenClaw Gateway coupling.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
|
|
@ -43,7 +45,12 @@ Role prompt = `.cursor/agents/role-*.md` + brief path. Model endpoint points at
|
||||||
|
|
||||||
- [ ] One brief from `.convoys/` completes unattended on connected repo.
|
- [ ] One brief from `.convoys/` completes unattended on connected repo.
|
||||||
- [ ] `complete_task` includes model alias + token totals.
|
- [ ] `complete_task` includes model alias + token totals.
|
||||||
|
- [ ] Crashed worker can resume from checkpoint (follow-on task).
|
||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
_To be decomposed when epic graduates to `ready`._
|
| Task | Link | Status |
|
||||||
|
|------|------|--------|
|
||||||
|
| Minimal tool loop + worktree | [Task-worker-minimal-tool-loop](./Task-worker-minimal-tool-loop.md) | ready |
|
||||||
|
| Checkpoint & crash recovery | [Task-worker-checkpoint-resume](./Task-worker-checkpoint-resume.md) | draft |
|
||||||
|
| Operator notes mid-build | [Task-worker-operator-notes](./Task-worker-operator-notes.md) | draft |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: worker-checkpoint-resume
|
||||||
|
title: Worker checkpoint and crash recovery
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: apps-worker-v1
|
||||||
|
status: draft
|
||||||
|
priority: P1
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Persist worker session progress at configurable checkpoints so a crashed or stalled job resumes from the last checkpoint instead of restarting the brief from scratch.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** [Autensa mission-control](https://github.com/crshdn/mission-control) checkpoint & crash recovery — study their checkpoint restore API and per-task history UX; implement Echodo-native equivalents on Postgres.
|
||||||
|
|
||||||
|
### Schema
|
||||||
|
|
||||||
|
Add `worker_checkpoints` (or JSONB on `agent_runs`) workspace-scoped:
|
||||||
|
|
||||||
|
- `agent_run_id`, `convoy_id`, `brief_id`
|
||||||
|
- `checkpoint_seq`, `tool_history` (bounded), `files_touched`, `branch`, `worktree_path`
|
||||||
|
- `occurred_at`
|
||||||
|
|
||||||
|
### Worker behavior
|
||||||
|
|
||||||
|
- Save checkpoint after each tool round (configurable via `WORKER_CHECKPOINT_EVERY_N_STEPS`, default 1).
|
||||||
|
- On job start: if open run has latest checkpoint, resume tool loop from saved state.
|
||||||
|
- Orchestrator stall detector can trigger re-dispatch with `resume_from_checkpoint: true`.
|
||||||
|
|
||||||
|
### Operator surface (minimal v1)
|
||||||
|
|
||||||
|
- Mission control detail panel: checkpoint count + last checkpoint time (full history deferred).
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- [Task-worker-minimal-tool-loop](./Task-worker-minimal-tool-loop.md) (baseline loop must exist).
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Zod schemas in `packages/shared/worker`
|
||||||
|
- [ ] Drizzle migration + workspace-scoped queries
|
||||||
|
- [ ] Checkpoint write in `minimal-session` / `handle-job`
|
||||||
|
- [ ] Resume path on re-dispatch
|
||||||
|
- [ ] Env docs in `docs/worker.md`
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Kill worker mid-brief; re-dispatch resumes from last tool step without re-cloning
|
||||||
|
- [ ] Checkpoints filtered by `workspace_id`
|
||||||
|
- [ ] Checkpoint payload does not store API keys or full file contents (paths + hashes only)
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-apps-worker-v1.md`
|
||||||
|
- Blocks: reliable unattended dogfood for Epic 8
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: worker-minimal-tool-loop
|
||||||
|
title: apps/worker — minimal tool loop and worktree-per-brief
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: apps-worker-v1
|
||||||
|
status: ready
|
||||||
|
priority: P1
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
agent_prompt: |
|
||||||
|
Epic: apps/worker v1. Read docs/worker.md and docs/adr-model-routing.md.
|
||||||
|
Consume orchestrator jobs from Redis; resolve model via workspace registry.
|
||||||
|
claim_task / complete_task parity with MCP. Run pnpm lint && pnpm type-check
|
||||||
|
&& pnpm test before done.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Ship the baseline `apps/worker` consumer: dequeue `role_dispatch` jobs, run `WorkerSession` tool loop against a git worktree, and close with model + token metadata on `complete_task`.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Core v1 scope from [Epic-apps-worker-v1](./Epic-apps-worker-v1.md). Builds on existing package skeleton (`handle-job.ts`, `minimal-session.ts`, allowlisted tools, worktree helpers).
|
||||||
|
|
||||||
|
### Worker loop
|
||||||
|
|
||||||
|
- `BLPOP` on `echodo:orchestrator:jobs` (same key as orchestrator).
|
||||||
|
- Load brief path + role from job payload; resolve model via shared resolver.
|
||||||
|
- `claim_task` on matching backlog item; run `read_file` / `write_file` / `grep` / `run_command` (allowlist: `pnpm lint`, `pnpm type-check`, `pnpm test`, `git status`, `git diff`).
|
||||||
|
- `complete_task` with `modelAlias`, token totals, outcome.
|
||||||
|
|
||||||
|
### Git
|
||||||
|
|
||||||
|
- One worktree per brief under `WORKER_WORKTREE_BASE`.
|
||||||
|
- Branch naming convention documented for Epic 8 PR linking.
|
||||||
|
|
||||||
|
### PR output
|
||||||
|
|
||||||
|
- Open draft PR via forge adapter from connected repo (Epic 3).
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Wire live dequeue loop (non-dry-run) end-to-end
|
||||||
|
- [ ] Role prompt = `.cursor/agents/role-*.md` + brief markdown path
|
||||||
|
- [ ] Worktree create/teardown on success and failure
|
||||||
|
- [ ] Draft PR via forge adapter when implementer completes
|
||||||
|
- [ ] `docs/worker.md` matches shipped behavior
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
L
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] One implementer brief from `.convoys/` completes unattended on a connected repo
|
||||||
|
- [ ] `complete_task` includes model alias + token totals
|
||||||
|
- [ ] Failed runs tear down worktree and mark run `failed`
|
||||||
|
- [ ] `WORKER_DRY_RUN=1` still exits cleanly without Redis
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-apps-worker-v1.md`
|
||||||
|
- Plan: `../Plan-automation-foundation.md`
|
||||||
|
- Design reference: Autensa convoy build phase (concepts only — no OpenClaw dependency)
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: worker-operator-notes
|
||||||
|
title: Operator notes — mid-build context injection
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: apps-worker-v1
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Let operators send **queued notes** and **direct messages** to an active worker session without waiting for a human gate.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa Operator Chat — two delivery modes:
|
||||||
|
|
||||||
|
| Mode | Delivery | Use case |
|
||||||
|
|------|----------|----------|
|
||||||
|
| **Queued note** | Injected at next checkpoint / tool round | "Use the existing auth middleware" |
|
||||||
|
| **Direct message** | Prepended to very next model call | Urgent course correction |
|
||||||
|
|
||||||
|
Echodo scope is convoy-scoped (not per arbitrary task board). Gate co-pilot (Epic 5) stays gate-focused; this extends intervention to `in_progress` convoys.
|
||||||
|
|
||||||
|
### Data model
|
||||||
|
|
||||||
|
`convoy_operator_messages` table (workspace-scoped):
|
||||||
|
|
||||||
|
- `convoy_id`, `brief_id` (optional), `agent_run_id` (optional)
|
||||||
|
- `delivery`: `queued` | `direct`
|
||||||
|
- `body`, `author_user_id`, `delivered_at`, `created_at`
|
||||||
|
|
||||||
|
### APIs
|
||||||
|
|
||||||
|
- tRPC `convoys.postOperatorNote` (workspace member)
|
||||||
|
- Worker polls or receives note via job metadata on each tool round
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
- Mission control detail panel: chat thread when convoy status is `in_progress`
|
||||||
|
- Distinct from gate co-pilot (separate tab or section)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- [Task-worker-minimal-tool-loop](./Task-worker-minimal-tool-loop.md)
|
||||||
|
- Epic 5 mission control detail panel (extend, do not rewrite)
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Schema + tRPC mutations/list
|
||||||
|
- [ ] Worker consumes queued notes between tool steps
|
||||||
|
- [ ] Worker consumes direct messages before next `generateText`
|
||||||
|
- [ ] Mission control UI thread for `in_progress` convoys
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Operator posts queued note; worker sees it on next tool round
|
||||||
|
- [ ] Direct message arrives before next model call when run is active
|
||||||
|
- [ ] Messages are workspace-scoped and auditable in convoy detail
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-apps-worker-v1.md`
|
||||||
|
- Related: [Task-mission-control-ui](../Epic-mission-control-gates-ui/Task-mission-control-ui.md)
|
||||||
|
|
@ -7,7 +7,7 @@ status: done
|
||||||
priority: P1
|
priority: P1
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_epic_id: null
|
cursor_epic_id: null
|
||||||
updated_at: "2026-07-03"
|
updated_at: "2026-08-03"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Epic objective
|
# Epic objective
|
||||||
|
|
@ -49,3 +49,9 @@ See automation foundation discussion: Vercel/Coolify-style “show me your repo.
|
||||||
- [x] [Task-db-connected-repos-migration](./Task-db-connected-repos-migration.md)
|
- [x] [Task-db-connected-repos-migration](./Task-db-connected-repos-migration.md)
|
||||||
- [x] [Task-forge-adapters-trpc](./Task-forge-adapters-trpc.md)
|
- [x] [Task-forge-adapters-trpc](./Task-forge-adapters-trpc.md)
|
||||||
- [x] [Task-settings-connected-repos-ui](./Task-settings-connected-repos-ui.md)
|
- [x] [Task-settings-connected-repos-ui](./Task-settings-connected-repos-ui.md)
|
||||||
|
|
||||||
|
## Follow-on tasks (Autensa benchmark)
|
||||||
|
|
||||||
|
| Task | Link |
|
||||||
|
|------|------|
|
||||||
|
| Repo setup preflight tab | [Task-repo-setup-preflight](./Task-repo-setup-preflight.md) |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: repo-setup-preflight
|
||||||
|
title: Connected repo setup preflight — readiness before automation
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: connected-repos
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
**Repo Setup** tab on connected repos: verify a remote is automation-ready before orchestrator/worker dispatch (git access, default branch, CI permissions, required secrets).
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa v2.5.1 Repo Setup tab — preflight checks with in-UI fixes where the forge API allows. Echodo adapts this to multitenant `repo_links` and forge adapters (Forgejo + GitHub minimum).
|
||||||
|
|
||||||
|
### Preflight checks
|
||||||
|
|
||||||
|
| Check | Pass criteria |
|
||||||
|
|-------|---------------|
|
||||||
|
| Git clone | Shallow clone with stored credentials |
|
||||||
|
| Default branch | API-detected default matches stored value |
|
||||||
|
| Forge API | PR list/create permission |
|
||||||
|
| CI visibility | Latest workflow run status readable |
|
||||||
|
| Actions token (GitHub) | `contents` + `pull-requests` write if applicable |
|
||||||
|
| Required secrets | Names present (values never stored in Echodo DB) |
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
- Settings → Connected repos → per-repo **Setup** tab
|
||||||
|
- Traffic-light checklist with expandable failure reasons
|
||||||
|
- Block convoy **Go** when critical checks fail (soft warning vs hard block — configurable per workspace)
|
||||||
|
|
||||||
|
### Fixes (where API supports)
|
||||||
|
|
||||||
|
- GitHub: suggest/set workflow token permissions; link to docs for secret creation (do not write secret values through Echodo — operator pastes in forge UI)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 3 connected repos (shipped)
|
||||||
|
- Epic 6 orchestrator should read preflight status before enqueue
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] `repoPreflightStatus` zod schema in `packages/shared`
|
||||||
|
- [ ] Forge adapter methods: `getDefaultBranch`, `listWorkflowRuns`, `getRepoPermissions`
|
||||||
|
- [ ] tRPC `connectedRepos.runPreflight`
|
||||||
|
- [ ] Settings UI Setup tab
|
||||||
|
- [ ] Orchestrator skips dispatch when repo link `preflight_ok` is false
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
L
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Repo with wrong default branch shows failing check with detected branch name
|
||||||
|
- [ ] Private repo without token shows auth failure (no silent pass)
|
||||||
|
- [ ] Preflight re-runnable without reconnecting repo
|
||||||
|
- [ ] No forge secret values persisted in Postgres
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-connected-repos.md`
|
||||||
|
|
@ -7,14 +7,16 @@ status: draft
|
||||||
priority: P2
|
priority: P2
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_epic_id: null
|
cursor_epic_id: null
|
||||||
updated_at: "2026-07-03"
|
updated_at: "2026-08-03"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Epic objective
|
# Epic objective
|
||||||
|
|
||||||
Top-level **fleet** view: all `convoys-<repo>` workspaces (or connected repos) in one screen. Roll up convoys by status, gate inbox count, active `agent_runs`, recent spend by model alias.
|
Top-level **fleet** view: all `convoys-<repo>` workspaces (or connected repos) in one screen. Roll up convoys by status, gate inbox count, active `agent_runs`, recent spend by model alias.
|
||||||
|
|
||||||
Answers: “What needs me across all projects?”
|
Live **activity feed** (SSE) from `convoy_events` — Autensa benchmark for operator situational awareness.
|
||||||
|
|
||||||
|
Answers: “What needs me across all projects?” and “What just happened?”
|
||||||
|
|
||||||
## In scope / out of scope
|
## In scope / out of scope
|
||||||
|
|
||||||
|
|
@ -23,10 +25,12 @@ Answers: “What needs me across all projects?”
|
||||||
- Route `/fleet` or home dashboard for operator account.
|
- Route `/fleet` or home dashboard for operator account.
|
||||||
- Cross-workspace tRPC (membership-scoped).
|
- Cross-workspace tRPC (membership-scoped).
|
||||||
- Links into per-repo mission control (Epic 5).
|
- Links into per-repo mission control (Epic 5).
|
||||||
|
- SSE activity stream (workspace + fleet scope).
|
||||||
|
|
||||||
**Out of scope**
|
**Out of scope**
|
||||||
|
|
||||||
- Multi-tenant fleet across unrelated customers (operator's own repos only for v1).
|
- Multi-tenant fleet across unrelated customers (operator's own repos only for v1).
|
||||||
|
- Autopilot research/ideation feeds.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
|
|
@ -36,7 +40,11 @@ Answers: “What needs me across all projects?”
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Operator with two connected repos sees combined “3 awaiting approval” badge.
|
- [ ] Operator with two connected repos sees combined “3 awaiting approval” badge.
|
||||||
|
- [ ] New convoy event appears in activity feed without page refresh.
|
||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
_To be decomposed when epic graduates to `ready`._
|
| Task | Link | Status |
|
||||||
|
|------|------|--------|
|
||||||
|
| Fleet rollup dashboard | [Task-fleet-rollup-dashboard](./Task-fleet-rollup-dashboard.md) | ready |
|
||||||
|
| Live activity feed (SSE) | [Task-convoy-activity-feed-sse](./Task-convoy-activity-feed-sse.md) | draft |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: convoy-activity-feed-sse
|
||||||
|
title: Live convoy activity feed (SSE)
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: fleet-dashboard
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Real-time activity stream from `convoy_events` for mission control and fleet dashboard — research/build/gate/health events without full page refresh.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa live activity feed (SSE). Echodo already appends `convoy_events` for role completion, transitions, and (future) health events — this task exposes them as a **subscription surface**.
|
||||||
|
|
||||||
|
### Transport
|
||||||
|
|
||||||
|
- Prefer Next.js Route Handler `GET /api/convoys/activity/stream` with SSE (workspace-scoped via session)
|
||||||
|
- Alternative: tRPC subscription if infra already supports it — pick one, document in ADR addendum
|
||||||
|
|
||||||
|
### Event types surfaced
|
||||||
|
|
||||||
|
- `role_complete`, `transition`, `health`, `gate_action`
|
||||||
|
- Payload: `convoy_id`, `title`, `event_type`, `role`, `outcome`, `occurred_at`, `estimated_cost_usd` (when present)
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
- Mission control: collapsible **Activity** strip (last 20 events for current workspace)
|
||||||
|
- Fleet dashboard: global feed with product/repo filter
|
||||||
|
- Fallback: React Query poll every 30s when SSE unavailable
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 4 `convoy_events` (shipped)
|
||||||
|
- [Task-orchestrator-auto-nudge](../Epic-apps-orchestrator/Task-orchestrator-auto-nudge.md) for health events (soft — feed works without it)
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] SSE route with workspace membership check
|
||||||
|
- [ ] `convoy_events` tail query + fan-out on insert (LISTEN/NOTIFY or short poll server-side)
|
||||||
|
- [ ] `ActivityFeed` client component
|
||||||
|
- [ ] Rate limit / connection cap per user
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] New `role_complete` event appears in mission control within 5s without refresh
|
||||||
|
- [ ] User cannot subscribe to another workspace's events
|
||||||
|
- [ ] Connection closes cleanly on navigation
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-fleet-dashboard.md`
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: fleet-rollup-dashboard
|
||||||
|
title: Fleet dashboard — cross-repo convoy rollup
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: fleet-dashboard
|
||||||
|
status: ready
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Operator home at `/fleet` (or authenticated landing): rollup gate inbox counts, convoys by status, and active `agent_runs` across all workspaces the user belongs to.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Core Epic 9 scope. Answers: **"What needs me across all projects?"**
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
- Card per connected repo / convoy workspace
|
||||||
|
- Badge: N awaiting approval (sum of `GATE_INBOX_STATUSES`)
|
||||||
|
- Quick links into `/{workspaceSlug}/mission-control?convoy=...`
|
||||||
|
- Active runs count + blocked count
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
- tRPC `fleet.summary` — membership-scoped cross-workspace query (no client-provided workspace_id trust)
|
||||||
|
- Reuse `MISSION_CONTROL_KANBAN_COLUMNS` counts per workspace
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 4, 5 (shipped)
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] `fleet` tRPC router with membership joins
|
||||||
|
- [ ] `/fleet` route (app layout)
|
||||||
|
- [ ] Icon rail / top-header link when user has ≥2 workspaces
|
||||||
|
- [ ] Empty state for single-workspace operators
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Operator with two connected repos sees combined "3 awaiting approval" badge
|
||||||
|
- [ ] Clicking badge navigates to correct workspace mission control with inbox focused
|
||||||
|
- [ ] Query performs one round-trip (no N+1 per workspace in UI)
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-fleet-dashboard.md`
|
||||||
|
|
@ -7,13 +7,15 @@ status: draft
|
||||||
priority: P2
|
priority: P2
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_epic_id: null
|
cursor_epic_id: null
|
||||||
updated_at: "2026-07-03"
|
updated_at: "2026-08-03"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Epic objective
|
# Epic objective
|
||||||
|
|
||||||
Webhook receivers on Echodo for connected forges: PR opened → `pr_review`; PR merged → trigger doc-writer job + `merged`; CI failed → optional `blocked` or notify. Supports Forgejo and GitHub adapters minimum.
|
Webhook receivers on Echodo for connected forges: PR opened → `pr_review`; PR merged → trigger doc-writer job + `merged`; CI failed → optional `blocked` or notify. Supports Forgejo and GitHub adapters minimum.
|
||||||
|
|
||||||
|
PR checks recovery UI in mission control when CI fails (Autensa benchmark).
|
||||||
|
|
||||||
## In scope / out of scope
|
## In scope / out of scope
|
||||||
|
|
||||||
**In scope**
|
**In scope**
|
||||||
|
|
@ -21,6 +23,7 @@ Webhook receivers on Echodo for connected forges: PR opened → `pr_review`; PR
|
||||||
- `POST /api/webhooks/forge/:repoLinkId` with signature verification.
|
- `POST /api/webhooks/forge/:repoLinkId` with signature verification.
|
||||||
- Map events to `transition_convoy_status(actor: automation)`.
|
- Map events to `transition_convoy_status(actor: automation)`.
|
||||||
- Link PR branch to convoy/brief via branch naming convention or PR body marker.
|
- Link PR branch to convoy/brief via branch naming convention or PR body marker.
|
||||||
|
- PR checks recovery panel (classify failures, rerun where API allows).
|
||||||
|
|
||||||
**Out of scope**
|
**Out of scope**
|
||||||
|
|
||||||
|
|
@ -33,7 +36,11 @@ Webhook receivers on Echodo for connected forges: PR opened → `pr_review`; PR
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Merge on Forgejo moves convoy from `pr_review` to `merged` when Gate 2 approved.
|
- [ ] Merge on Forgejo moves convoy from `pr_review` to `merged` when Gate 2 approved.
|
||||||
|
- [ ] Mission control shows PR check failures with recovery actions for `pr_review` convoys.
|
||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
_To be decomposed when epic graduates to `ready`._
|
| Task | Link | Status |
|
||||||
|
|------|------|--------|
|
||||||
|
| Webhook receiver | [Task-forge-webhook-receiver](./Task-forge-webhook-receiver.md) | ready |
|
||||||
|
| PR checks recovery panel | [Task-pr-checks-recovery-panel](./Task-pr-checks-recovery-panel.md) | draft |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: forge-webhook-receiver
|
||||||
|
title: Forge webhook receiver — PR and CI events
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: forge-webhooks
|
||||||
|
status: ready
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
`POST /api/webhooks/forge/:repoLinkId` with HMAC signature verification; map forge events to `transition_convoy_status(actor: automation)`.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Core Epic 8 scope. Link PRs to convoys via branch naming convention (`convoy/<slug>/brief-N`) or PR body marker (`echodo-convoy: <uuid>`).
|
||||||
|
|
||||||
|
### Events (minimum)
|
||||||
|
|
||||||
|
| Forge event | Convoy transition |
|
||||||
|
|-------------|-------------------|
|
||||||
|
| PR opened | Ensure convoy in `pr_review` (if Gate 2 not yet human-approved, notify only) |
|
||||||
|
| PR merged | `pr_review` → `merged` when Gate 2 already approved |
|
||||||
|
| CI completed (failure) | Optional `blocked` or `convoy_events` notify |
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Per-repo webhook secret in `repo_links` metadata (reference env var name, not value)
|
||||||
|
- Zod-validated payload per `forge_type`
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 3, 4, 7
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Route handler + signature verification
|
||||||
|
- [ ] GitHub + Forgejo payload parsers
|
||||||
|
- [ ] Convoy lookup by branch/body marker
|
||||||
|
- [ ] Register webhook URL helper on connect (optional UX)
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Merge webhook moves convoy from `pr_review` to `merged` when Gate 2 approved
|
||||||
|
- [ ] Invalid signature returns 401
|
||||||
|
- [ ] Unknown branch logs and returns 200 (no retry storm)
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-forge-webhooks.md`
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: pr-checks-recovery-panel
|
||||||
|
title: PR checks recovery panel in mission control
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: forge-webhooks
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
When a convoy is in `pr_review`, show linked PR CI status in mission control with classified failures and recovery actions (rerun jobs, link to repo setup).
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa v2.5.1 PR checks recovery panel — classify failures as retryable, repo setup, or external provider; offer rerun where forge API supports it.
|
||||||
|
|
||||||
|
### UI (convoy detail panel)
|
||||||
|
|
||||||
|
- PR link + check run list (name, status, conclusion)
|
||||||
|
- Failure classification badge per check
|
||||||
|
- Actions: **Rerun failed jobs** (GitHub Actions API), **Open repo setup** (Epic 3 follow-on task)
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
- tRPC `convoys.getPrChecks` — workspace-scoped, uses forge adapter
|
||||||
|
- `convoys.rerunFailedChecks` — admin only; audit log in `convoy_events`
|
||||||
|
|
||||||
|
### Webhook integration
|
||||||
|
|
||||||
|
- CI `completed` webhook refreshes cached check status on convoy metadata
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- [Task-forge-webhook-receiver](./Task-forge-webhook-receiver.md)
|
||||||
|
- [Task-repo-setup-preflight](../Epic-connected-repos/Task-repo-setup-preflight.md) (link target for setup failures)
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Forge adapter: list check runs for PR
|
||||||
|
- [ ] Failure classifier (heuristics: permissions → setup, timeout → retryable, external → informational)
|
||||||
|
- [ ] Mission control PR checks section when status is `pr_review`
|
||||||
|
- [ ] Rerun action + event logging
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Failed lint CI shows retryable with working rerun (GitHub fixture or manual dogfood)
|
||||||
|
- [ ] Missing Actions permission links to repo setup tab with failing check highlighted
|
||||||
|
- [ ] No recovery action exposed without workspace admin role
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-forge-webhooks.md`
|
||||||
|
|
@ -7,7 +7,7 @@ status: done
|
||||||
priority: P1
|
priority: P1
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_epic_id: null
|
cursor_epic_id: null
|
||||||
updated_at: "2026-07-03"
|
updated_at: "2026-08-03"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Epic objective
|
# Epic objective
|
||||||
|
|
@ -48,3 +48,12 @@ Echodo UI for human gates and convoy visibility:
|
||||||
|
|
||||||
- [x] [Task-trpc-convoys-router](./Task-trpc-convoys-router.md)
|
- [x] [Task-trpc-convoys-router](./Task-trpc-convoys-router.md)
|
||||||
- [x] [Task-mission-control-ui](./Task-mission-control-ui.md)
|
- [x] [Task-mission-control-ui](./Task-mission-control-ui.md)
|
||||||
|
|
||||||
|
## Follow-on tasks (Autensa benchmark)
|
||||||
|
|
||||||
|
| Task | Link |
|
||||||
|
|------|------|
|
||||||
|
| Convoy DAG visualization | [Task-convoy-dag-visualization](./Task-convoy-dag-visualization.md) |
|
||||||
|
| Automation tiers (supervised / semi-auto) | [Task-automation-tiers](./Task-automation-tiers.md) |
|
||||||
|
|
||||||
|
Operator mid-build chat is tracked under Epic 7: [Task-worker-operator-notes](../Epic-apps-worker-v1/Task-worker-operator-notes.md).
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: automation-tiers
|
||||||
|
title: Automation tiers — supervised, semi-auto, full-auto gate policy
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: mission-control-gates-ui
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Per-convoy (or per-workspace default) **automation tier** controlling which human gates auto-advance when CI and review agents pass.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa automation tiers (Supervised / Semi-Auto / Full Auto). Maps onto Echodo's explicit gate model without removing human override.
|
||||||
|
|
||||||
|
| Tier | Gate 1 (plan) | Gate 2 (merge) | Gate 3 (prod) |
|
||||||
|
|------|---------------|----------------|---------------|
|
||||||
|
| **Supervised** | Human | Human | Human |
|
||||||
|
| **Semi-auto** | Human | Auto when CI green + review agent pass | Human |
|
||||||
|
| **Full-auto** | Human | Auto when CI green | Auto when deploy webhook fires (future) |
|
||||||
|
|
||||||
|
### Schema
|
||||||
|
|
||||||
|
- `convoys` metadata field `automation_tier`: `supervised` | `semi_auto` | `full_auto` (default `supervised`)
|
||||||
|
- Workspace default in settings (optional)
|
||||||
|
|
||||||
|
### Behavior
|
||||||
|
|
||||||
|
- Orchestrator / webhook handlers consult tier before calling `transition_convoy_status` with `actor: automation`
|
||||||
|
- Mission control shows tier badge on convoy card; editable before **Go**
|
||||||
|
|
||||||
|
### Out of scope
|
||||||
|
|
||||||
|
- Auto-approving Gate 1 (plan always human in v1)
|
||||||
|
- Autopilot research/ideation (Autensa-specific)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 5 gates UI
|
||||||
|
- Epic 8 webhooks for semi-auto Gate 2
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Zod enum in `packages/shared/convoy-lifecycle`
|
||||||
|
- [ ] Create convoy dialog + detail panel tier selector
|
||||||
|
- [ ] Orchestrator respects tier on CI webhook path
|
||||||
|
- [ ] Document tier semantics in `docs/orchestrator.md`
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
S
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Semi-auto convoy auto-transitions `pr_review` → `merged` on merge webhook only when CI was green at merge time
|
||||||
|
- [ ] Supervised convoy never auto-merges
|
||||||
|
- [ ] Tier visible on kanban card tooltip
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-mission-control-gates-ui.md`
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: convoy-dag-visualization
|
||||||
|
title: Convoy DAG visualization for parallel briefs
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: mission-control-gates-ui
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Read-only dependency graph in mission control showing brief/subtask relationships and `multitask_group` parallel lanes.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa Convoy Mode DAG — visual dependency graph for parallel subtasks. Echodo already has `multitask_group` on `convoy_events` and parallel implementer fan-out in the orchestrator ADR; this task adds **visibility**, not new scheduling logic.
|
||||||
|
|
||||||
|
### Data source
|
||||||
|
|
||||||
|
- Parse brief frontmatter / `slice_dependencies` from `.convoys/<slug>/brief-*.md` (via convoy object metadata or file reconcile)
|
||||||
|
- Overlay live status from `agent_runs` + convoy status per brief
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
- Mission control detail panel tab: **Graph**
|
||||||
|
- Nodes = briefs; edges = dependencies; color = run status (pending, running, done, blocked)
|
||||||
|
- Click node selects brief in detail panel
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 5 mission control (shipped)
|
||||||
|
- Epic 6 orchestrator parallel dispatch (shipped)
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Shared zod type `ConvoyDag` in `packages/shared`
|
||||||
|
- [ ] tRPC `convoys.getDag`
|
||||||
|
- [ ] React graph component (lightweight — e.g. layered layout, no heavy graph lib unless justified)
|
||||||
|
- [ ] Empty state when single-brief convoy
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Two-brief convoy with dependency shows correct edge direction
|
||||||
|
- [ ] Parallel briefs without dependency appear in same column/lane
|
||||||
|
- [ ] Blocked brief visually distinct from pending
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-mission-control-gates-ui.md`
|
||||||
|
|
@ -7,7 +7,7 @@ status: done
|
||||||
priority: P1
|
priority: P1
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_epic_id: null
|
cursor_epic_id: null
|
||||||
updated_at: "2026-07-03"
|
updated_at: "2026-08-03"
|
||||||
agent_prompt: |
|
agent_prompt: |
|
||||||
Epic: model provider registry (docs/adr-model-routing.md). Server-only change —
|
Epic: model provider registry (docs/adr-model-routing.md). Server-only change —
|
||||||
no UI component library inventing; reuse components/ui/. Admin-only mutations.
|
no UI component library inventing; reuse components/ui/. Admin-only mutations.
|
||||||
|
|
@ -32,12 +32,9 @@ This epic is the first shipped piece of the automation-foundation plan and unblo
|
||||||
- `complete_task` optional model logging fields.
|
- `complete_task` optional model logging fields.
|
||||||
- `.env.example` env var documentation.
|
- `.env.example` env var documentation.
|
||||||
|
|
||||||
**Out of scope**
|
**Out of scope (moved to follow-on task)**
|
||||||
|
|
||||||
- Orchestrator dispatch (consumes resolver later).
|
- Billing/budget enforcement → [Task-cost-budget-ui-and-caps](./Task-cost-budget-ui-and-caps.md)
|
||||||
- Worker inference loop.
|
|
||||||
- Parsing `model_policy` from `.convoys/*.md` files (orchestrator reads later).
|
|
||||||
- Billing/budget enforcement.
|
|
||||||
|
|
||||||
## Related tasks
|
## Related tasks
|
||||||
|
|
||||||
|
|
@ -47,9 +44,15 @@ This epic is the first shipped piece of the automation-foundation plan and unblo
|
||||||
| DB schema and migration | `./Task-db-model-providers-migration.md` |
|
| DB schema and migration | `./Task-db-model-providers-migration.md` |
|
||||||
| tRPC models router | `./Task-trpc-models-router.md` |
|
| tRPC models router | `./Task-trpc-models-router.md` |
|
||||||
| Settings — providers UI | `./Task-settings-ai-providers-ui.md` |
|
| Settings — providers UI | `./Task-settings-ai-providers-ui.md` |
|
||||||
| Settings — role routing UI | `./Task-settings-role-routing-ui.md` |
|
| Settings — role routing UI | `./Task-settings-ai-role-routing-ui.md` |
|
||||||
| agent_runs model fields + MCP | `./Task-agent-runs-model-logging.md` |
|
| agent_runs model fields + MCP | `./Task-agent-runs-model-logging.md` |
|
||||||
|
|
||||||
|
## Follow-on tasks (Autensa benchmark)
|
||||||
|
|
||||||
|
| Task | Link |
|
||||||
|
|------|------|
|
||||||
|
| Cost visibility & dispatch budget caps | [Task-cost-budget-ui-and-caps](./Task-cost-budget-ui-and-caps.md) |
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- Depends on: existing auth + workspace admin patterns in `apps/web`.
|
- Depends on: existing auth + workspace admin patterns in `apps/web`.
|
||||||
|
|
@ -57,11 +60,11 @@ This epic is the first shipped piece of the automation-foundation plan and unblo
|
||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Admin can create `claude-planning` (anthropic) and `qwen-coder` (openai_compatible + base URL) in a workspace.
|
- [x] Admin can create `claude-planning` (anthropic) and `qwen-coder` (openai_compatible + base URL) in a workspace.
|
||||||
- [ ] Admin can map `role-implementer` → `qwen-coder`, `role-architect` → `claude-planning`.
|
- [x] Admin can map `role-implementer` → `qwen-coder`, `role-architect` → `claude-planning`.
|
||||||
- [ ] `testProvider` returns success/failure without exposing API keys.
|
- [x] `testProvider` returns success/failure without exposing API keys.
|
||||||
- [ ] `resolveModel()` unit tests cover override order and missing-alias error.
|
- [x] `resolveModel()` unit tests cover override order and missing-alias error.
|
||||||
- [ ] At least one task in this epic completed via `claim_task` → `complete_task` with model metadata.
|
- [x] At least one task in this epic completed via `claim_task` → `complete_task` with model metadata.
|
||||||
|
|
||||||
## Proposed timeline
|
## Proposed timeline
|
||||||
|
|
||||||
|
|
@ -71,6 +74,7 @@ This epic is the first shipped piece of the automation-foundation plan and unblo
|
||||||
| API | Session 3 | tRPC router |
|
| API | Session 3 | tRPC router |
|
||||||
| UI | Session 4–5 | Both settings pages |
|
| UI | Session 4–5 | Both settings pages |
|
||||||
| Logging | Session 6 | agent_runs + MCP |
|
| Logging | Session 6 | agent_runs + MCP |
|
||||||
|
| Usage & caps | Future | Follow-on task |
|
||||||
|
|
||||||
## Pipeline / convoy mapping
|
## Pipeline / convoy mapping
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
kind: task
|
||||||
|
slug: cost-budget-ui-and-caps
|
||||||
|
title: Cost visibility and dispatch budget caps
|
||||||
|
plan_slug: automation-foundation
|
||||||
|
epic_slug: model-provider-registry
|
||||||
|
status: draft
|
||||||
|
priority: P2
|
||||||
|
tenant_id: global
|
||||||
|
owner: unassigned
|
||||||
|
cursor_todo_id: null
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task summary
|
||||||
|
|
||||||
|
Surface spend from `convoy_events.estimated_cost_usd` and `agent_runs` token metadata; add optional workspace budget caps that pause orchestrator dispatch when exceeded.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Benchmark:** Autensa per-task/product cost tracking and daily/monthly budget caps. Epic 1 deferred billing — this follow-on uses data already on `convoy_events` and run completion.
|
||||||
|
|
||||||
|
### Read path (UI)
|
||||||
|
|
||||||
|
- Settings → AI → **Usage & budgets**
|
||||||
|
- Rollups: today / this month by `model_alias`, by convoy, by role
|
||||||
|
- Mission control convoy detail: spend to date for selected convoy
|
||||||
|
|
||||||
|
### Write path (enforcement)
|
||||||
|
|
||||||
|
- `workspace_budget_caps` table: `period` (`daily` | `monthly`), `cap_usd`, `action` (`pause_dispatch` | `warn_only`)
|
||||||
|
- Orchestrator tick: sum `estimated_cost_usd` for period; if over cap and `pause_dispatch`, skip new `role_dispatch` enqueue and write health event
|
||||||
|
|
||||||
|
### Cost estimation
|
||||||
|
|
||||||
|
- Worker/orchestrator populate `estimated_cost_usd` on `convoy_events.role_complete` using provider-reported usage × static price table in shared config (v1 — no live pricing API)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Epic 1 model registry + `convoy_events` cost column (shipped)
|
||||||
|
- Epic 7 worker records token totals on complete
|
||||||
|
|
||||||
|
## Subtasks
|
||||||
|
|
||||||
|
- [ ] Price table stub in `packages/shared` (document as operator-editable later)
|
||||||
|
- [ ] tRPC usage queries (workspace-scoped aggregates)
|
||||||
|
- [ ] Settings usage page
|
||||||
|
- [ ] Budget cap schema + orchestrator guard
|
||||||
|
|
||||||
|
## Estimation
|
||||||
|
|
||||||
|
M
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Settings shows month-to-date spend grouped by model alias
|
||||||
|
- [ ] With cap set and exceeded, orchestrator logs skip reason and does not enqueue new jobs
|
||||||
|
- [ ] Warn-only cap emits event but does not block dispatch
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Epic: `./Epic-model-provider-registry.md`
|
||||||
|
- Unblocks: Epic 9 fleet spend rollup
|
||||||
|
|
@ -6,7 +6,7 @@ status: ready
|
||||||
priority: P1
|
priority: P1
|
||||||
tenant_id: global
|
tenant_id: global
|
||||||
cursor_plan_id: null
|
cursor_plan_id: null
|
||||||
updated_at: "2026-07-07"
|
updated_at: "2026-08-03"
|
||||||
agent_prompt: |
|
agent_prompt: |
|
||||||
You are implementing Echodo's automation foundation. Read docs/adr-model-routing.md
|
You are implementing Echodo's automation foundation. Read docs/adr-model-routing.md
|
||||||
before touching model routing code. This repo uses pnpm, Drizzle, tRPC, zod in
|
before touching model routing code. This repo uses pnpm, Drizzle, tRPC, zod in
|
||||||
|
|
@ -28,7 +28,7 @@ agent_prompt: |
|
||||||
|
|
||||||
Echodo is evolving from a multitenant task app with MCP coordination into **mission control** for an agent pipeline: fleet view, human gates, per-role model routing, and (later) a built-in orchestrator and worker. This plan delivers the **first concrete slice** — the model provider registry and role routing system defined in [docs/adr-model-routing.md](../../docs/adr-model-routing.md).
|
Echodo is evolving from a multitenant task app with MCP coordination into **mission control** for an agent pipeline: fleet view, human gates, per-role model routing, and (later) a built-in orchestrator and worker. This plan delivers the **first concrete slice** — the model provider registry and role routing system defined in [docs/adr-model-routing.md](../../docs/adr-model-routing.md).
|
||||||
|
|
||||||
Later epics in this plan (2–9) add convoy scaffolding, connected repos, lifecycle MCP, gates UI, orchestrator, worker, webhooks, and fleet dashboard. Epic 1 gives them a stable `resolveModel()` contract.
|
Epics 1–6 and the mission-control UI are **shipped**. Epic 7 (worker) is **in progress** — skeleton exists in `apps/worker`. Epics 8–9 remain draft with decomposed tasks. Follow-on tasks from the [Autensa benchmark](#autensa-benchmark-2026-08) are injected into epics 1, 3, 5, 6, 7, 8, and 9 (concepts only — no OpenClaw dependency).
|
||||||
|
|
||||||
## Dogfooding the agent pipeline
|
## Dogfooding the agent pipeline
|
||||||
|
|
||||||
|
|
@ -115,7 +115,8 @@ Start with **`Task-shared-schemas-resolve-model`** — no DB migration, pure `pa
|
||||||
**In scope (full plan)**
|
**In scope (full plan)**
|
||||||
|
|
||||||
- Nine epics — see [Epic roadmap](#epic-roadmap-complete) below.
|
- Nine epics — see [Epic roadmap](#epic-roadmap-complete) below.
|
||||||
- Epic 1 (model registry) is **ready** with six tasks; epics 2–9 are **draft** stubs for architect decomposition.
|
- Epics 1–6 **done**; Epic 7 **in progress**; Epics 8–9 **draft** with bead-scale tasks.
|
||||||
|
- [Autensa benchmark](#autensa-benchmark-2026-08) follow-ons: reliability (checkpoints, auto-nudge), operator UX (activity feed, DAG, PR recovery), cost caps.
|
||||||
- ADR at `docs/adr-model-routing.md`.
|
- ADR at `docs/adr-model-routing.md`.
|
||||||
|
|
||||||
**Out of scope (separate future plans)**
|
**Out of scope (separate future plans)**
|
||||||
|
|
@ -133,7 +134,7 @@ Start with **`Task-shared-schemas-resolve-model`** — no DB migration, pure `pa
|
||||||
|
|
||||||
## Epic roadmap (complete)
|
## Epic roadmap (complete)
|
||||||
|
|
||||||
Sequential order with parallel opportunities noted. Only **Epic 1** has bead-scale tasks today; epics 2–9 are draft stubs ready for architect decomposition when the prior epic lands.
|
Sequential order with parallel opportunities noted. **Current focus: Epic 7** (worker end-to-end dogfood), then Epic 8 → 9. Follow-on tasks on done epics can run in parallel when they do not block the critical path.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
|
|
@ -162,15 +163,15 @@ flowchart LR
|
||||||
|
|
||||||
| # | Epic | Status | Delivers | Depends on |
|
| # | Epic | Status | Delivers | Depends on |
|
||||||
|---|------|--------|----------|------------|
|
|---|------|--------|----------|------------|
|
||||||
| 1 | [Model provider registry](./Epic-model-provider-registry/Epic-model-provider-registry.md) | **ready** (6 tasks) | `resolveModel()`, Settings AI pages, run model logging | — |
|
| 1 | [Model provider registry](./Epic-model-provider-registry/Epic-model-provider-registry.md) | done (+1 follow-on) | `resolveModel()`, Settings AI pages, run model logging; cost caps task | — |
|
||||||
| 2 | [Pipeline convoy scaffolding](./Epic-pipeline-convoy-scaffolding/Epic-pipeline-convoy-scaffolding.md) | done | `.convoys/`, `log-convoy-event.sh`, `convoy-planning.mdc` — dogfood metrics | — (parallel with 1) |
|
| 2 | [Pipeline convoy scaffolding](./Epic-pipeline-convoy-scaffolding/Epic-pipeline-convoy-scaffolding.md) | done | `.convoys/`, `log-convoy-event.sh`, `convoy-planning.mdc` — dogfood metrics | — (parallel with 1) |
|
||||||
| 3 | [Connected repos](./Epic-connected-repos/Epic-connected-repos.md) | done | `repo_links` table, “paste remote URL”, forge adapter interface | — |
|
| 3 | [Connected repos](./Epic-connected-repos/Epic-connected-repos.md) | done (+1 follow-on) | `repo_links` table, paste URL, forge adapters; repo setup preflight | — |
|
||||||
| 4 | [Convoy lifecycle MCP](./Epic-convoy-lifecycle-mcp/Epic-convoy-lifecycle-mcp.md) | done | `create_convoy`, `transition_convoy_status`, state machine §7, `convoy_events` | 2, 3 |
|
| 4 | [Convoy lifecycle MCP](./Epic-convoy-lifecycle-mcp/Epic-convoy-lifecycle-mcp.md) | done | `create_convoy`, `transition_convoy_status`, state machine §7, `convoy_events` | 2, 3 |
|
||||||
| 5 | [Mission control gates UI](./Epic-mission-control-gates-ui/Epic-mission-control-gates-ui.md) | done | Convoy kanban, gate inbox, approve/deny/revise, gate co-pilot chat | 4 |
|
| 5 | [Mission control gates UI](./Epic-mission-control-gates-ui/Epic-mission-control-gates-ui.md) | done (+2 follow-ons) | Kanban, gate inbox, co-pilot; DAG viz + automation tiers | 4 |
|
||||||
| 6 | [Orchestrator](./Epic-apps-orchestrator/Epic-apps-orchestrator.md) | done | `apps/orchestrator`, Redis queue, role dispatch, pause at gates | 1, 3, 4 |
|
| 6 | [Orchestrator](./Epic-apps-orchestrator/Epic-apps-orchestrator.md) | done (+1 follow-on) | `apps/orchestrator`, Redis queue, role dispatch; auto-nudge | 1, 3, 4 |
|
||||||
| 7 | [Worker v1](./Epic-apps-worker-v1/Epic-apps-worker-v1.md) | draft | `apps/worker` minimal tool loop, worktree-per-brief, MCP claim/complete | 1, 3, 6 |
|
| 7 | [Worker v1](./Epic-apps-worker-v1/Epic-apps-worker-v1.md) | **in progress** (3 tasks) | Tool loop, checkpoints, operator notes | 1, 3, 6 |
|
||||||
| 8 | [Forge webhooks](./Epic-forge-webhooks/Epic-forge-webhooks.md) | draft | PR opened/merged/CI webhooks → convoy transitions | 3, 4, 7 |
|
| 8 | [Forge webhooks](./Epic-forge-webhooks/Epic-forge-webhooks.md) | draft (2 tasks) | Webhooks + PR checks recovery panel | 3, 4, 7 |
|
||||||
| 9 | [Fleet dashboard](./Epic-fleet-dashboard/Epic-fleet-dashboard.md) | draft | Cross-repo home, `convoys-*` workspaces, “needs you” rollup | 4, 5 |
|
| 9 | [Fleet dashboard](./Epic-fleet-dashboard/Epic-fleet-dashboard.md) | draft (2 tasks) | Cross-repo rollup + SSE activity feed | 4, 5 |
|
||||||
|
|
||||||
### Overlap with existing plans
|
### Overlap with existing plans
|
||||||
|
|
||||||
|
|
@ -183,7 +184,26 @@ flowchart LR
|
||||||
|
|
||||||
### End-state (what “done” looks like for the full plan)
|
### End-state (what “done” looks like for the full plan)
|
||||||
|
|
||||||
Operator opens Echodo fleet view → starts convoy chat → hits **Go** → orchestrator runs pipeline roles with per-role models → worker executes briefs against connected repos → gates surface in inbox with AI co-pilot → approve → repeat until `released`.
|
Operator opens Echodo fleet view → starts convoy chat → hits **Go** → orchestrator runs pipeline roles with per-role models → worker executes briefs against connected repos → gates surface in inbox with AI co-pilot → approve → repeat until `released`. Live activity feed, spend rollups, and PR recovery are visible without leaving mission control.
|
||||||
|
|
||||||
|
### Autensa benchmark (2026-08)
|
||||||
|
|
||||||
|
Studied [crshdn/mission-control](https://github.com/crshdn/mission-control) (Autensa) as a UX/reliability benchmark — **not** as a runtime dependency. Ideas mapped to tasks:
|
||||||
|
|
||||||
|
| Autensa concept | Echodo task | Epic |
|
||||||
|
|-----------------|-------------|------|
|
||||||
|
| Checkpoint & crash recovery | [Task-worker-checkpoint-resume](./Epic-apps-worker-v1/Task-worker-checkpoint-resume.md) | 7 |
|
||||||
|
| Operator chat mid-build | [Task-worker-operator-notes](./Epic-apps-worker-v1/Task-worker-operator-notes.md) | 7 |
|
||||||
|
| Agent health / auto-nudge | [Task-orchestrator-auto-nudge](./Epic-apps-orchestrator/Task-orchestrator-auto-nudge.md) | 6 |
|
||||||
|
| Repo setup preflight | [Task-repo-setup-preflight](./Epic-connected-repos/Task-repo-setup-preflight.md) | 3 |
|
||||||
|
| PR checks recovery | [Task-pr-checks-recovery-panel](./Epic-forge-webhooks/Task-pr-checks-recovery-panel.md) | 8 |
|
||||||
|
| Convoy DAG visualization | [Task-convoy-dag-visualization](./Epic-mission-control-gates-ui/Task-convoy-dag-visualization.md) | 5 |
|
||||||
|
| Automation tiers | [Task-automation-tiers](./Epic-mission-control-gates-ui/Task-automation-tiers.md) | 5 |
|
||||||
|
| Cost tracking & budget caps | [Task-cost-budget-ui-and-caps](./Epic-model-provider-registry/Task-cost-budget-ui-and-caps.md) | 1 |
|
||||||
|
| Live activity feed (SSE) | [Task-convoy-activity-feed-sse](./Epic-fleet-dashboard/Task-convoy-activity-feed-sse.md) | 9 |
|
||||||
|
| Fleet rollup | [Task-fleet-rollup-dashboard](./Epic-fleet-dashboard/Task-fleet-rollup-dashboard.md) | 9 |
|
||||||
|
|
||||||
|
**Explicitly not adopted:** OpenClaw Gateway, autopilot research/ideation/swipe, preference learning, agent skills learner, SQLite single-tenant model.
|
||||||
|
|
||||||
## Epics (links)
|
## Epics (links)
|
||||||
|
|
||||||
|
|
@ -212,6 +232,20 @@ Operator opens Echodo fleet view → starts convoy chat → hits **Go** → orch
|
||||||
| M6 Automation | 6–7 | Orchestrator dispatches one implementer brief unattended |
|
| M6 Automation | 6–7 | Orchestrator dispatches one implementer brief unattended |
|
||||||
| M7 PR loop | 8 | Merge webhook moves convoy to `merged` |
|
| M7 PR loop | 8 | Merge webhook moves convoy to `merged` |
|
||||||
| M8 Fleet | 9 | Single view across ≥2 connected repos |
|
| M8 Fleet | 9 | Single view across ≥2 connected repos |
|
||||||
|
| M9 Reliability | 7 | Worker completes brief; checkpoint resume after kill |
|
||||||
|
| M10 Observability | 9 | Activity feed shows role_complete without refresh |
|
||||||
|
| M11 Spend control | 1 follow-on | Month-to-date spend + dispatch pause on cap |
|
||||||
|
|
||||||
|
## Recommended execution order (post-benchmark)
|
||||||
|
|
||||||
|
1. **Epic 7 critical path** — [Task-worker-minimal-tool-loop](./Epic-apps-worker-v1/Task-worker-minimal-tool-loop.md) → live dogfood with orchestrator
|
||||||
|
2. **Epic 7 reliability** — checkpoint/resume, then operator notes
|
||||||
|
3. **Epic 8** — webhook receiver → PR checks panel (needs worker PR output)
|
||||||
|
4. **Epic 6 follow-on** — auto-nudge (pairs with checkpoints)
|
||||||
|
5. **Epic 3 follow-on** — repo preflight (before unattended prod dogfood)
|
||||||
|
6. **Epic 9** — fleet rollup → SSE feed
|
||||||
|
7. **Epic 5 follow-ons** — DAG viz, automation tiers (after Epic 8 for semi-auto)
|
||||||
|
8. **Epic 1 follow-on** — cost caps (after worker records token totals)
|
||||||
|
|
||||||
## Risks and mitigations
|
## Risks and mitigations
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue