前言¶
OpenSpec 擅长把变更拆成 proposal、tasks、archive 等规格步骤,但规格本身不执行。主会话若自行判断「哪张票算完成」,容易与任务清单脱节,子智能体的自由文本输出也难以当作可核验的成功依据。下面介绍 Lumos-789 维护的 DSH 插件 Baton:它把已批准的 OpenSpec 变更转成可执行的 ticket/DAG,用本地 Python CLI 给出确定性动作,主会话只机械转发,成功仅以 sealed receipt 为准。
这是什么¶
Baton 是覆盖 OpenSpec 变更的 ticket / DAG / session-subagent 控制面。一句话定位:OpenSpec 是计划面,SessionController 是唯一确定性调度器,主会话是指挥棒下的机械转发者。 插件在 SkillHub 分类为工作流;仓库为 Lumos-789/baton,DSH 包名为 dsh-openspec-baton(与无关的 dsh-baton 区分),当前 package 版本为 0.3.0,许可证 MIT。
它解决的核心问题是:把已批准变更 deterministically 跑完——主会话不自行决定 ticket 状态,只按 Baton CLI 返回的 actions 原样交给 DSH subagent,再用 sealed receipt(任务包哈希 + 干净 worktree 上 HEAD 前进 + 验证命令 exit 0)对账完成通知;无 receipt 的完成会记为 unknown 并走 recover。Free-text 子智能体输出不参与成功判定。
核心功能¶
三条接缝的确定性桥接¶
| 接缝 | Baton 的做法 |
|---|---|
| 依赖(章节顺序 DAG → 下一步跑什么) | SessionController.actions() 每次重算 frontier,并原子认领不同任务 |
| 并发(最多 5 个并行任务) | 每个 assignment 一个隔离 git worktree;集成由仓库级锁串行 |
| 状态(子智能体完成 → 任务 resolved) | sealed receipt 是唯一成功证据;集成分支、finalize attempt、在 tasks.md 把对应项标为 [x] |
Session-subagent 执行(唯一路径)¶
- 确定性调度:认领、租约、worktree、receipt 校验、集成、完成均由脚本驱动,模型不决定状态。
- 隔离 worktree:每个 assignment 一条分支;容量滑动窗口
<=5;集成串行加锁。 - Sealed receipts:
scripts/receipt.py的 verify / seal 是唯一接受的成功证据(本地完整性证据,非对抗性密码学证明)。
控制面与可观测¶
- OpenSpec 原生认知阶段:「用 baton 做完 X」意味着先走项目 OpenSpec 流程(对齐 → 写变更 → 用户批准),再驱动执行至
complete。 - 活计划 = 编辑 tasks.md:运行中增删任务或章节时,下一次
actions()记录新 plan revision 并重算 frontier;在途 Task Packet 保持不可变。 - 看板:
scripts/ticket_board.py生成纯静态 HTML Kanban(无进程、无端口),输出在.dsh/baton/下,可用file://打开。
Bundle 主要路径包括:skills/baton/SKILL.md(baton skill)、scripts/session_control.py(actions / bind / reconcile / status / cleanup)、持久化计划存储 .dsh/baton/queue.db 等。
安装与启用¶
Baton 是 DSH bundle:挂载 baton skill,执行经 bundled Python CLI scripts/session_control.py。需要 DSH 0.2.1-rc.2 或更新(package.json 约束为 >=0.2.1-rc.2 <0.3.0)、提供 subagent 工具的 profile(随附的 dsh-base 即可)、以及 Python 3.10+ 在 PATH 上(或通过 BATON_PYTHON 指定)。
官方安装方式如下(勿自行拼接 github:owner/repo 形式):
# 本地 checkout
dsh plugin add /path/to/baton
# 发布后
dsh plugin add dsh-openspec-baton
自检 bundle(仅需 python3 + git,对临时 git 仓库驱动真实 CLI,健康时 exit 0):
python3 tests/cli_smoke.py
# CLI SMOKE PASS: actions dispatch, status snapshot, error exit - all green
插件以当前 DSH 进程权限运行;安装前请阅读仓库源码与 MIT 许可证,确认与你的工作流和合规要求一致。
典型用法¶
1. 准备 OpenSpec 变更与 tasks.md¶
在业务项目中按项目惯用的 openspec/AGENTS.md 流程编写变更并获批准,例如:
openspec/changes/<change-id>/proposal.md 与 tasks.md(未勾选的 N.M 任务)。
tasks.md 是 ticket 源:章节表示阶段,任务带 N.M id;较早章节中的任务会阻塞后续章节(同章内可并行)。最小形态示例:
# Tasks: add-login
## 1. Backend
- [x] 1.1 token endpoint
- [ ] 1.2 session persistence
## 2. Frontend
- [ ] 2.1 login form
[x] 表示已 resolved,[ ] 表示 ready;精确解析规则见仓库 docs/ticket-format.md。
2. 在会话中驱动 Baton¶
对会话说明:
run baton on <project_path> <change-id>
Skill 会循环:actions → subagent → bind → 完成通知 → reconcile,直到 batch 返回 complete。
架构上,主会话调用例如:
session_control.py <project> <change> actions --session-id ... --capacity<=5
返回 dispatch / recover / resolve_merge / wait / blocked / complete 等动作;绑定子智能体 id 后,在 reconcile 阶段用 --agent-terminal 等对账 sealed receipt。
3. 可选:生成 ticket 看板¶
python3 scripts/ticket_board.py build-all /path/to/project
# → .dsh/baton/board-all.html
python3 scripts/ticket_board.py build /path/to/project <change-id>
# → .dsh/baton/<change-id>/board.html
项目仅有一个 change 时,build / scan 可省略 <change-id>;零个或多个 change 时会明确报错并列出候选。
适用场景与注意¶
适合谁:已在用 OpenSpec 管理变更、且 DSH profile 具备 subagent、希望在规格与执行之间用同一粒度(约 one assignment ~ one task)做确定性编排的团队或个人。
注意:
- 集成 merge 冲突会保留,不会自动 abort。
- 并发上限为 5;集成始终串行。
- 同一仓库还提供 ZCode 插件形态(
.zcode-plugin/plugin.json),挂载相同 skill 与同一 CLI;DSH 用户以上述 bundle 安装为准。 - DSH 社区目录(如 SkillHub)是独立站点,与 DeepSeek / 幻方无官方从属关系;星标与发布状态以 GitHub 与目录页为准。
结尾¶
Baton 把 OpenSpec 已批准变更变成可核验的完工路径:调度 deterministic、worktree 隔离、成功只看 sealed receipt。若要进一步了解参数与内部命令,以仓库 README 与 docs/ 为准。
- 目录页:https://www.skillhub.cn/plugins/Lumos-789/baton
- GitHub:https://github.com/Lumos-789/baton