[taskboard] document control plane status and roadmap
This commit is contained in:
15
README.md
15
README.md
@@ -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)
|
||||||
|
|||||||
47
docs/IMPLEMENTATION_STATUS.md
Normal file
47
docs/IMPLEMENTATION_STATUS.md
Normal 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
45
docs/ROADMAP.md
Normal 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.
|
||||||
@@ -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}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
Reference in New Issue
Block a user