Back to home

af2000-tech

dsh-taskboard-plugin

Taskboard plugin for DeepSeek Harness (DSH) — issue kanban with a sidebar board panel, a 13-command agent tool, and a managed self-contained local service

Stars
0
Language
JavaScript
Created
Aug 16, 2026
Updated
Aug 16, 2026

Introduction

dsh-taskboard-plugin

Issue kanban for DeepSeek Harness (DSH) — a sidebar board panel, an agent tool, and a managed local service, in one self-contained plugin.

As of 0.2.0 the package is fully self-contained: the Taskboard application (a zero-dependency, pure-Node issue-board service with its prebuilt web UI) is vendored inside the package under app/. Installing the plugin is all there is to install.

Features

  • Managed loopback service — the plugin supervises the vendored Taskboard server as a local subprocess bound to 127.0.0.1 only: spawn + /health wait (30s ready timeout), log forwarding, crash restart with exponential backoff (restartBackoffMs base, capped at 30s; gives up after 5 consecutive failures — service_start retries), and tree-kill of the whole process tree on plugin dispose (taskkill /T on Windows, process-group kill on POSIX). If a healthy Taskboard instance already owns the port, the plugin adopts it instead of spawning a second one and never kills adopted instances on stop/dispose (adoption requires Taskboard's /health JSON contract — a plain 200 responder is not adopted). The child environment is an explicit allowlist plus the TASKBOARD_* contract — never a full process.env inheritance.

  • taskboard agent tool — 13 subcommands via a single command parameter:

    • reads: project_list, project_get, issue_list, issue_get, comment_list
    • writes: project_map, issue_create, issue_update, issue_move, comment_add, relation_add
    • lifecycle: service_start, service_stop

    Writes are attributed to the current DSH session automatically (explicit threadId parameter wins, then the agent session id, then DSH_SESSION_ID; all three missing → the write is rejected). project_map binds a project to a local workspace path (a mutation, session-attributed like other writes). Issue writes use optimistic locking: omit ifVersion to reuse the latest version; an HTTP 409 VERSION_CONFLICT is surfaced verbatim so the agent can re-read and retry once. Issue statuses: backlog (not approved for execution), todo, in_progress, in_review, blocked, done, canceled.

  • Sidebar board panel — a sidebar footer entry opens an overlay panel with an iframe direct-connecting to http://127.0.0.1:<port>/. The panel shell follows DSH theme tokens (with fallbacks); the iframe's internal theme is the Taskboard app's own. When the service is down, the panel degrades to a "service not running" view with Retry and Open in system browser (bare loopback URL, no credentials).

  • Port/status channel — the client half resolves the actual port and supervisor status from a same-origin route registered on the GUI web server: GET /plugins/taskboard/config.json{ ok, port, status } (statuses: ready / adopted / starting / restarting / stopped / failed / disposed). If the route is unavailable, the panel falls back to the conventional default port 47823.

  • Runtime skill registration — the plugin registers a taskboard skill into the DSH skill registry at load and withdraws it on disable. It teaches agents the tool face (claim discipline, backlog = not approved, 409 retry-once, session attribution). A user-level skill file with the same name would shadow the runtime registration by name.

Install

Primary path — install from GitHub, then restart the GUI:

dsh plugin --profile <name> add github:af2000-tech/dsh-taskboard-plugin
dsh --profile <name>   # (re)start the GUI

The plugin graph is composed when the GUI boots: installing into a profile whose GUI is already running takes effect only after a GUI restart (verified contract). This repository commits its build artifacts (dist/, lib/), so installs need no build scripts and no build permission — nothing runs at install time.

The package is self-contained: no external taskboard checkout, no extra downloads. Data lands in ~/.dsh/taskboard/data by default (respects $DSH_HOME).

Alternative — tarball:

npm pack                                    # → dsh-taskboard-plugin-0.2.0.tgz
dsh plugin --profile <name> add file:<path-to-tgz>

Re-adding the same version is a no-op; run dsh plugin --profile <name> remove dsh-taskboard-plugin first when force-reinstalling a rebuilt tarball.

Configuration

FieldDefaultMeaning
port47823Taskboard service port (loopback only — always 127.0.0.1)
dataDir""SQLite data directory; empty = $DSH_HOME/taskboard/data (~/.dsh/taskboard/data without DSH_HOME)
autoStarttrueStart the service when the plugin loads; false defers to the first tool call or service_start
restartBackoffMs3000Crash-restart backoff base in ms (exponential, capped at 30s; gives up after 5 consecutive failures)
appRoot""Empty = the vendored app inside this package (normal path). Set to an external Taskboard app root (a checkout containing server/index.mjs) to run against it — an escape hatch, not the normal path

Whole-row restatement warning (cordis patch semantics): an entry in the profile's cordis.patch.yml that targets id: taskboard replaces the entire config row — it does not deep-merge with the bundle layer's config. When you override even one key (e.g. only port), restate every key you care about: omitted keys fall back to the schema defaults above, not to the bundle-layer values.

Architecture

Dual-half cordis plugin:

  • Host half (dist/host.js, ESM, peers external) — the TaskboardService supervisor, the taskboard tool registration, the same-origin status route, and the runtime skill registration (web server / skills services are injected lazily, so headless profiles load the plugin fine).
  • Client half (lib/client.js) — sidebar footer entry, overlay panel shell, and iframe. Resolves the service origin exclusively from the port channel; degrades to the retry / open-in-browser view when the supervisor is not ready/adopted.
  • Contract between the halves — the single same-origin JSON route (config.json) plus the conventional default port 47823; no cross-origin config access, no extra web-exposed surface. (The host also proxies one same-origin helper route, POST /plugins/taskboard/bind-task, used by the board UI to bind an issue to a conversation thread.)

Dependencies: the vendored app has zero npm dependencies (pure Node; it serves its prebuilt web UI from app/dist/web/). The host half uses only Node built-ins (child_process, fs, os, path, url); all plugin peer dependencies are provided by the DSH host at runtime — nothing is installed alongside the plugin.

Development

npm install
npm run build        # esbuild → dist/host.js + lib/client.js
npm run typecheck    # tsc --noEmit (strict)
npm run vendor       # re-sync the vendored app/ from a local checkout of the upstream Taskboard app

npm run vendor mirror-syncs server/, shared/, cli/, skills/, dist/web/, LICENSE, and PRIVACY.md from a sibling checkout of the upstream app into app/ (the source location is resolved inside scripts/vendor-app.mjs). After changing src/, rebuild and commit dist/ + lib/ — published installs must never need build scripts.

Credits

The vendored app under app/ is a fork of chuspeeism/dashi-taskboard, renamed Taskboard. Fork changes: the Codex-specific challenge/proof handshake and instance-token routes were removed, the environment prefix was changed from CODEX_* to TASKBOARD_*, and branding/docs were neutralized to Taskboard wording. The app ships under its own app/LICENSE and app/PRIVACY.md.

License

Apache-2.0.

中文简介

  • dsh-taskboard-plugin 是 DeepSeek Harness(DSH)的本地议题看板插件:侧边栏看板面板 + taskboard 代理工具 + 托管的本地服务,三位一体。
  • 插件完全自包含——Taskboard 应用(零 npm 依赖的纯 Node 服务 + 预构建 Web UI)已内置于包内 app/,安装即用,无需外部仓库。
  • 服务只监听 127.0.0.1,崩溃自动重启(指数退避封顶 30 秒,连败 5 次放弃),端口已被健康实例占用时自动收养;数据默认落在 ~/.dsh/taskboard/data
  • 工具面共 13 个子命令(项目 / 议题 / 评论 / 关系的读与写 + 服务启停),写入自动归属当前 DSH 会话,议题写入带乐观锁(409 VERSION_CONFLICT 原样透出,重读后至多重试一次)。
  • 安装:dsh plugin --profile <名称> add github:af2000-tech/dsh-taskboard-plugin,然后重启 GUI 生效。