deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
一个运行在 DeepSeek Harness (DSH) 里的任务面板插件:把「聊天气泡」升级成「任务流水线」。
| Tab | 状态 | 指示点颜色 | 含义 |
|---|---|---|---|
| 待领取 | todo |
灰 | 任务已登记,等待插件领取(或排队等待执行名额) |
| 待澄清 | clarify |
粉 | 规划代理发现需求不明确,产出问题清单,等待老板回答后定稿计划 |
| 待确认 | confirm |
琥珀 | 规划代理已产出实施计划,等待老板确认(仅当任务关闭「自动确认」时出现) |
| 开发中 | develop |
蓝 | 开发代理正在执行 |
| 暂停中 | paused |
橙 | 老板点「暂停」后进入;可「继续执行」恢复原阶段,或「重新编辑」调整方向 |
| 复核中 | review |
紫 | 自动复核通过(零遗留问题)后进入,等待老板验收 |
| 已完成 | done |
绿 | 老板验收通过 |
待验收的质量门槛:复核代理是老板验收前的最后一道关卡——有任何遗留问题即视为复核未通过(不允许「通过但带遗留问题」)。复核未通过时面板会自动把问题清单带回开发重试(最多 3 轮),超过上限后任务停在「复核中」并显示红色「不可验收」提示,由老板决定打回 / 重新复核 / 验收。因此出现在「复核中」Tab 的任务默认都是零问题、可验收的,卡片上有「可验收 / 有问题」徽标可一眼分辨。
每个阶段是任务状态机的一环,迁移由「自动读取器」或老板按钮驱动,见 §3。发布粗需求(方向型任务)时,规划代理会先澄清(产出问题清单进「待澄清」)再定稿,避免自行假设。
发布任务 ──▶ 自动蒸馏历史会话(匹配的旧会话自动挂到任务上)
│
├─ 自动领取 ──▶ 规划代理产出「实施计划 + 问题清单 questions[]」
│ │
│ ├─ 有澄清问题 ──▶ 待澄清 Tab:老板逐条回答(至少 1 个)
│ │ └─▶ 澄清定稿轮(结合回答重规划)──┐
│ └─ 需求清晰(questions 为空)──────────────────────────┤
│ ▼
│ 计划定稿:写入 OpenSpec 产物 specs/proposals/<任务id>/
│ ├─ 自动确认(默认) ──▶ 开发代理实施(按 tasks.md 逐项勾选)
│ └─ 需确认 ──▶ 待确认 Tab,老板点「确认计划」
│
├─ 开发完成 ──▶ 自动进入复核 ──▶ 复核代理对照验收标准 + tasks.md 逐项自检
│
└─ 复核通过 ──▶ 复核中 Tab ──▶ 老板点「验收通过」──▶ 已完成
└─ 老板点「打回开发」──▶ 带反馈重回开发
任意阶段(已完成除外)都可点「暂停」──▶ 暂停中 Tab
├─「继续执行」──▶ 恢复到暂停前状态(若暂停时正在执行,自动重踢对应阶段)
└─「重新编辑」──▶ 修改标题/描述/验收标准,旧计划与产物清空,按新方向重新生成
发布时的自动蒸馏(tasks.create 内部):
sessionQuery.searchSessions);relatedSessions —— 规划/开发代理开跑前会先读这些历史上下文,等于「接着上次的会话继续做」。面板里还有「扫描关联会话」按钮:发布前先检索,勾选你想挂载的历史会话,再发布。
index.js 的 buildPrompt){plan, steps, risks, questions}(steps 编号列出:做什么 / 涉及文件 / 如何验收),明确「不要开始实施」。tasks.md 逐项勾选;涉及 UI/页面/表单的任务必须做端到端验证并把关键界面截图保存到 <目标仓库>/specs/proposals/<任务id>/screenshots/,输出 {done, summary, changedFiles, screenshots, blocker}。adb exec-out screencap(Android 真机/模拟器)、xcrun simctl io(iOS 模拟器)或 idb screenshot / idevicescreenshot(iOS 真机)截真机/模拟器实际运行界面。截屏前先探测工具与设备:缺工具/无设备/未配对时如实报告(done=false + deviceStatus),任务停留在「开发中」,面板卡片显示「待接设备」徽标与按平台的安装/连接指引,老板接好设备后点「重新执行」即可重试;成功出图后走与 Web 截图完全相同的验收截图管道。{passed, issues, verdict, screenshots};有遗留问题即 passed=false(issues 为空才可通过),复核截图一并挂到任务。原生 App 任务由复核代理亲自截真机/模拟器运行界面核对,拿不到真实截图证据必须记为问题。各阶段都通过 outputSchema(JSON Schema)约束子代理的输出,结果结构化、可被读取器机械解析 —— 不靠猜文本。
规划代理发现以下任一不明确点时,必须在 questions 中向老板提问(每问一句话可答,why 说明为什么需要),不得自行假设:
存在问题时任务进入「待澄清」Tab,老板逐条回答(至少 1 个)后触发澄清定稿轮;需求清晰时 questions 为空数组,直接定稿。整个流程保证:粗方向 → 澄清 → 完整开发步骤 → 才动手。
计划定稿时,Host 在目标仓库写入 OpenSpec 风格产物:
<repoPath>/specs/proposals/<任务id>/
├── proposal.md # 背景与动机 / 目标与方案 / 风险 / 验收方式
└── tasks.md # 编号任务清单,开发代理每完成一项把 [ ] 改为 [x]
开发代理与复核代理的 prompt 都会引用 tasks.md(逐项实施 / 逐项核对),实现过程与验收都有仓库内可追踪的清单。目标仓库不可写时回退到面板目录,并在卡片上标注「(目标仓库不可写,回退于面板目录)」。
| 读取器 | 触发 | 行为 |
|---|---|---|
| 领取读取器 | 任务进入待领取且有空闲执行名额 | 启动规划代理;产出计划后自动流入下一步 |
| 开发读取器 | 规划完成(自动确认)或老板确认 | 启动开发代理;done=true 时自动转入复核 |
| 复核读取器 | 开发代理报告完成 | 启动复核代理;零遗留问题才停在「复核中」并点亮面板角标;有遗留问题则带问题清单自动打回开发(≤3 轮) |
| 恢复读取器 | 每 20s 巡检一次 | 检测到开发子会话已不在线(进程重启)时,在任务上标注「可重新执行」 |
并发控制:默认同一时间只跑 1 个开发任务,其余自动排队,队列在「待领取」Tab 可见。
位置说明:DSH 侧边栏「新会话」按钮下方是内置的会话浏览区(单一内置 Slot),插件没有可插入的槽位; 侧边栏底部
sidebar.footer.action是唯一可追加的入口,故按钮放在底部(设置上方)。如需真正置于「新会话」 下方,需要改动 DSH 自带的 Web 侧边栏源码,可作为后续工程化事项。
shell.overlay,不遮挡其它列交互):sessions.open,子会话优先按 subagentAddress + openSubagent 打开,失败回退 open。Q1/Q2 序号胶囊 + 15px 加粗的问题正文,why 说明退为 12px 次级灰行,作答框 14px 独立成行;区域标题右侧显示 「已答 x/y」 进度(全部答完转绿),已答的卡片整体转绿(含序号胶囊),输入或清空作答框即时更新进度;多个问题不再挤成一片 12px 小字。浏览器 (Client) DSH 进程 (Host)
───────────────── ─────────────────────────────
sidebar.footer.action 按钮 ──fetch/JSON─▶ webServer 路由 /dsh-task-panel/api/*
shell.overlay 抽屉面板 ◀── JSON 返回 ─── tasks-list / tasks-scan / tasks-create / tasks-action
验收截图 <img> ◀── 图片字节 ─────── webServer 路由 /dsh-task-panel/files/<taskId>/<name>
│
├─ sessionQuery.searchSessions 蒸馏历史会话
├─ subagents.start('spawn') 各阶段子代理
├─ fs (tasks.json) 持久化
├─ fs (specs/proposals/<id>/) OpenSpec 产物写入目标仓库(不可写时回退面板目录)
├─ fs/node:fs (screenshots/) 收集并下发验收截图
└─ timer.interval 恢复读取器
tasks.json 落在项目根目录(写入失败时退回 /tmp),进程重启后任务与时间线不丢。tasks.json —— 每任务含 id/title/description/acceptance/status/plan/steps/risks/questions/summary/changedFiles/reviewReport/relatedSessions/sourceSessionId/sourceCwd/repoPath/workSessionId/pausedFrom/pausedFromRunning/history/flags/autoRun/autoConfirm。index.js(Host 半部)、client.js(Client 半部,浏览器端静态 bundle)。task_publish 模型工具(在聊天框里直接「发布任务:…」)暂未接入。subagents.followup)。proposal.md + tasks.md;后续可对接 openspec CLI 做 proposal review 与 spec 归档(specs/<capability>/spec.md)。本目录即标准 DSH 插件包:index.js(Host 入口)、client.js(浏览器 bundle,__ModuleLoader__ 协议)、cordis.patch.yml(composition 行)、package.json(dsh.bundle + dsh.client 声明)。
~/.dsh/profiles/web/package.json:dependencies 增加 "dsh-task-panel": "link:<你的 dsh-task-panel 目录>",并在 dsh.profile.bundles 末尾追加 "dsh-task-panel";~/.dsh/profiles/web 执行 pnpm install;dsh web。index.js)或前端(client.js)后重启 dsh web 生效;tasks.json 是运行时数据(gitignored,插件会自动创建)。npm test(= node --test "test/*.test.js")。除纯逻辑单测外,test/clarify-card.render.test.js 会用极简 DOM 跑 client.js 的真实渲染代码,并(本机有 Chrome 时)用 headless Chrome 的 getComputedStyle 核对字号 / 字重 / 边框 / 配色等视觉验收点;无 Chrome 自动跳过。dsh web、不动真实 tasks.json):node devtools/render-clarify-card.mjs(结构核对)/ --measure(浏览器实测计算样式)/ --contrast(亮/暗两套主题的对比度实测,含 WCAG AA 判定)/ --png(输出到 screenshots/clarify-card/,同时落一份可直接打开的 .html 预览)。Chrome 路径可用 DSH_CLARIFY_CHROME 覆盖。POST /dsh-task-panel/api/tasks-list | tasks-scan | tasks-create | tasks-action。原因:DSH 的全文会话搜索默认是关闭的(opt-in)。dsh-base / dsh-web-app 两个 bundle 层把 session-query-sqlite 配成 openAt: never(path 为 :memory:),此时 ctx.sessionQuery 仍挂载,但 searchSessions / searchEvents 会直接抛 SESSION_QUERY_SEARCH_DISABLED,且 node:sqlite 不会被导入。任务面板的「自动蒸馏 / 扫描关联会话」调用 sessionQuery.searchSessions,因此报错(见 index.js 中 [task-panel] 检索失败:)。
修复:在 profile 的 patch 层(~/.dsh/profiles/web/cordis.patch.yml,在所有 bundle 层之后应用)覆盖该行 —— patch 会整体替换 config,所以要连同 path 一起重申:
- id: session-query-sqlite
config:
path: ~/.dsh/session-query/index.sqlite
openAt: first-search
openAt 取值:startup(服务激活时打开)/ first-search(推荐,推迟到首次搜索,Node 22 启动输出保持干净)/ never(关闭,默认)。path 建议用持久化路径;默认 :memory: 首次搜索时会从 JSONL 会话日志重建索引,但每次进程重启后都要重建。dsh web 生效,再点「扫描关联会话」或发布任务即可。原因:插件未安装或未在 profile 中启用。
排查:
~/.dsh/profiles/web/package.json 的 dependencies 含 "dsh-task-panel": "link:<你的 dsh-task-panel 目录>",且 dsh.profile.bundles 末尾含 "dsh-task-panel";~/.dsh/profiles/web 执行 pnpm install;dsh web 后刷新页面(侧边栏底部、设置上方应出现带角标的按钮)。含义:这是原生 App(iOS/Android)任务的开发代理想截真机/模拟器运行界面作为验收证据,但当前机器缺工具 / 没连设备 / iOS 真机未配对,任务因此停留在「开发中」。
处理:
adb(brew install android-platform-tools)并 adb devices 确认授权;iOS 模拟器确认 Xcode/simctl 并 open -a Simulator;iOS 真机安装 idb(brew install idb-companion + pipx install fb-idb)并让手机点「信任此电脑」);前置条件:dsh web 跑在开发者本机、手机(USB 或无线)直连这台机器;代理只能截到本机能连到的设备。
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。