Master task list for building the v2 web dashboard with Linear integration and agent monitoring.
Reference docs:
ARCHITECTURE.md— system architecture, data flows, DB schema.env.example— all environment variables
- 0.1 Add
Authorization: Bearer <DASHBOARD_API_KEY>middleware to all API routes - 0.2 Fix CORS — replace
Access-Control-Allow-Origin: *with allowlist - 0.3 Add rate limiting to write endpoints
- 0.4 Update
opencode-hook/dashboard-hook.tsto send API key
- 1A.1 Add
project_id TEXTcolumn tomessages,sessions,tasks,sprints,todo_comments - 1A.2 Create
userstable (github_id, username, display_name, avatar_url, role) - 1A.3 Create
auth_sessionstable (token_hash SHA-256, expires_at) - 1A.4 Create
invite_linkstable (created_by, role, expires_at, used_by) - 1A.5 Create
projectstable + seed from existing todos
- 1B.1
.env.exampledocumentsGITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET⚠️ User action needed: Create GitHub OAuth App at github.com/settings/developers- Callback URL:
https://clawdinas-mac-mini.tail677558.ts.net/opencode/api/auth/callback .env.localhas placeholders ready to fill
- 1B.2
GET /api/auth/login— redirects to GitHub with state param + CSRF cookie - 1B.3
GET /api/auth/callback— exchanges code, fetches user, creates session- First user becomes owner; subsequent users need invite link or direct add
- Invite-link users are created with viewer role at callback, upgraded at accept
- 1B.4
GET /api/auth/verify— reads cookie/header, checks expiry, returns user- Supports
DISABLE_AUTH=truefor Tailscale-only setups
- Supports
- 1B.5
POST /api/auth/logout— deletes session, clears cookie - 1B.6 Multiple GitHub accounts per browser (account switcher)
- Low priority nice-to-have
- 1C.1
validateAuth()accepts API key (machine) + session token (browser) - 1C.2
requireRole()with owner > admin > viewer hierarchy
- 1D.1
GET /api/settings/team— returns all users (owner only) - 1D.2
POST /api/settings/team/invite— direct add by GitHub username + invite link mode - 1D.3
DELETE /api/settings/team/:userId— remove user + sessions - 1D.4
PATCH /api/settings/team/:userId— update role - 1D.5
/invite/[id]landing page +/invite/[id]/acceptpage - 1D.6 Settings page at
/settings— team list, add member, invite link, projects
- 1E.1 Project dropdown in header (next to sprint picker)
- 1E.2 Filter todos, messages, sprints by selected project
- URL param
?project=cookbookfor shareable links
- URL param
- 1E.3 Todos API accepts
projectfield on create/update; hook sends project via payload
- 1F.1
/loginpage with "Sign in with GitHub" button - 1F.2
AuthGuardcomponent wraps/,/analytics,/settings- Zustand auth store (
useAuthStore) for user state
- Zustand auth store (
- 2.1
GET /api/stream— SSE endpoint with auth (token query param), ping keepalive - 2.2
eventBussingleton — in-memory EventEmitter,publish()method- Events:
todo:updated,todo:created,todo:deleted,message:created,sprint:updated,sprint:created,agent:status,project:updated - 21
eventBus.publish()calls across 13 API route files
- Events:
- 2.3
useSSEhook — EventSource with reconnection, fallback to 3s polling on failure - 2.4 Polling is fallback only; SSE is primary transport
- 3.1
agentsandagent_taskstables with full schema + indexes - 3.3
GET /api/agents— enriched with current_task, sub_agent_count, age_seconds - 3.4
GET/PATCH/DELETE /api/agents/[id]— full agent CRUD - 3.5 Agent action endpoints:
POST /api/agents/[id]/actions— sleep, stop, unblock, restartPOST /api/agents/[id]/assign— assign taskPOST /api/agents/[id]/block— mark blockedPOST /api/agents/[id]/complete— complete taskPOST /api/agents/[id]/error— report errorPOST /api/agents/[id]/heartbeat— heartbeatPOST /api/agents/[id]/tasks— create/list tasksPATCH /api/agents/[id]/tasks/[taskId]— update taskPOST /api/agents/[id]/workflow— workflow managementPOST /api/agents/[id]/workflow/signal— workflow signals
- 3.6 Agent age — computed
age_secondsfromcreated_at - 3.7 Agent hierarchy —
parent_agent_id+sub_agent_countin enrichment - 3.UI AgentPanel, AgentCard, AgentDetailModal components + Agents tab on dashboard
- 3.2 Agent registration hook for oh-my-opencode
BackgroundManager- Requires upstream oh-my-opencode integration release
- Hook calls: POST on spawn, PATCH on heartbeat, PATCH on complete/error
- 3.8 Track oh-my-opencode integration release status
- 4.1
@linear/sdkinstalled (v75) - 4.2
linear_projects,linear_issues,linear_workflow_statestables - 4.4
POST /api/linear/webhook— HMAC signature verification, issue/project/cycle handlers, auto-assignment to agents - 4.5
POST /api/linear/sync— full sync (teams → states → projects → issues) - 4.6
PATCH /api/linear/sync— card drag handler (updates issue state via Linear API + local cache) - 4.8 Agent-to-issue linking (
linkAgentToIssue,agent_task_idon issues) - 4.UI LinearBoard, LinearProjectSelector, LinearIssueCard components + Linear tab on dashboard
- 4.3 Linear client (
src/lib/linear/client.ts) — usesLINEAR_API_KEYenv var⚠️ User action needed: AddLINEAR_API_KEYto.env.localto enable sync
- 4.7 Programmatic webhook registration via
webhookCreatemutation- Currently manual: register at linear.app/settings/api/webhooks
The lifecycle manager (
src/lib/agents/lifecycle.ts) implements agent orchestration with in-memory timers instead of Temporal. All Phase 5 features work today without Temporal. Temporal adds crash recovery and durable retry — upgrade when needed.
- 5.1 Install Temporal TypeScript SDK
- 5.2 Run Temporal server (Docker or Temporal Cloud)
- 5.3 Define
agentTaskWorkflow - 5.4 Define activities (start, monitor, notify, update)
- 5.5 Implement sleep/wake signals via Temporal conditions
- 6.1
alert_rulestable with full schema - 6.2 Default alert rules seeded (blocked, error, completed, idle, stale)
- 6.3 Alert engine (
src/lib/alerts/engine.ts) — processes events, matches rules, fires notifications- Lifecycle manager calls
alertEngine.processEvent()on block/complete/idle
- Lifecycle manager calls
- 6.5
GET/PUT /api/settings/alerts+DELETE /api/settings/alerts/[id] - 6.4 Push notification channel (currently in-app only)
- Needs: push notification service integration (web push or mobile)
src/lib/agents/lifecycle.ts— full lifecycle manager singleton
- 7.1 Task assignment (
assignTask) — creates agent_task, sets agent working, links to Linear issue - 7.2 Block detection (
detectBlocked) — explicit, repeated_errors (3+ in window), idle (5min no heartbeat)- Auto-triggers alerting via alert engine
- 7.3 Message throttling (
shouldSendMessage) — max 3 pushes per agent per hour - 7.4 Sleep/wake management:
triggerSleep— manual, error threshold (5 in 10min), scheduled windowtriggerWake— manual, new high-priority taskisInSleepWindow— timezone-aware schedule checkGET/PUT /api/settings/sleep-scheduleendpoint
- 7.5 Task completion (
completeTask) — updates status, checks for pending work, auto-sleeps if in window - 7.6 Idle monitoring — 5min timer per agent, auto-detects blocked state
- 9.1 Agent monitoring panel (AgentPanel tab)
- 9.2 Linear kanban view (LinearBoard tab)
- 9.3 SSE on web (useSSE hook)
- 9.4 Login page (GitHub OAuth)
- 10.1 API tests: auth middleware, CORS, rate limiting
- 10.2 Integration tests: hook → API → DB → SSE → web flow
- 10.3 Linear webhook signature verification test
- 10.4 Agent lifecycle tests: block → alert → unblock cycle
- 10.5 Load test: concurrent agents posting updates
- Create GitHub OAuth App — github.com/settings/developers → fill
GITHUB_CLIENT_ID/SECRETin.env.local→ setDISABLE_AUTH=false - Add LINEAR_API_KEY — linear.app/settings/api → fill in
.env.local
- 1B.6 — Account switcher for multiple GitHub accounts
- 4.7 — Programmatic Linear webhook registration
- 6.4 — Push notification channel
- Phase 5 — Temporal upgrade (when crash recovery is needed)
- Phase 10 — Test suite
- 3.2 — oh-my-opencode BackgroundManager hook integration (blocked on upstream release)
Phase 0 (Security) ✅
└──> Phase 1 (Auth) ✅ ──> Phase 2 (SSE) ✅ ──> Phase 3 (Agents) ✅ ──> Phase 5 (Temporal) ○
└──> Phase 6 (Alerting) ✅
└──> Phase 7 (Lifecycle) ✅
──> Phase 4 (Linear) ✅ ──> Phase 9 (Web) ✅
All ──> Phase 10 (Testing) ○
✅ = Complete ○ = Not started / Deferred