DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

KarBurKi /

KarBurKi/dsh-flow

Verified

跨会话流程编排:四角色(统筹/预研/开发/测试)的派单、独立验收、需求比对、终审把关、归档闭环。DSH 插件,零依赖。

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@ca0338ca

dsh-flow

跨会话流程编排:让四个角色(统筹 / 预研 / 开发 / 测试)在 DSH 里配合走完一条活——派单、实现、独立验收、需求比对、终审把关、归档,然后回到起点开下一条。

和剧场插件(dsh-theater)无关:不 import、不依赖、不共用数据。投递是自己实现的(agent.steer + 等 turn/end),插件里也没有任何剧本逻辑。


解决什么

多会话协作时,两件事最容易坏:

  • 「自己验自己」:开发写完自测通过,就等于「做完了」。没有第二双眼睛,边界没人报。
  • 流程全靠人记:派了谁、到哪一步、卡在哪,散在各个会话的脑子里。换一天就接不上。

dsh-flow 把「一条活怎么走完」固成工具:任务卡是文档(正本),状态写在 YAML 头里,每一步都有工具管。人和会话都不用记流程,照卡走就行。


角色与流程

                        ┌─────────── 回到起点(下一轮)────────────┐
                        ▼                                            │
预研 ─提需求/选型─► 统筹 ─建卡、拆解、派单─► 开发 ─实现、自测、push、回执─┤
                     │                                              │
                     └──派验收──► 测试 ─独立验收、出报告、报边界──► 统筹 ─需求比对、终审、归档
角色 干什么 不干什么
统筹 拆解、建卡、派单、派验收、需求比对、终审把关、汇总、归档 不自己动手实现;不替别人拍板
预研 提需求、写预研说明、选型 不直接改实现
开发 认领、实现、自测、push、回执 不自验——自测通过不等于验收通过
测试 独立验收、出报告、报边界 不替开发改代码;不接「边改边验」

闭环一句话:预研 → 统筹(建卡/拆解)→ 开发(做)/ 测试(验)→ 统筹(需求比对、终审把关,不过就再走一轮开发)→ 统筹(汇总/归档)→ 回到起点。

五个坎:派单 → 认领 → 回执 → 独立验收 → 终审。少一个,这条活就不算闭环。


流程原理(平台无关)

这套流程不绑 DSH。拆开看只有五个抽象——角色 / 任务卡 / 状态机 / 投递 / 归档,换到飞书、GitHub Issues、Notion 或者自建系统,照着都能复刻。

三条不变量换平台也不能改:

  1. 卡是正本:状态、派单记录、验收结论都在卡上;聊天和看板只是视图。
  2. 开发不自验:做的人不判自己。这条松了,整个流程就没有意义了。
  3. 关闭要有通过的验收:没有验收的 done 是耍赖。

完整原理——八拍时序(每拍的输入/产出/判据/失败怎么办)、状态转移表、换平台映射表、最小实现清单、复刻成功的判据——见 docs/流程原理.md。


工具

工具 干什么
flow_roles 登记 / 查看四个角色对应的会话 id;action=set 用逗号分隔可一次登记多个会话(多实例,例如三个测试)
flow_start 建任务卡:写 YAML 头(from/to/type/ticket/status/created),status=pending,投给统筹
flow_dispatch 统筹派单:卡状态 pending → processing,记一笔派单,投给开发 / 测试;写 toSession(完整会话 id)优先于 to 角色名;顺手把下一站写进卡头 downstream(不填按 to 推导:开发→测试、测试→统筹)
flow_submit 开发交卡:processing → waiting_verify,追加「## 交付记录」,自动挑一个空闲测试(名下没有在途卡)投过去;都忙就停在 waiting_verify 报「排队」
flow_ask 开发遇需求对不上、不确定时不许猜:卡 processing → blocked,追加「## 疑问」,投统筹决策
flow_answer 统筹答复疑问:blocked → processing,追加「## 决策」,投回开发;决策留卡里供追溯
flow_verify 测试回执:把「通过 / 不通过 + 报告路径」写进卡;不通过投回开发(同一张卡最多自动退 2 次,第 3 次转 waiting_human 人工裁定;此状态下再调会直接报错,要先由统筹 flow_dispatch 放行)。先投递再记账,投递结果分三档见下。dryRun:true 只算不改:不改卡、不投递、不写登记单、不占分配时间,返回 wouldBeStatus / wouldDeliverTo / rejectsLeft,给测试验流程用
flow_close 归档:状态改 done、移到【归档区】<类型>\<YYYY-MM>\、移动前后核对 SHA-256
flow_run 一键封顶:读一张卡按状态自动推进,失败停下报原因
flow_status 读全局会话状态表,汇总「活跃 N / 待机 M」+ 明细;only 可只看活跃或待机

状态机(0.2.7)

pending → processing → blocked → waiting_verify → waiting_final → done
              ▲            │            │
              └─ answer ───┘            │
              └────── 不通过返工 ────────┘

waiting_verify ──连退满 3 次──> waiting_human ──统筹 flow_dispatch 放行──> processing
状态 谁在手上 怎么离开
pending 等派单(统筹) flow_dispatch → processing
processing 开发在做 flow_submit → waiting_verify;flow_ask → blocked
blocked 等统筹答复疑问 flow_answer → processing
waiting_verify 测试在验(或排队中) flow_verify 通过 → waiting_final;不通过 → processing(回开发;连退满 3 次 → waiting_human)
waiting_human 连退超限,等人工裁定 统筹 flow_dispatch 派单 → 转回 processing(等于放行);此状态下不能再 flow_verify
waiting_final 等统筹终审 flow_close → done(归档)
done 归档区 终态

卡头的 to_session 记的是当前持有人,挑空闲测试就靠它判断「谁手里有在途卡」。

数据在哪

  • ~/.dsh/plugins/dsh-flow/config.json — 工作区路径、任务卡目录、归档目录、四个角色的会话 id。
  • 任务卡 — 在 config.workspace + config.tasksDir 下(workspace 默认为空,首次使用前必须配成本机工作区路径;tasksDir 默认 【文档区】\计划与任务)。
  • 归档 — 在 config.workspace + config.archiveDir 下,按 <类型>\<YYYY-MM> 分。
  • 派活登记单 — 【文档区】\进度\派活登记.md(即 tasksDir 的同级 进度/ 下),一行一条:时间 | 谁 | 任务 | 状态 | 摘要。flow_dispatch / flow_submit(含排队)/ flow_verify / flow_close 各自追加;只追加不重写,写失败不影响主流程——但不再静默:会 console.error 并往插件目录 _dispatch-error.log 落一条完整堆栈,排查「登记单没写」先看它。登记单的「谁」列默认取卡头 to_session;手工建的卡没有这一栏,交卡时传 flow_submit({ "session": "session-…" }) 补上。
  • 投递结果分三档(flow_verify / flow_submit 都按这套):delivered(reply 正常返回)、timeout(超时,不确定)、failed(reply 里是 not-found / 不存在 这类,明确没送到)。超时按「当它送到了」处理——照常 touchAssigned、卡头写 target、登记单记「…(投递超时,未确认)」;因为漏记分配时间的伤害比多记一次大。只有 failed 才回滚卡头、不占分配时间、记「投递失败(未送达)」。返回体里有 outcome 字段,三档一眼可辨。
  • 为什么超时不等于没送到:theater_say 超时的消息通常已经送达,只是对方没在 timeoutMs 内回。2026-10-25 实测:往开发投「请重做」,对端真收到了,但当时按「未送达」记账,对端和白纸黑字的登记单对不上。
  • 假派活:明确失败(会话不存在)时不会有「开发收到请重做、去看卡已没了」这种事。这种卡头 to_session 会回滚成原持有人,不留指向死会话的指针;lastAssigned 也不动,轮转挑人不受影响。要复现:把 config.json 里某个角色临时指到不存在的会话,跑 flow_verify / flow_submit,看登记单记的是不是「投递失败(未送达)」,跑完记得还原。
  • ~/.dsh/会话状态.md — 全局会话状态表,所有会话共用一张,不由本插件维护也不归本插件。flow_status 只读它,汇总「活跃 / 待机」;这张表是判断「现在能不能重启宿主」的依据。

安装

  1. plugin 目录已有(~/.dsh/plugins/dsh-flow/)。

  2. 在 profile 的 package.json 里挂上:

// ~/.dsh/profiles/<profile>/package.json
"dependencies": { "dsh-flow": "link:<home>/.dsh/plugins/dsh-flow" },
"dsh": { "profile": { "bundles": ["...", "dsh-flow"] } }
  1. 建 junction(PowerShell):
New-Item -ItemType Junction -Path "$env:USERPROFILE\.dsh\profiles\<profile>\node_modules\dsh-flow" `
  -Target "$env:USERPROFILE\.dsh\plugins\dsh-flow"
  1. 重启 DSH(Host 只在启动时加载插件一次)。改了 lib/*.js 必须重启才生效,改 config.json 不用。

  2. 登记四个角色:

flow_roles({ "action": "set", "role": "统筹", "sessionId": "session-abcdefgh-…" })
flow_roles({ "action": "set", "role": "开发", "sessionId": "session-abcdefgh-…" })
// 预研、测试同理
flow_roles({ "action": "get" })   // 看现状

sessionId 必须带 session- 前缀。只传 uuid 会报 session/not-found。


一键 vs 分步

场景 用哪个
想盯着每一步、每一步都能改主意 分步:flow_start → flow_dispatch → flow_verify → flow_close
卡已经写好,只想让它往前走 一键:flow_run
卡在哪一步说不清 flow_run 先用 maxSteps: 1 探一步,看返回的 steps

flow_run 的推进逻辑:

  • pending → 派给开发
  • processing、卡里没有「## 验收」段 → 请测试验;测试把结论写进卡后,下一圈才继续
  • processing、卡里有验收段 → 关闭归档
  • done → 结束

中途失败就停,返回 steps 和 stopped 说明卡在哪。它不会替你改实现、也不会替你编验收结论。


完整案例:从预研提需求到归档

场景:预研发现缺一个「视频录制」能力,提给统筹;统筹拆成两单(开发 + 测试);开发做出 0.1.0;测试独立验收;统筹终审、比对需求,收口归档。

第 1 步 · 预研提需求

预研会话里:

flow_start({
  "title": "视频录制插件",
  "summary": "录屏录制",
  "from": "预研",
  "to": "统筹",
  "requirement": "需要一个能把屏幕/会话录成 mp4 的插件:开始、停止、存到交付区。依赖尽量少。",
  "criteria": "1) flow 工具能起录、停录;2) 产物是能播的 mp4;3) 空 PATH 能跑或写清依赖。"
})

结果:

  • 卡落地:【文档区】\计划与任务\任务卡_视频录制插件_录屏录制_NA_20261025.md
  • YAML 头:from: 预研、to: 统筹、type: 任务卡、ticket: NA、status: pending
  • 统筹被投递叫醒(投递正文包在代码块里,语音不会念)

第 2 步 · 统筹建卡、拆解、派单

统筹看卡后拆成两条:

  • 实现单 → 开发
  • 验收单 → 测试
// 派给开发
flow_dispatch({ "card": "任务卡_视频录制插件_录屏录制_NA_20261025.md", "to": "开发", "toSession": "session-1d314539-…",
                "note": "按卡实现到 0.1.0,自测后 push,回执写在卡末" })
  • 卡状态:pending → processing
  • 卡里多一行:> 派单 → 开发(2026-10-25 14:20):按卡实现到 0.1.0,…
  • 开发被叫醒

第 3 步 · 开发实现、回执

开发照卡做,做完在卡末尾写 ## 回执(改了什么 / 验了什么 / 版本 / push SHA),然后:

flow_dispatch({ "card": "任务卡_视频录制插件_录屏录制_NA_20261025.md", "to": "测试",
                "note": "实现完了,请独立验收" })

第 4 步 · 测试独立验收

测试只看任务卡的验收标准,不看开发写的回执结论:

flow_verify({ "card": "任务卡_视频录制插件_录屏录制_NA_20261025.md",
              "pass": true,
              "report": "【文档区】\\测试文档\\测试报告-视频录制插件-20261025.md",
              "note": "三条判据全过;边界:没测长录制(>30 分钟)" })
  • 卡里追加 ## 验收(2026-10-25 15:02),结论「通过」,报告路径,备注
  • 不通过时 pass: false,卡会投回开发重做

第 5 步 · 统筹汇总、归档

统筹先做需求比对与终审:功能跟需求对不对得上、有没有 BUG、有没有小改大收益的优化点——不过就出方案再走一轮开发;通过了才汇总给主人,然后:

flow_close({ "card": "任务卡_视频录制插件_录屏录制_NA_20261025.md" })
  • 状态:processing → done
  • 文件移到:【归档区】\任务卡\2026-10\任务卡_视频录制插件_录屏录制_NA_20261025.md
  • 移动前后 SHA-256 一致才返回成功

一键版

上面五步如果不想一步步点:

flow_run({ "card": "任务卡_视频录制插件_录屏录制_NA_20261025.md" })

它会:派开发 → 请测试验(等测试把结论写进卡)→ 关闭归档,每步都记在返回的 steps 里;哪一步没成,stopped 会说明。


验证边界

单测

  • 分步闭环、拒绝路径、flow_run 分步推进:历史自测脚本 21 项全过(模板工作区,跑完还原 config)。
  • 段落拼接:_selftest_section.mjs 10 项全过(0.2.5 起)。
  • 宿主内实际加载:2026-10-25 重启后工具出现在真实工具列表。前提是每个工具的 schema 必须带 additionalProperties: false 和 output——缺了宿主会把整行静默判成「启动失败」,工具不出现但也不报错。

真实会话闭环

  • 0.2.0(2026-10-25,开发 3 / 测试 3 六条独立会话跑四张卡):flow_roles get 多实例显示正常;flow_submit 四次交卡都由工具挑人,两个不同测试先后接到卡;全链路四遍走通无人工补位;旧单值配置回归正常。
  • 0.2.5:waiting_human 用真卡验——连退第 1、2 次回 processing,第 3 次转 waiting_human,第 4 次 flow_verify 直接被拒;flow_dispatch 放行后回 processing,再验通过进 waiting_final。验收段四段都两换行、段内不粘连。另有独立测试会话按四条判据复核通过。
  • 0.2.6:dryRun 硬条件——同一张卡跑前跑后 SHA-256 不变、登记单不增行、lastAssigned 一字不差;wouldBeStatus / wouldDeliverTo / rejectsLeft 与真跑一致;waiting_human 下 dryRun 同样被拒(闸门与真跑同源);flow_submit 投递失败回滚卡头、不占分配时间;resolveCard 找不到卡时带 dryRun 提示。
  • 0.2.7:三档复查——timeout 档 outcome=timeout、卡头写 target 不回滚、lastAssigned 确实变动、登记单记「投递超时(未确认)」;failed 档(死号)卡头回滚、死号不进 lastAssigned、记「投递失败(未送达)」。判据 6 的连退 1/2/3 递增不跳号、通过进 waiting_final 一并复查。
  • 现场共造 9 张一次性假卡(dryRun / submit / waiting_human / 连退回归 / 通过 / 判据 CD 等),验完全部清掉,config 临时改动均已还原。

没验的(先当不能)

  • flow_submit 的 timeout 档:跟 flow_verify 同一套判定,但没单独实证。
  • failed 档的字面量匹配:靠 /not-found|不存在/i 认,宿主换措辞会漏判成 timeout,届时同步改正则。
  • 排队路径:交卡时刻一直错开,pickFree 返回 null 那条没在真实会话跑过。
  • 疑问回传:flow_ask / flow_answer 一次都没走到。
  • 挑人轮转:只验了「不是固定第一个」,没验连续多轮是否真按最久未派轮转。
  • 跨工作区(config.workspace 指到别处)、同名卡片、卡被归档后再被 flow_run 指到。

样本:单机、Windows 宿主、9 张假卡 + 6 条真实会话;不是端到端演练。0.2.6 的 timeout 档是拿生产 config 直接投到真开发身上验的——方式不合规,结论可采信。

—/ 5

No ratings yet

Verified DSH bundle

Commit ca0338caaa40

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout