[taskboard] document control plane status and roadmap

This commit is contained in:
2026-03-07 12:39:11 -08:00
parent e20b0ba55c
commit e8e79c7b4c
5 changed files with 121 additions and 2 deletions

View File

@@ -29,6 +29,16 @@ It tracks and visualizes:
- `/wiki` - markdown-backed runbooks and generated docs - `/wiki` - markdown-backed runbooks and generated docs
- `/usage` - usage aggregates from the local tracking table - `/usage` - usage aggregates from the local tracking table
## Control Plane Features
- typed fleet config and task template config
- dispatch lifecycle states and SQLite audit history
- OpenClaw swarm dispatch into `~/.clawdbot/active-tasks.json`
- ZeroClaw webhook dispatch for `grizzley` and `ice`
- failure queue and dispatch history views
- family-specific runtime views for OpenClaw and ZeroClaw
- architecture documentation rendered directly from tracked config
## Fleet Model ## Fleet Model
### OpenClaw ### OpenClaw
@@ -99,3 +109,8 @@ npm start
- The UI intentionally treats OpenClaw and ZeroClaw as separate families with different runtime and channel models. - The UI intentionally treats OpenClaw and ZeroClaw as separate families with different runtime and channel models.
- `ice` ZeroClaw remains tied to host-local secret/encryption state; the dashboard reads that runtime but does not attempt to rewrite it. - `ice` ZeroClaw remains tied to host-local secret/encryption state; the dashboard reads that runtime but does not attempt to rewrite it.
## Status Docs
- [Implementation status](./docs/IMPLEMENTATION_STATUS.md)
- [Roadmap](./docs/ROADMAP.md)

View File

@@ -0,0 +1,47 @@
# Taskboard Implementation Status
## Implemented
- Next.js App Router migration with React 19, Tailwind CSS, and shadcn-style UI primitives
- Typed fleet model loaded from `config/fleet.json`
- Typed task templates loaded from `config/task-templates.json`
- Unified task intake for OpenClaw and ZeroClaw
- Dispatch lifecycle states:
- `planned`
- `assigned`
- `dispatched`
- `acknowledged`
- `completed`
- `failed`
- SQLite-backed audit log in `task_events`
- Dispatch history API and UI
- Failure queue UI
- Family-specific pages:
- `/openclaw`
- `/zeroclaw`
- Architecture page rendered from tracked fleet config
- Agent cards with:
- heartbeat age
- workload
- last dispatch event
- failure counts
- OpenClaw swarm dispatch:
- repo map lookup
- safe-directory git handling for mounted repos
- worktree creation
- queue insertion into `~/.clawdbot/active-tasks.json`
- ZeroClaw webhook dispatch:
- bearer-token support for paired gateways
- direct gateway mode for testing
## Verified Live
- `grizzley` ZeroClaw webhook dispatch from taskboard
- `ice` ZeroClaw webhook dispatch from taskboard
- OpenClaw swarm queue creation and host worktree creation on `ubuntu`
## Current Limits
- Taskboard can dispatch OpenClaw swarm tasks, but it does not yet monitor tmux session progress automatically.
- ZeroClaw acknowledgements and completions are still operator-driven; remote runtimes do not push completion state back yet.
- The board records remote webhook responses, but not structured per-step execution output from the agents.

45
docs/ROADMAP.md Normal file
View File

@@ -0,0 +1,45 @@
# Taskboard Roadmap
## Next
1. Add execution-state sync for OpenClaw swarm tasks.
- Read `~/.clawdbot/active-tasks.json`
- Detect `queued`, `running`, and `completed`
- Reflect those states back into taskboard tasks automatically
2. Add remote completion callbacks for ZeroClaw.
- Accept structured webhook acknowledgements
- Persist remote execution summaries
- Auto-transition tasks to `acknowledged` or `completed`
3. Add per-host direct taskboard targets beyond the current fleet.
- `pve`
- `truenas`
- `panda`
4. Add operator controls for swarm execution.
- launch queued task
- stop task
- nudge task
- open session/log link
5. Add richer audit detail.
- store structured request payload
- store response excerpt separately from summary
- attach host/service verification artifacts
6. Add dashboard summaries.
- task counts by family
- stale heartbeat warnings
- failure trends
- dispatch latency
7. Add completion workflows.
- generate wiki summary automatically
- link completed task to artifacts, PRs, or logs
## Longer Term
- Introduce a fleet capability registry so the taskboard can validate whether a task is legal for a given host before dispatch.
- Add authentication and RBAC for multi-operator use.
- Add generated runbooks and service maps directly from live host inventory.

View File

@@ -5,6 +5,7 @@ import { execFile } from "node:child_process";
import { import {
REPO_ACCESS_ROOTS, REPO_ACCESS_ROOTS,
SWARM_HOST_WORKTREES_DIR,
SWARM_REPO_MAP_FILE, SWARM_REPO_MAP_FILE,
SWARM_TASKS_FILE, SWARM_TASKS_FILE,
SWARM_WORKTREES_DIR, SWARM_WORKTREES_DIR,
@@ -78,6 +79,7 @@ async function dispatchOpenClawTask(taskId: number) {
const taskKey = `taskboard-${task.id}`; const taskKey = `taskboard-${task.id}`;
const repoName = path.basename(repoPath); const repoName = path.basename(repoPath);
const worktree = path.join(SWARM_WORKTREES_DIR, repoName, taskKey); const worktree = path.join(SWARM_WORKTREES_DIR, repoName, taskKey);
const hostWorktree = path.join(SWARM_HOST_WORKTREES_DIR, repoName, taskKey);
const branch = `feat/taskboard-${task.id}`; const branch = `feat/taskboard-${task.id}`;
const baseBranch = task.base_branch || "main"; const baseBranch = task.base_branch || "main";
@@ -102,7 +104,7 @@ async function dispatchOpenClawTask(taskId: number) {
repo: repoName, repo: repoName,
repoPath, repoPath,
repoSlug: task.repo_slug, repoSlug: task.repo_slug,
worktree, worktree: hostWorktree,
branch, branch,
baseBranch, baseBranch,
tmuxSession: `${agentName}-${taskKey}`, tmuxSession: `${agentName}-${taskKey}`,
@@ -124,6 +126,14 @@ async function dispatchOpenClawTask(taskId: number) {
reviewPassed: false, reviewPassed: false,
}, },
}); });
} else {
existing.repoPath = repoPath;
existing.repoSlug = task.repo_slug;
existing.worktree = hostWorktree;
existing.branch = branch;
existing.baseBranch = baseBranch;
existing.agent = agentName;
existing.tmuxSession = `${agentName}-${taskKey}`;
} }
fs.writeFileSync(SWARM_TASKS_FILE, JSON.stringify({ tasks }, null, 2)); fs.writeFileSync(SWARM_TASKS_FILE, JSON.stringify({ tasks }, null, 2));
@@ -131,7 +141,7 @@ async function dispatchOpenClawTask(taskId: number) {
return { return {
state: "dispatched" as const, state: "dispatched" as const,
summary: `Queued in OpenClaw swarm for ${agentName}`, summary: `Queued in OpenClaw swarm for ${agentName}`,
detail: `${task.repo_slug} -> ${worktree}`, detail: `${task.repo_slug} -> ${hostWorktree}`,
}; };
} }

View File

@@ -9,6 +9,8 @@ export const OPENCLAW_CONFIG_PATH = process.env.OPENCLAW_CONFIG || "/home/bear/.
export const SWARM_TASKS_FILE = process.env.SWARM_TASKS_FILE || "/app/swarm/active-tasks.json"; export const SWARM_TASKS_FILE = process.env.SWARM_TASKS_FILE || "/app/swarm/active-tasks.json";
export const SWARM_REPO_MAP_FILE = process.env.SWARM_REPO_MAP_FILE || "/app/swarm/repo-map.json"; export const SWARM_REPO_MAP_FILE = process.env.SWARM_REPO_MAP_FILE || "/app/swarm/repo-map.json";
export const SWARM_WORKTREES_DIR = process.env.SWARM_WORKTREES_DIR || "/app/swarm/worktrees"; export const SWARM_WORKTREES_DIR = process.env.SWARM_WORKTREES_DIR || "/app/swarm/worktrees";
export const SWARM_HOST_WORKTREES_DIR =
process.env.SWARM_HOST_WORKTREES_DIR || SWARM_WORKTREES_DIR;
export const REPO_ACCESS_ROOTS = (process.env.REPO_ACCESS_ROOTS || "/srv/apps,/home/bear") export const REPO_ACCESS_ROOTS = (process.env.REPO_ACCESS_ROOTS || "/srv/apps,/home/bear")
.split(",") .split(",")
.map((entry) => entry.trim()) .map((entry) => entry.trim())