Local-first issue board for DeepSeek Harness: board data, model-facing tools, an agent planning loop, and a human approval queue for agent-proposed issues.
Local-first issue orchestrator for DeepSeek Harness: one board per repository, a fresh session per issue, and a scheduler that works the queue itself
Cordis Plugin · Workspace-Scoped Board · Per-Issue Sessions · Auto-Pull Scheduler · Two Human Approval Gates
Features
Feature
Description
One Board Per Repository
The board is bound to the session's working directory, not to the conversation: two sessions in the same repo share a board, and a session in another repo sees its own — the host resolves it, so the browser can never mix projects
Fresh Session Per Issue
"Work on this" opens a brand-new session with the issue's brief and binds the issue to it, so every issue's transcript and cost are its own — and several can run at once
Auto-Pull Scheduler
A scheduler keeps up to N issues in flight and refills from todo by itself — highest priority first — with live controls for concurrency and the auto-pull toggle in the board header
Two Human Gates
An agent can never move an issue out of proposed and can never mark one done: proposals need your approval, finished work needs your acceptance — both enforced in the service layer, not the UI
Durable Approval Queue
dsh-orchestrator · DSH Hub
Agent-proposed issues land in a proposed column and stay there until a human approves or rejects them — durable across restarts, unlike a one-shot approval prompt
Board as a Chat Peer
The board registers into the conversation view ring, so it appears as a tab beside Chat and Trajectory instead of a separate page
Screenshots
The board rendered with sample data — no project details from any real deployment.
Board view: workspace-scoped board with the approval queue, the scheduler strip (auto-pull toggle, parallelism, live running/waiting counts), and the session chip on the in-flight issue:
Issue detail, expanded from a card, showing the unified acceptance controls — Accept, or Send back with a reason that lands as a comment:
%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '14px'}}}%%
graph LR
UI[Board View
React] -->|RPC + SSE| SVC[Taskboard Service
Cordis Plugin]
TOOLS[taskboard_* Tools
Model-facing] --> SVC
PLAN[taskboard_plan
Workflow Engine] -->|fresh subagents| TOOLS
SVC --> DB[(Storage Domain)]
SVC --> WS[Workspace Registry
cwd → workspace]
SCHED[Scheduler
session-link] -->|agents.create| ISS[Per-Issue Sessions
ctx.agents]
SVC --> SCHED
ISS --> SVC
classDef client fill:#3B82F6,stroke:#2563EB,color:#fff,stroke-width:2px
classDef service fill:#10B981,stroke:#059669,color:#fff,stroke-width:2px
classDef data fill:#8B5CF6,stroke:#7C3AED,color:#fff,stroke-width:2px
class UI client
class SVC,TOOLS,PLAN,SCHED,ISS service
class DB,WS data
The browser half never talks to storage directly. Every read and write goes through ctx.taskboard, whether the caller is the board's own RPC route, a model-facing tool, the planning loop, or the scheduler — so the two human gates (no self-approval, no self-acceptance) live in one place and apply to every caller. The scheduler is the only thing that starts work on its own, and it draws exclusively from todo, which only a human can put an issue into.
Configuration
Key
Default
Description
scheduler.concurrency
1
How many issues may run at once; changeable live from the board header
scheduler.autoPull
true
Whether the board pulls from todo on its own; changeable live from the board header
scheduler.sweepIntervalMs
30000
Safety-net sweep that frees slots occupied by vanished sessions
plan.subagentProvider
spawn
Fresh structured-output subagent provider used for every planning round
plan.maxRounds
32
Default AND ceiling for one taskboard_plan run; a call may lower it, never raise it
plan.maxHandoffChars
16384
Maximum serialized characters in one round's structured report; an oversized report fails the run instead of being truncated
plan.maxIssues
16
Maximum issues admitted into one planning run
API
The browser half talks to the host half over one endpoint, POST /_dsh/taskboard/rpc, with { method, params } in the body, rather than one REST path per resource. DeepSeek Harness's typed RPC layer requires build-time code generation this plugin's build does not run, so the route is deliberately explicit — see docs/spike-findings.md for why.
Method
Description
board.view
The board this session belongs to (resolved from its workspace), with live scheduler state
project.list
List every project
project.create
Create a project
task.list
List issues, optionally filtered by project, status, or session
task.get
Read one issue with its comments and activity trail
task.create
Create an issue
task.update
Change an issue; refuses a stale expectedVersion
comment.create
Add a comment to an issue
task.start
Open a FRESH session for one issue and hand it the work
task.startNext
Start the next todo issue — highest priority first — without naming one
task.accept
Accept finished work (in_review → done) — the human gate no agent can pass
task.sendBack
Send finished work back to todo with a reason (recorded as a comment), unbinding its session
scheduler.configure
Change concurrency or the auto-pull toggle; returns the resulting state
Change notifications stream over GET /_dsh/taskboard/events as Server-Sent Events.
Directory Structure
src/
├── client/ # Browser half
│ ├── board.tsx # BoardView: columns, cards, scheduler strip, approval + acceptance controls
│ ├── index.tsx # Client plugin entry, slot registration
│ ├── rpc.ts # fetch()-based RPC client + SSE subscription
│ └── styles.ts # Layout-only CSS; every color is a theme token
├── domain.ts # Zod schemas and the status machine
├── service.ts # ctx.taskboard: reads, writes, version CAS
├── rpc.ts # Host RPC route + SSE change stream
├── tools.ts # Model-facing taskboard_* tools
├── command.ts # /task human command
├── plan-loop.ts # taskboard_plan: the fixed planning loop
├── session-link.ts # Workspace resolution, per-issue sessions, the scheduler
├── skill.ts # Registers the manage-taskboard skill
├── actors.ts # Actor identity
├── wire.ts # Shared browser host RPC types
└── index.ts # Plugin entry: mounts every face
test/ # node:test suites
skills/manage-taskboard/ # Bundled working-agreement skill
docs/ # Extension-point research notes