使用dsh-dashboard在DeepSeek Harness里编排Linear与GitHub任务

前言

DeepSeek Harness(简称 dsh)是 DeepSeek 开源的 Agent 运行时,核心理念是「一切皆插件」:模型、工具、会话、沙箱、调度和界面都可以用插件替换或组合。官方仓库目前仍处于 developer preview,接口还会变。社区里有人把各类插件整理到独立站点 DeepSeek Harness 插件库,它和 DeepSeek / 幻方没有官方从属关系,安装命令要以目录页原文为准。

日常用 dsh 写代码时,真正花时间的往往不是打开一次会话,而是把 Linear、GitHub Issues、Jira 里已经排好的票,一张一张交给智能体,再盯着它跑完、失败重试、换工作区。OpenAI 开源的 Symphony 做的就是这件事:轮询任务源、为每张票建隔离工作区、按 WORKFLOW.md 派发 Agent,失败则退避重试。dsh-dashboard 把这套编排契约接到了 DeepSeek Harness 上,并且看板直接嵌在原生侧栏里,不必另开一套控制台。

下面介绍这个插件是什么、能做什么、怎么装、WORKFLOW.md 怎么写,以及使用时必须注意的边界。

这是什么

dsh-dashboard 是一个工作流与自动化插件,由 Uddoo 维护,仓库地址是 Uddoo/dsh-dashboard,许可证为 MIT,主要语言是 TypeScript。目录页收录于 2026-08-15,截至 2026-08-18,GitHub 星标为 3。npm 包当前版本是 0.7.0,仓库声明针对 DeepSeek Harness Web profile 0.1.0-rc.6 编译和测试。

一句话定位:它把 Linear、GitHub Issues、Jira Cloud、Asana、GitLab 或 Host 本地任务,转成相互隔离的 Harness Agent 运行,同时保留原生 shell、侧栏、会话、工具、模型选择和权限系统。

它复刻的是 Symphony 的编排契约,而不是把 Elixir/OTP 实现嵌进 dsh。README 写得很清楚:TaskSource 负责 Provider 边界,HarnessAgentRunner 把执行和续跑映射到 Harness 原生 session,看板则把运行观测信号做成 Linear 风格的 Board。上游参考是 openai/symphony

核心功能

插件能力可以分成任务源、调度、工作区和看板四块。

1、多任务源,但一份 WORKFLOW.md 只激活一个。支持 Linear 项目 Issue、GitHub 仓库 Issue(明确排除 Pull Request)、Jira Cloud 项目 Issue、Asana 项目 Task、GitLab 项目 Issue,以及不需要凭据的 Local 任务。切换 tracker.kind 之后,只有新工作流通过完整校验并热更新成功,看板上下文和调度来源才会跟着变。无效热更新会被拒绝,最后一个有效定义继续生效。

2、确定性调度。符合条件的任务按优先级、创建时间和标识符排序;可以要求必需标签;可以设全局并发,也可以按状态设并发。失败运行使用有上限的指数退避,每次派发前会重新核对任务源状态。Linear 的 blocks 关系和 Jira 的 “is blocked by” 在可用时会投影成 blocker。查询结果里暂时缺失的任务会停跑,但不会被当成终态,避免一次瞬时查询把工作区清掉。

3、每个任务一个持久工作区,并带生命周期 Hook。可配置 after_createbefore_runafter_runbefore_remove。Git 项目使用 detached worktree,非 Git 项目使用受控目录。自动任务领取始终关闭:注册或扫描到其他 Project,只是写入 Catalog,不会跨项目自己领票。

4、原生侧栏里的 Dashboard。通过 sidebar.footer.actionshell.overlay 挂上去,不替换现有侧栏。四个视图分别是 Board(列、筛选、任务详情)、Runtime(运行 / 重试 / 阻塞、turn、token、worker host)、Projects(持久化 Catalog、扫描确认)和 Configuration(最后有效 workflow、凭据健康、并发与 turn 上限)。标题旁的 Provider · Project 是动态上下文,例如 Linear · ENGGitHub · openai/exampleLocal · Personal

另外还有几条实现上的硬约束,写文章时不能略过:外部凭据始终留在受信任 Host,不会进入 Dashboard 的 RPC payload 或浏览器状态;浏览器只拿到受约束的状态投影,操作面是 Pause/Resume、Stop、Refresh、Catalog 以及 Local 任务维护;agentProfile.permissionPreset 必须显式填写,随包默认用已有的 workspace-write,无人值守编排不会静默抬权限。

安装与启用

运行环境按仓库 README:Node.js 22.19+24+;从源码构建时用 pnpm 11.19+;DeepSeek Harness Web profile 0.1.0-rc.6;还需要一个已经存在的 Harness permission preset。远程 Provider 需要对应凭据,Local 任务不需要。

目录页给出的安装命令如下,在 DeepSeek Harness 终端里运行即可:

dsh plugin add github:Uddoo/dsh-dashboard

目录页同时提醒:插件以当前 dsh 进程的权限运行,安装时可能执行代码。安装前请检查源代码仓库和许可证。如果需要可复现安装,按页面写法固定 commit 哈希:

dsh plugin add github:Uddoo/dsh-dashboard#commit

把上面的 commit 换成仓库里实际的提交哈希,不要用字面量 commit

GitHub README 还提供了 npm 包安装方式,并明确指定 Web profile 和版本 0.7.0。npm 包含预构建的 Host 与浏览器入口,不需要授予安装时构建权限:

dsh plugin --profile web add dsh-dashboard@0.7.0
dsh web --dump-config
dsh web

没有全局 CLI 时,可以用官方包拉起同一套命令:

npx --yes @deepseek-ai/dsh@0.1.0-rc.6 plugin --profile web add dsh-dashboard@0.7.0
npx --yes @deepseek-ai/dsh@0.1.0-rc.6 web --dump-config
npx --yes @deepseek-ai/dsh@0.1.0-rc.6 web

打开 dsh web 打印出来的地址,在原生侧栏选择 Dashboard。卸载:

dsh plugin --profile web remove dsh-dashboard

插件默认配置在包内的 cordis.patch.yml。Web profile 里至少要配当前项目根目录、WORKFLOW.md 路径,以及显式的 permission preset。下面是 README 中的覆盖示例(路径按仓库原文,开发验证主机是 Windows):

- id: dsh-dashboard
  config:
    currentProject:
      root: C:\work\my-project
      policyPath: WORKFLOW.md
      registerInCatalog: true
    agentProfile:
      id: default
      permissionPreset: workspace-write
      workerHost: workstation-01
    policyDefaults:
      pollingIntervalMs: 5000
      workspaceRoot: .dsh-dashboard/workspaces
      hookTimeoutMs: 60000
      maxConcurrentAgents: 10
      maxTurns: 20
      maxRetryBackoffMs: 300000

currentProject.root 是 Harness 选中的项目根;相对路径从 Harness 进程工作目录解析。agentProfile.id 必须和 WORKFLOW.md 里的 project.agent_profile 完全一致。discovery.roots 可以给 Catalog 指定受限扫描根目录,每项需要绝对路径,maxDepth 范围是 1 到 8;扫描到的候选未经确认不会写入 Catalog。

典型用法

先决定任务源。仓库给了完整示例:默认的 WORKFLOW.example.md 面向 Linear,另外还有 GitHub、Jira、Asana、GitLab 和 Local 各一份。version 当前必须为 1

不想接外部 Tracker 时,用 Local 最直接。下面摘自官方 examples/WORKFLOW.local.md

---
version: 1
project:
  name: personal
  agent_profile: default
tracker:
  kind: local
  provider:
    project_id: personal
    context_label: Personal
  required_labels: []
  active_states: [Todo, In Progress, Human Review]
  terminal_states: [Done, Canceled]
policy:
  polling:
    interval_ms: 5000
  workspace:
    root: .dsh-dashboard/workspaces
  hooks:
    timeout_ms: 60000
  agent:
    max_concurrent_agents: 3
    max_turns: 20
    max_retry_backoff_ms: 300000
  dashboard:
    visible_states: [Backlog, Todo, In Progress, Human Review]
---

Work on {{ issue.identifier }}: {{ issue.title }}.

{{ issue.description }}

Local 模式下,每个可见列标题会出现 Linear 风格的 +,可以直接建任务、改标题和描述、切状态、设优先级、删除。任务由 Host 侧 JSON 文件保存,默认路径是 ~/.dsh-dashboard/tasks.json,不走浏览器 localStorage。写入串行执行,用同目录临时文件再原子 rename。编辑会带上打开时的版本,Agent 或其他编辑器已经改过就会被拒绝。Dashboard 删除只去掉任务记录,已经存在的 Agent workspace 会留下来。

如果任务已经在 GitHub Issues 里,把 tracker.kind 换成 github,并填 ownerrepo。下面摘自官方 examples/WORKFLOW.github.md

tracker:
  kind: github
  provider:
    owner: your-org
    repo: your-repository
    context_label: ENG
    state_labels:
      Backlog: status:backlog
      Todo: status:todo
      In Progress: status:in-progress
      Human Review: status:review
      Done: status:done
  required_labels: []
  active_states: [Todo, In Progress, Human Review]
  terminal_states: [Done, Canceled]

GitHub 和 GitLab 用 state_labels 把工作流状态名映射到仓库标签。名称和某个已声明状态完全相同的标签也会被识别。没有匹配标签的打开 Issue 回退到第一个 active state,没有匹配终态标签的关闭 Issue 回退到第一个 terminal state。Jira 直接用原生 status 名;Asana 用任务所在 Section,已完成任务走第一个终态。

远程 Provider 的凭据只设当前用到的那一组。README 给出的环境变量名是:

  • Linear:LINEAR_API_KEY
  • GitHub:GITHUB_TOKEN
  • Jira Cloud:JIRA_EMAILJIRA_API_TOKEN
  • Asana:ASANA_ACCESS_TOKEN
  • GitLab:GITLAB_TOKEN

也可以把同名引用写进 $DSH_HOME/.credentials.yaml。不要提交这个文件,也不要把真实 token 写进日志。Configuration 视图只显示引用名称、是否已配置、凭据来源,不会把密钥送到浏览器。

Prompt 部分用 Liquid 模板。可以引用 issue.identifierissue.titleissue.descriptionissue.stateissue.labelsissue.url 以及重试次数 attempt。Agent 在配置的 max_turns 内续跑同一个 Harness session;attempt 有值时,官方示例会要求从当前工作区和会话接着做,而不是把已经完成的调查重来一遍。

生命周期 Hook 在任务工作区里作为受信任的本地命令运行,审核标准应当和构建、部署脚本一样。当前项目是 Git 仓库时,after_create 执行前工作区已经是 detached worktree,不要在 Hook 里再 clone 一次。非 Git 项目拿到的是受控空目录,需要初始化就写在 after_create 里。after_create 失败会删掉不完整工作区,方便下次重新初始化;before_remove 结束后还会再解析一次删除目标,Hook 期间 root 或目标变了就不会清。

适用场景与注意事项

适合已经在用 DeepSeek Harness Web UI,并且希望按任务源状态自动派发 Agent 的人。典型用法有三类:

1、团队票在 Linear / Jira / Asana / GitLab,希望按状态列把「该跑的票」交给隔离工作区里的 Agent,并在同一个 Harness 界面里看 turn、token 和阻塞原因。
2、仓库用 GitHub Issues 做任务板(注意:Pull Request 不在任务范围内),用标签映射 Todo / In Progress / Review。
3、先不接外部系统,用 Local 看板自己建票,验证 WORKFLOW.md、Hook 和并发限制。

使用前有几条边界必须看清楚。

插件以当前 dsh 进程权限运行。目录页和 README 都要求安装前检查源码与许可证。Hook 能在工作区里执行本地命令,权限模型上应当按「这段脚本会出现在构建流水线里」来审查。

兼容性声明比安装命令更严。package.json 对多数 Harness peer 的范围是 >=0.1.0-rc.5 <0.2.0,但 Project Catalog 依赖的 dsh-storage / dsh-storage-domain 要求 >=0.1.0-rc.6 <0.2.0,完整运行基线是 Web profile 0.1.0-rc.6。仓库明确说:不能只凭 semver 假定兼容 rc.7 或后续 0.1.x,需要重新 typecheck、测试、打包,并在隔离的 DSH_HOME 里做一次安装和 smoke test。未声称兼容 <rc.6>=0.2.0

开发与验证主机是 Windows。兼容性文档写明:未声称已在 Linux / macOS 上完成 Hook、符号链接和路径清理的实机测试;实现里保留了跨平台路径逻辑,但实机证据目前停在 Windows。Workspace root 和任务目录必须是真实目录,不能是符号链接。

远程 Provider 的自动化测试用的是 mock API。仓库未声称已用真实 GitHub、Jira、Asana、GitLab 凭据做过写入或长期无人值守 burn-in,真实凭据要由部署者自己验证。GitHub 任务范围是 Issue,不含 Pull Request。

执行面始终绑在 Harness 选中的 currentProject 上。Catalog 可以登记多个 Project,但自动领取保持关闭,不会自己跨项目抢票。这和「打开看板就能同时喂一堆仓库」不是一回事。

小结

dsh-dashboard 解决的是 dsh 里一张一张手工喂票的问题:用 WORKFLOW.md 描述任务源、状态、并发和 Prompt,由 Host 侧编排器按规则派发隔离的 Harness Agent,看板仍留在原生侧栏。它受 Symphony 启发,但跑的是 Harness 自己的 session、权限和 UI slot,而不是另一套 Elixir 运行时。

社区插件目录页:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-dashboard/

源码与完整配置说明:https://github.com/Uddoo/dsh-dashboard

安装前先看许可证和源码,需要可复现环境时固定 commit 或 npm 版本 0.7.0,并把 Harness 版本对到仓库声明的 0.1.0-rc.6

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜