clawspec 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +908 -0
  2. package/README.zh-CN.md +914 -0
  3. package/index.ts +3 -0
  4. package/openclaw.plugin.json +129 -0
  5. package/package.json +52 -0
  6. package/skills/openspec-apply-change.md +146 -0
  7. package/skills/openspec-explore.md +75 -0
  8. package/skills/openspec-propose.md +102 -0
  9. package/src/acp/client.ts +693 -0
  10. package/src/config.ts +220 -0
  11. package/src/control/keywords.ts +72 -0
  12. package/src/dependencies/acpx.ts +221 -0
  13. package/src/dependencies/openspec.ts +148 -0
  14. package/src/execution/session.ts +56 -0
  15. package/src/execution/state.ts +125 -0
  16. package/src/index.ts +179 -0
  17. package/src/memory/store.ts +118 -0
  18. package/src/openspec/cli.ts +279 -0
  19. package/src/openspec/tasks.ts +40 -0
  20. package/src/orchestrator/helpers.ts +312 -0
  21. package/src/orchestrator/service.ts +2971 -0
  22. package/src/planning/journal.ts +118 -0
  23. package/src/rollback/store.ts +173 -0
  24. package/src/state/locks.ts +133 -0
  25. package/src/state/store.ts +527 -0
  26. package/src/types.ts +301 -0
  27. package/src/utils/args.ts +88 -0
  28. package/src/utils/channel-key.ts +66 -0
  29. package/src/utils/env-path.ts +31 -0
  30. package/src/utils/fs.ts +218 -0
  31. package/src/utils/markdown.ts +136 -0
  32. package/src/utils/messages.ts +5 -0
  33. package/src/utils/paths.ts +127 -0
  34. package/src/utils/shell-command.ts +227 -0
  35. package/src/utils/slug.ts +50 -0
  36. package/src/watchers/manager.ts +3042 -0
  37. package/src/watchers/notifier.ts +69 -0
  38. package/src/worker/prompts.ts +484 -0
  39. package/src/worker/skills.ts +52 -0
  40. package/src/workspace/store.ts +140 -0
  41. package/test/acp-client.test.ts +234 -0
  42. package/test/acpx-dependency.test.ts +112 -0
  43. package/test/assistant-journal.test.ts +136 -0
  44. package/test/command-surface.test.ts +23 -0
  45. package/test/config.test.ts +77 -0
  46. package/test/detach-attach.test.ts +98 -0
  47. package/test/file-lock.test.ts +78 -0
  48. package/test/fs-utils.test.ts +22 -0
  49. package/test/helpers/harness.ts +241 -0
  50. package/test/helpers.test.ts +108 -0
  51. package/test/keywords.test.ts +80 -0
  52. package/test/notifier.test.ts +29 -0
  53. package/test/openspec-dependency.test.ts +67 -0
  54. package/test/pause-cancel.test.ts +55 -0
  55. package/test/planning-journal.test.ts +69 -0
  56. package/test/plugin-registration.test.ts +35 -0
  57. package/test/project-memory.test.ts +42 -0
  58. package/test/proposal.test.ts +24 -0
  59. package/test/queue-planning.test.ts +247 -0
  60. package/test/queue-work.test.ts +110 -0
  61. package/test/recovery.test.ts +576 -0
  62. package/test/service-archive.test.ts +82 -0
  63. package/test/shell-command.test.ts +48 -0
  64. package/test/state-store.test.ts +74 -0
  65. package/test/tasks-and-checkpoint.test.ts +60 -0
  66. package/test/use-project.test.ts +19 -0
  67. package/test/watcher-planning.test.ts +504 -0
  68. package/test/watcher-work.test.ts +1741 -0
  69. package/test/worker-command.test.ts +66 -0
  70. package/test/worker-skills.test.ts +12 -0
  71. package/tsconfig.json +25 -0
@@ -0,0 +1,914 @@
1
+ # ClawSpec
2
+
3
+ [English](./README.md)
4
+
5
+ ClawSpec 是一个把 OpenSpec 工作流嵌入 OpenClaw 聊天窗口的插件。它有意把“项目控制”和“执行触发”分成两层:
6
+
7
+ - `/clawspec ...` 负责 workspace、project、change、恢复状态等直接控制。
8
+ - `cs-*` 关键字负责在当前聊天里触发工作。
9
+ - `cs-plan` 在当前可见聊天回合里执行 planning sync。
10
+ - `cs-work` 通过 watcher + ACP worker 在后台执行实现,并把简短进度消息回推到聊天窗口。
11
+
12
+ 这样做的目的,是让 OpenSpec 既保持聊天式体验,又不会把长时间实现任务硬塞进主聊天回合里。
13
+
14
+ ## 一眼看懂
15
+
16
+ - workspace 按 chat channel 记忆,不是全局只有一个。
17
+ - 每个 chat channel 只维护一个活动 project。
18
+ - 同一个 repo 在所有 channel 中只允许存在一个未完成 change。
19
+ - 在 attached 状态下,需求讨论会写入 planning journal。
20
+ - `cs-plan` 只刷新 `proposal.md`、`design.md`、`specs`、`tasks.md`,不写业务代码。
21
+ - `cs-work` 会把 `tasks.md` 变成后台执行任务,并由 watcher 负责推进度和恢复。
22
+ - 如果 ACP worker 在 gateway 重启后仍然存活,ClawSpec 会优先接管这条现有 session,而不是盲目再起一个新 worker。
23
+ - `/clawspec cancel` 通过快照回滚变更,不会做整仓库 Git reset。
24
+ - `/clawspec archive` 在任务完成后归档 OpenSpec change,并清掉当前聊天里的活动 change。
25
+
26
+ ## 为什么命令面要拆开
27
+
28
+ ClawSpec 使用两套入口,是因为它们解决的是两类完全不同的问题:
29
+
30
+ | 入口 | 示例 | 负责什么 | 为什么需要它 |
31
+ | --- | --- | --- | --- |
32
+ | Slash command | `/clawspec use`、`/clawspec proposal`、`/clawspec status` | 直接插件控制、目录初始化、状态查询 | 快、确定性强,不依赖 agent 回合 |
33
+ | 聊天关键字 | `cs-plan`、`cs-work`、`cs-pause` | 在当前聊天里注入工作流上下文,或排队后台执行 | 让 planning 可见、让实现可恢复 |
34
+
35
+ 实际使用时:
36
+
37
+ - 用 `/clawspec ...` 管项目和状态。
38
+ - 用 `cs-plan` 让当前可见聊天回合去刷新 planning artifacts。
39
+ - 用 `cs-work` 让 watcher 启动后台实现。
40
+
41
+ ## 架构图
42
+
43
+ ```mermaid
44
+ flowchart TD
45
+ BOOT[clawspec.bootstrap 服务]
46
+ BOOT --> DEPS[检查 openspec + acpx]
47
+ BOOT --> STORES[state + memory + workspace 存储]
48
+
49
+ U[聊天中的用户] --> CMD[/clawspec command/]
50
+ U --> KEY[cs-* keyword]
51
+ U --> MSG[普通需求讨论]
52
+
53
+ CMD --> SVC[ClawSpec service]
54
+ KEY --> HOOK[before_prompt_build hook]
55
+ MSG --> INBOUND[message_received hook]
56
+
57
+ INBOUND --> JOURNAL[planning-journal.jsonl]
58
+ HOOK --> SVC
59
+ SVC --> STATE[plugin state store]
60
+ SVC --> WS[workspace store]
61
+ SVC --> MEM[project memory store]
62
+ SVC --> OSCLI[OpenSpec CLI]
63
+
64
+ SVC -->|cs-plan| MAIN[可见聊天主 agent]
65
+ MAIN -->|skills + planning prompt| ARTIFACTS[proposal/design/specs/tasks]
66
+
67
+ SVC -->|cs-work| CTRL[execution-control.json]
68
+ CTRL --> WATCHER[watcher manager]
69
+ WATCHER --> ACPCLIENT[AcpWorkerClient]
70
+ ACPCLIENT --> ACPCLI[直接 acpx CLI session]
71
+ ACPCLI --> PROGRESS[worker-progress.jsonl]
72
+ ACPCLI --> RESULT[execution-result.json]
73
+ WATCHER --> NOTIFY[聊天进度通知]
74
+ NOTIFY --> U
75
+
76
+ JOURNAL --> MAIN
77
+ ARTIFACTS --> ACPCLI
78
+ RESULT --> STATE
79
+ PROGRESS --> STATE
80
+ ```
81
+
82
+ ## 当前系统架构
83
+
84
+ ClawSpec 现在可以按六层来理解:
85
+
86
+ | 层级 | 主要组件 | 职责 |
87
+ | --- | --- | --- |
88
+ | 启动层 | `clawspec.bootstrap`、`ensureOpenSpecCli`、`ensureAcpxCli` | 初始化存储、检查依赖、启动 watcher manager |
89
+ | 控制层 | `/clawspec` 命令、`clawspec-projects`、插件 hooks | 接收用户意图、路由命令、决定当前聊天要注入什么上下文 |
90
+ | Planning 层 | `message_received`、`before_prompt_build`、主聊天 agent | 记录需求讨论,并在 `cs-plan` 时直接在主聊天窗口完成 planning sync |
91
+ | 执行层 | `WatcherManager`、`ExecutionWatcher`、`AcpWorkerClient` | arm 任务、启动后台 worker、监控 progress/result 文件 |
92
+ | 恢复层 | 启动恢复、重试退避、session 接管 | gateway 重启后接管存活 worker,或安全地重排任务 |
93
+ | 持久化层 | OpenClaw 全局状态 + repo 内 `.openclaw/clawspec` | 保存项目状态、journal、回滚快照、执行结果、进度偏移量 |
94
+
95
+ 当前架构里有几个关键取舍:
96
+
97
+ - Planning 是可见的。`cs-plan` 在主聊天窗口执行,不走隐藏 subagent。
98
+ - Implementation 是耐久的。`cs-work` 交给 watcher 管理的后台 worker。
99
+ - Worker 通道是直接的。ClawSpec 通过自己的 `AcpWorkerClient` 直接调用 `acpx`,而不是依赖隐藏 planning thread。
100
+ - 进度是文件化的。worker 把进度和结果写到文件里,这样 watcher 和 gateway 重启后都能恢复。
101
+ - 回滚是显式的。`cancel` 走快照恢复,不做整仓库粗暴重置。
102
+
103
+ ## 实现方案
104
+
105
+ ### 1. 启动与依赖自检
106
+
107
+ 插件服务启动时会做这几件事:
108
+
109
+ - 初始化 project、memory、workspace 三套 store
110
+ - 检查 `openspec` 是否可用,优先本地安装,其次系统 `PATH`
111
+ - 检查 `acpx` 是否可用,优先插件本地安装,其次 OpenClaw 自带的 ACPX,最后才是系统 `PATH`
112
+ - 构造 `OpenSpecClient`、`AcpWorkerClient`、`ClawSpecNotifier`、`WatcherManager`、`ClawSpecService`
113
+
114
+ 这意味着在一台比较“干净”的 gateway 主机上,ClawSpec 也能把自己依赖的工具链引导起来。
115
+
116
+ ### 2. 命令路由与 prompt 注入
117
+
118
+ ClawSpec 主要用三条 hook 链路:
119
+
120
+ - `message_received`:在 attached 状态下把需求讨论写入 planning journal
121
+ - `before_prompt_build`:决定当前可见聊天回合要注入 project / planning / execution 哪类上下文
122
+ - `agent_end`:对齐一次可见 planning 回合的结束状态
123
+
124
+ 而 `/clawspec` 斜杠命令负责确定性更强的操作,例如:
125
+
126
+ - 切 workspace
127
+ - 选 project
128
+ - 新建 change
129
+ - pause / continue
130
+ - archive / cancel
131
+
132
+ ### 3. 可见 planning 流程
133
+
134
+ Planning 分两种模式:
135
+
136
+ - 普通 attached 需求讨论:只记录,不改 artifacts
137
+ - `cs-plan`:显式触发 planning sync,在主聊天窗口里执行
138
+
139
+ 在 `cs-plan` 时,ClawSpec 会向主聊天 agent 注入:
140
+
141
+ - 当前 active repo 和 active change
142
+ - planning journal
143
+ - `skills/` 目录里的 OpenSpec skill 文本
144
+ - 一套严格规则,防止它静默切换 change 或直接开始写业务代码
145
+
146
+ 随后主聊天 agent 会在当前可见回合里刷新 `proposal.md`、`specs`、`design.md`、`tasks.md`。
147
+
148
+ ### 4. 后台 implementation 流程
149
+
150
+ `cs-work` 不会在主聊天窗口里直接实现代码,而是按这条链路走:
151
+
152
+ - 先确认 planning 状态足够干净,可以开始执行
153
+ - 写入 `execution-control.json`
154
+ - 给当前 channel/project arm watcher
155
+ - watcher 再启动一个直接的 `acpx` worker session
156
+
157
+ worker 会读取:
158
+
159
+ - repo 内的控制文件
160
+ - planning artifacts
161
+ - `openspec instructions apply --json`
162
+
163
+ 然后按 task 顺序逐个执行、更新 `tasks.md`、写 `execution-result.json`,并把结构化进度事件追加到 `worker-progress.jsonl`。
164
+
165
+ ### 5. 进度播报与漏发补偿
166
+
167
+ 面向用户的进度回报由 watcher 负责:
168
+
169
+ - 持续读取 `worker-progress.jsonl`
170
+ - 把 worker 事件转换成简短聊天消息
171
+ - 同步 project task counts 和 heartbeat
172
+ - 在最终完成消息发出前,根据上次保存的 offset 把漏掉的进度补发出来
173
+
174
+ 现在实现启动期的可见性被拆成了两层:
175
+
176
+ - watcher 侧状态,例如“starting worker”“ACP worker connected”
177
+ - worker 自己写出的上下文加载状态,例如“Preparing <task>: loading context”“Loaded proposal.md”“Context ready...”
178
+
179
+ 最后这一点很重要,因为它能避免 gateway 或 watcher 短暂落后时,用户错过最后几条任务更新。
180
+
181
+ ### 6. 恢复、重启与有界重试
182
+
183
+ gateway 重启后,watcher manager 会:
184
+
185
+ - 扫描所有活动项目
186
+ - 如果发现旧 worker session 还活着,就直接接管
187
+ - 如果 session 已经死掉,就把项目重新 arm 到 planning 或 implementation
188
+ - 保留 task 进度和 worker progress offset
189
+
190
+ 自动恢复只会针对“原本就在执行链路中”的项目:例如 `armed`、`running`、`planning`,或者被可恢复 ACP/runtime 故障打断的 `blocked` 项目。单纯处于 `ready` / `idle`、只是等你手动说 `cs-plan` 或 `cs-work` 的项目,不会在 gateway 重启后自动开跑。
191
+
192
+ worker 失败时,ClawSpec 会:
193
+
194
+ - 区分“可恢复的 ACP 故障”和“真实 blocker”
195
+ - 对可恢复故障做有限次数、带退避的重试
196
+ - 超过上限后把项目标记为 `blocked`
197
+
198
+ 这样 `cs-work` 才能既有恢复能力,又不会在后台无休止地留下僵尸任务。
199
+
200
+ ## 各动作到底跑在哪
201
+
202
+ | 动作 | 运行位置 | 用户是否可见 | 会写什么 |
203
+ | --- | --- | --- | --- |
204
+ | `/clawspec workspace` | 插件命令处理器 | 直接回复 | Workspace 状态 |
205
+ | `/clawspec use` | 插件命令处理器,必要时跑 `openspec init` | 直接回复 | Project 选择、OpenSpec 初始化 |
206
+ | `/clawspec proposal` | 插件命令处理器,跑 `openspec new change` | 直接回复 | Change 脚手架、快照基线、planning 初始状态 |
207
+ | 普通需求讨论 | 主聊天 agent + prompt 注入 | 可见 | Planning journal,不改 artifact |
208
+ | `cs-plan` | 当前可见聊天回合 | 可见 | Planning artifacts、journal snapshot |
209
+ | `cs-work` | Watcher + ACP worker | 只看到简短进度回报 | 代码、`tasks.md`、runtime 支持文件 |
210
+ | `/clawspec continue` | 插件根据当前 phase 决定恢复 planning 还是 work | 直接回复,之后进入相应流程 | Execution 状态 |
211
+
212
+ ## 环境要求
213
+
214
+ - 一份较新的 OpenClaw,支持插件 hooks 和 ACP runtime。
215
+ - Gateway 主机上有 Node.js `>= 24`。
216
+ - 如果需要自动安装 OpenSpec,则主机上还需要 `npm`。
217
+ - 用于可见 planning 的 agent 需要具备 shell 和文件编辑能力。
218
+ - 后台实现依赖 ACP backend `acpx`。
219
+
220
+ ClawSpec 依赖这几个 OpenClaw hook:
221
+
222
+ - `message_received`
223
+ - `before_prompt_build`
224
+ - `agent_end`
225
+
226
+ 如果宿主全局禁用了插件 hooks,那么基于关键字的工作流就跑不起来。
227
+
228
+ ## 安装
229
+
230
+ ### 1. 安装插件
231
+
232
+ npm 发布后的标准安装方式:
233
+
234
+ ```powershell
235
+ openclaw plugins install clawspec@latest
236
+ ```
237
+
238
+ `@latest` 会始终解析到 npm 上最新发布的 ClawSpec 版本。
239
+
240
+ 当前 OpenClaw 一般不接受把 GitHub 仓库 URL 直接当作普通插件安装源。也就是说,单独一个 GitHub repo 还不够,公开安装路径通常还是 npm 包规格,例如 `clawspec@latest`。
241
+
242
+ 如果你要安装一个还没发布到 npm 的提交,请改用本地 checkout 或下载好的 `.tgz` 包安装。
243
+
244
+ ### 2. 在 OpenClaw 里启用 ACP 和 ACPX
245
+
246
+ 示例 `~/.openclaw/openclaw.json`:
247
+
248
+ ```json
249
+ {
250
+ "acp": {
251
+ "enabled": true,
252
+ "backend": "acpx",
253
+ "defaultAgent": "codex"
254
+ },
255
+ "plugins": {
256
+ "entries": {
257
+ "acpx": {
258
+ "enabled": true,
259
+ "config": {
260
+ "permissionMode": "approve-all",
261
+ "expectedVersion": "any"
262
+ }
263
+ },
264
+ "clawspec": {
265
+ "enabled": true,
266
+ "config": {
267
+ "defaultWorkspace": "~/clawspec/workspace",
268
+ "workerAgentId": "codex",
269
+ "openSpecTimeoutMs": 120000,
270
+ "watcherPollIntervalMs": 4000
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+ ```
277
+
278
+ 这里要注意:
279
+
280
+ - 新版 OpenClaw 往往已经自带 `acpx`,ClawSpec 现在会先检查这份 builtin ACPX,再回退到系统 `PATH` 或插件本地安装。
281
+ - 如果你的 OpenClaw 没有自带 `acpx`,那就要先单独安装或加载 `acpx`。
282
+ - ClawSpec 自己不携带 ACP runtime backend。
283
+ - 当 ACPX 不可用时,watcher 会在聊天里发一条简短提示,告诉用户去启用 `plugins.entries.acpx` 和 backend `acpx`。
284
+ - `acp.defaultAgent` 是 OpenClaw 自己的 ACP 默认 agent;ClawSpec 的后台 worker 默认看的是 `plugins.entries.clawspec.config.workerAgentId`。
285
+ - 对 ClawSpec 来说,worker 选择优先级是:当前 channel/project 上的 `/clawspec worker <agent-id>` 覆盖,其次是 `clawspec.config.workerAgentId`,最后才是 ClawSpec 自己的内置默认值。
286
+ - 也就是说,ClawSpec 现在不会自动继承 `acp.defaultAgent`。如果你希望两边都用同一个 agent,需要把两处都显式配成一样。
287
+
288
+ ### 2.5. 选择默认 worker agent
289
+
290
+ ClawSpec 可以让后台任务跑在不同的 ACP agent 上,比如 `codex` 或 `claude`,但这里有两个“默认值”要区分:
291
+
292
+ - `acp.defaultAgent`:OpenClaw 自己 ACP 系统的默认 agent
293
+ - `plugins.entries.clawspec.config.workerAgentId`:ClawSpec 执行 `cs-work` 时使用的默认 worker agent
294
+
295
+ 如果你希望两层都统一成同一个 agent,建议同时这样配置:
296
+
297
+ ```json
298
+ {
299
+ "acp": {
300
+ "enabled": true,
301
+ "backend": "acpx",
302
+ "defaultAgent": "claude"
303
+ },
304
+ "plugins": {
305
+ "entries": {
306
+ "clawspec": {
307
+ "enabled": true,
308
+ "config": {
309
+ "workerAgentId": "claude"
310
+ }
311
+ }
312
+ }
313
+ }
314
+ }
315
+ ```
316
+
317
+ 运行时常用命令:
318
+
319
+ - `/clawspec worker`:查看当前 channel/project 的 worker agent 以及插件默认值
320
+ - `/clawspec worker codex`:把当前 channel/project 切到 `codex`
321
+ - `/clawspec worker claude`:把当前 channel/project 切到 `claude`
322
+ - `/clawspec worker status`:查看实时 worker 状态、传输层状态、startup phase、startup wait 和 session 信息
323
+
324
+ 补充说明:
325
+
326
+ - `/clawspec worker <agent-id>` 的覆盖范围是当前 channel/project
327
+ - 你填写的 agent id 必须已经存在于 OpenClaw 的 agent 列表或 ACP allowlist 中
328
+ - 如果你想配置“全局默认”,改的是 `clawspec.config.workerAgentId`
329
+ - 如果你想临时对当前项目改用另一个 agent,就直接执行 `/clawspec worker <agent-id>`
330
+
331
+ ### 2.6. ClawSpec 插件配置项参考
332
+
333
+ 常用的 `plugins.entries.clawspec.config` 字段如下:
334
+
335
+ | Key | 用途 | 说明 |
336
+ | --- | --- | --- |
337
+ | `defaultWorkspace` | `/clawspec workspace` 和 `/clawspec use` 的默认 workspace | 某个 channel 第一次选定 workspace 后,会优先使用该 channel 自己记住的值 |
338
+ | `workerAgentId` | 后台 worker 默认使用的 ACP agent | 可以被 `/clawspec worker <agent-id>` 在当前 channel/project 覆盖 |
339
+ | `openSpecTimeoutMs` | 每次 OpenSpec CLI 调用的超时时间 | repo 较大或主机较慢时可以调大 |
340
+ | `watcherPollIntervalMs` | watcher 的后台恢复扫描周期 | 影响恢复检查和进度补发的灵敏度 |
341
+ | `archiveDirName` | `.openclaw/clawspec/` 下归档目录名称 | 除非你要调整归档布局,否则保持默认即可 |
342
+ | `allowedChannels` | 可选的 channel allowlist | 只想在部分频道启用 ClawSpec 时很有用 |
343
+
344
+ 为了兼容旧配置,下面这些字段目前仍然接受,但已经是 no-op:
345
+
346
+ - `maxAutoContinueTurns`
347
+ - `maxNoProgressTurns`
348
+ - `workerBackendId`
349
+ - `workerWaitTimeoutMs`
350
+ - `subagentLane`
351
+
352
+ ### 3. 重启 gateway
353
+
354
+ ```powershell
355
+ openclaw gateway restart
356
+ openclaw gateway status
357
+ ```
358
+
359
+ ### 4. 了解工具依赖的自动引导逻辑
360
+
361
+ ClawSpec 启动时会按这个顺序检查 `openspec`:
362
+
363
+ 1. 插件本地 `node_modules/.bin` 下的二进制
364
+ 2. 系统 `PATH` 上的 `openspec`
365
+ 3. 如果都没有,可能执行:
366
+
367
+ ```powershell
368
+ npm install --omit=dev --no-save @fission-ai/openspec
369
+ ```
370
+
371
+ 这意味着如果 gateway 主机上本来没有 `openspec`,它可能需要网络访问和可用的 `npm`。
372
+
373
+ ClawSpec 启动时会按这个顺序检查 `acpx`:
374
+
375
+ 1. 插件本地 `node_modules/.bin` 下的二进制
376
+ 2. 当前 OpenClaw 安装自带的 ACPX 二进制
377
+ 3. 系统 `PATH` 上的 `acpx`
378
+ 4. 如果这些都不满足 worker 运行要求,可能执行:
379
+
380
+ ```powershell
381
+ npm install --omit=dev --no-save acpx@0.3.1
382
+ ```
383
+
384
+ 第一次 fallback 安装可能会花一点时间。如果 OpenClaw 已经自带 ACPX,ClawSpec 现在应该直接复用它,而不是再额外安装一份。
385
+
386
+ ### 4.5. CI 与发布自动化
387
+
388
+ 仓库里现在已经有两条 GitHub Actions workflow:
389
+
390
+ - `.github/workflows/ci.yml`
391
+ 在 `push main`、`pull_request` 和手动触发时运行。
392
+ 使用三平台矩阵:`ubuntu-latest`、`windows-latest`、`macos-latest`。
393
+ 执行 `npm ci`、`npm run check`、`npm test`。
394
+ - `.github/workflows/release.yml`
395
+ 在推送 `v*` tag 时运行。
396
+ 会校验 tag 和 `package.json` 版本一致,然后执行安装、检查、测试、打包、发布 npm,最后创建 GitHub Release。
397
+
398
+ 发布要点:
399
+
400
+ - release tag 形如 `vX.Y.Z`
401
+ - tag 必须和 `package.json` 里的版本完全一致
402
+ - npm 发布需要配置 npm trusted publishing,或者提供仓库 secret `NPM_TOKEN`
403
+ - GitHub Release 创建使用默认的 GitHub Actions token,不需要额外手工 token
404
+
405
+ 典型发布流程:
406
+
407
+ ```powershell
408
+ # 1. 先更新 package.json 版本号
409
+ git add package.json package-lock.json
410
+ git commit -m "chore: release vX.Y.Z"
411
+ git push origin main
412
+
413
+ # 2. 再创建并推送同版本 tag
414
+ git tag vX.Y.Z
415
+ git push origin vX.Y.Z
416
+ ```
417
+
418
+ ## 快速开始
419
+
420
+ ```text
421
+ /clawspec workspace "<workspace-path>"
422
+ /clawspec use "demo-app"
423
+ /clawspec proposal add-login-flow "Build login and session handling"
424
+ 在聊天里继续描述需求
425
+ cs-plan
426
+ cs-work
427
+ /clawspec status
428
+ /clawspec archive
429
+ ```
430
+
431
+ 这 8 步分别发生了什么:
432
+
433
+ 1. `/clawspec workspace` 为当前 chat channel 选择 workspace。
434
+ 2. `/clawspec use` 在该 workspace 下选择或创建项目目录,必要时执行 `openspec init`。
435
+ 3. `/clawspec proposal` 创建 OpenSpec change 脚手架和回滚快照基线。
436
+ 4. 普通聊天讨论会被写入 planning journal。
437
+ 5. `cs-plan` 在当前可见聊天回合里刷新 planning artifacts。
438
+ 6. `cs-work` 激活 watcher,并启动后台实现。
439
+ 7. Watcher 把简短进度消息回推到同一个聊天窗口。
440
+ 8. `/clawspec archive` 校验并归档已完成 change。
441
+
442
+ ## 推荐首次使用流程
443
+
444
+ 下面这套流程就是普通用户第一次上手时最标准的 happy path。
445
+
446
+ ### 1. 先绑定 workspace,再选项目
447
+
448
+ ```text
449
+ /clawspec workspace "D:\clawspec\workspace"
450
+ /clawspec use "demo-app"
451
+ ```
452
+
453
+ 预期结果:
454
+
455
+ - ClawSpec 会把这个 workspace 记到当前 chat channel 上
456
+ - 如果项目目录不存在,会自动创建
457
+ - 如果这是第一次选中这个 repo,会自动执行 `openspec init`
458
+
459
+ ### 2. 先开 change,再开始聊需求
460
+
461
+ ```text
462
+ /clawspec proposal add-login-flow "Build login and session handling"
463
+ ```
464
+
465
+ 预期结果:
466
+
467
+ - OpenSpec 会创建 `openspec/changes/add-login-flow/`
468
+ - ClawSpec 会先拍一份回滚快照基线
469
+ - 当前聊天会进入 `add-login-flow` 这个 active change 上下文
470
+
471
+ ### 3. 正常在聊天里描述需求
472
+
473
+ 例如:
474
+
475
+ ```text
476
+ 支持邮箱加密码登录。
477
+ 需要 refresh token。
478
+ access token 15 分钟过期。
479
+ ```
480
+
481
+ 预期结果:
482
+
483
+ - 这些讨论内容会在 attached 状态下写入 planning journal
484
+ - 此时不会立刻刷新 artifacts
485
+ - 此时也不会立刻开始写代码
486
+
487
+ ### 4. 显式执行 planning sync
488
+
489
+ ```text
490
+ cs-plan
491
+ ```
492
+
493
+ 预期结果:
494
+
495
+ - 当前可见聊天回合会刷新 `proposal.md`、`design.md`、`specs`、`tasks.md`
496
+ - 你会在主聊天窗口看到 planning 过程
497
+ - 最后一条提示应该明确告诉你下一步运行 `cs-work`
498
+
499
+ ### 5. 启动后台实现
500
+
501
+ ```text
502
+ cs-work
503
+ ```
504
+
505
+ 预期结果:
506
+
507
+ - ClawSpec 会先 arm watcher
508
+ - watcher 会通过 `acpx` 启动 ACP worker
509
+ - 聊天窗口会开始收到简短的任务开始/完成进度消息
510
+
511
+ ### 6. 查看进度,或者临时切走项目上下文
512
+
513
+ 常用命令:
514
+
515
+ ```text
516
+ /clawspec worker status
517
+ /clawspec status
518
+ cs-detach
519
+ cs-attach
520
+ ```
521
+
522
+ 如果你想让后台继续跑,但前台聊天先聊别的事,就用 `cs-detach`。等你要继续讨论当前 change,再用 `cs-attach` 接回来。
523
+
524
+ ### 7. 收尾
525
+
526
+ 如果任务已经全部完成:
527
+
528
+ ```text
529
+ /clawspec archive
530
+ ```
531
+
532
+ 如果归档前又想追加需求:
533
+
534
+ ```text
535
+ 继续在聊天里描述新需求
536
+ cs-plan
537
+ cs-work
538
+ ```
539
+
540
+ 这也是 ClawSpec 最常见的正常循环:
541
+
542
+ 1. 聊需求
543
+ 2. `cs-plan`
544
+ 3. `cs-work`
545
+ 4. 完成后 `/clawspec archive`
546
+
547
+ ## Slash 命令
548
+
549
+ | 命令 | 何时使用 | 会做什么 |
550
+ | --- | --- | --- |
551
+ | `/clawspec workspace [path]` | 在选项目之前,或需要切换工作区时 | 查看当前 chat channel 的 workspace;如果提供路径,则切换到新的 workspace |
552
+ | `/clawspec use <project-name>` | 开始一个项目,或重新回到某个 repo 时 | 在当前 workspace 下选中或创建项目目录,并在必要时执行 `openspec init` |
553
+ | `/clawspec proposal <change-name> [description]` | 在开始结构化 planning 之前 | 创建 OpenSpec change 脚手架、准备回滚基线,并把该 change 设为当前活动 change |
554
+ | `/clawspec worker` | 想查看当前 worker agent 配置时 | 展示当前 channel/project 的 worker agent 和插件默认值 |
555
+ | `/clawspec worker <agent-id>` | 想让当前项目对话改用另一个 ACP worker,例如 `codex` 或 `claude` | 覆盖当前 channel/project 的 worker agent |
556
+ | `/clawspec worker status` | 后台运行中、恢复中、或排查 worker 问题时 | 展示 worker 配置、传输层状态、startup phase、startup wait、实时 session 状态、pid、heartbeat 和下一步建议 |
557
+ | `/clawspec attach` | 想让普通聊天重新回到当前 change 的需求讨论上下文时 | 重新接入 ClawSpec 上下文,使普通聊天再次进入 planning journal |
558
+ | `/clawspec detach` | 想让后台继续跑,但普通聊天先别影响项目时 | 把普通聊天从 ClawSpec prompt 注入和 planning journal 记录中分离出去 |
559
+ | `/clawspec deattach` | 仅用于兼容旧习惯 | `/clawspec detach` 的兼容别名 |
560
+ | `/clawspec continue` | pause 后恢复、修完 blocker 后恢复、或重启后恢复时 | 根据当前 phase 恢复 planning 或 implementation |
561
+ | `/clawspec pause` | 想在安全边界暂停后台 worker 时 | 请求当前执行在下一个安全点暂停 |
562
+ | `/clawspec status` | 任何时候想看一次统一状态快照时 | 输出当前 workspace、project、change、生命周期、任务计数、journal 状态和下一步建议 |
563
+ | `/clawspec archive` | 所有任务完成,准备收尾时 | 校验并归档当前 OpenSpec change,同时清理活动 change 状态 |
564
+ | `/clawspec cancel` | 想放弃当前 change 时 | 按快照恢复已跟踪文件、删除 change、停止执行状态,并清掉活动 change |
565
+
566
+ 辅助 host CLI:
567
+
568
+ | 命令 | 何时使用 | 会做什么 |
569
+ | --- | --- | --- |
570
+ | `clawspec-projects` | 在 gateway 主机上想查看已记忆 workspace 时 | 列出插件状态里保存过的 workspace 根目录 |
571
+
572
+ ## 聊天关键字
573
+
574
+ 这些关键字是作为普通聊天消息发送的。
575
+
576
+ | 关键字 | 作用 |
577
+ | --- | --- |
578
+ | `cs-plan` | 在当前可见聊天回合里执行 planning sync。适合在你新增、修改需求后使用。 |
579
+ | `cs-work` | 启动后台 implementation。应当在 planning 已经干净之后再执行。 |
580
+ | `cs-attach` | 把普通聊天重新接回 project mode,使新的需求讨论继续记入 journal。 |
581
+ | `cs-detach` | 把普通聊天从 project mode 中分离,但 watcher 进度推送仍会继续。 |
582
+ | `cs-deattach` | `cs-detach` 的兼容别名。 |
583
+ | `cs-pause` | 协作式暂停后台 worker。 |
584
+ | `cs-continue` | 根据当前状态恢复 planning 或 implementation。 |
585
+ | `cs-status` | 在聊天里查看当前项目状态。 |
586
+ | `cs-cancel` | 不走 slash command,直接在聊天里取消当前 change。 |
587
+
588
+ ## 端到端工作流
589
+
590
+ ```mermaid
591
+ sequenceDiagram
592
+ actor User
593
+ participant Chat as OpenClaw Chat
594
+ participant Plugin as ClawSpec Plugin
595
+ participant Main as 可见主 Agent
596
+ participant Watcher as Watcher Manager
597
+ participant Worker as ACP Worker
598
+ participant OpenSpec as OpenSpec CLI
599
+
600
+ User->>Plugin: /clawspec workspace + /clawspec use
601
+ Plugin->>OpenSpec: openspec init(如有需要)
602
+ Plugin-->>User: Project selected
603
+
604
+ User->>Plugin: /clawspec proposal add-change
605
+ Plugin->>OpenSpec: openspec new change
606
+ Plugin-->>User: Proposal ready
607
+
608
+ User->>Chat: 普通需求讨论
609
+ Chat->>Plugin: message_received
610
+ Plugin->>Plugin: 写入 planning journal
611
+
612
+ User->>Chat: cs-plan
613
+ Chat->>Plugin: before_prompt_build
614
+ Plugin->>Main: 注入 planning sync 上下文 + OpenSpec skills
615
+ Main->>OpenSpec: status + instructions + artifact refresh
616
+ Main-->>User: 可见 planning 更新
617
+ Plugin->>Plugin: 写入 planning snapshot
618
+
619
+ User->>Chat: cs-work
620
+ Chat->>Plugin: before_prompt_build
621
+ Plugin->>Watcher: 进入 implementation 队列
622
+ Watcher->>Worker: 启动 ACP session
623
+ Worker->>OpenSpec: apply instructions
624
+ Worker->>Watcher: progress/result files
625
+ Watcher-->>User: 简短进度卡片
626
+
627
+ User->>Plugin: /clawspec archive
628
+ Plugin->>OpenSpec: validate + archive
629
+ Plugin-->>User: Archive complete
630
+ ```
631
+
632
+ ## Attached 与 Detached
633
+
634
+ ClawSpec 会为每个 chat channel 维护一个 `contextMode`:
635
+
636
+ | 模式 | 含义 |
637
+ | --- | --- |
638
+ | `attached` | 普通聊天会带 ClawSpec prompt 注入,需求消息会进入 planning journal |
639
+ | `detached` | 普通聊天回到正常模式;后台 watcher 的进度消息仍然会继续出现 |
640
+
641
+ 如果你想让后台实现继续跑,但当前窗口要去聊别的事情,就应该切到 detached。
642
+
643
+ ## Planning Journal 与 Dirty 机制
644
+
645
+ ClawSpec 的 planning journal 在这里:
646
+
647
+ ```text
648
+ <repo>/.openclaw/clawspec/planning-journal.jsonl
649
+ ```
650
+
651
+ 记录规则如下:
652
+
653
+ - active change 且 context attached 时,用户需求消息会写入 journal。
654
+ - 有价值的 assistant 回复也会写入 journal。
655
+ - 被动的流程提示、控制类消息会被过滤。
656
+ - 命令和 `cs-*` 关键字不会被当成 planning 内容写入。
657
+ - 成功执行 `cs-plan` 后,会写一份 journal snapshot。
658
+ - 如果 snapshot 之后又来了新的需求讨论,journal 就会变成 `dirty`。
659
+
660
+ 所以你会看到这种行为:
661
+
662
+ - 你聊了新需求
663
+ - journal 变脏
664
+ - `cs-work` 被阻止
665
+ - 插件要求你先 `cs-plan`
666
+
667
+ 这是为了避免在过期 artifacts 上继续实现。
668
+
669
+ ## 可见 Planning
670
+
671
+ `cs-plan` 不走后台 ACP worker,而是直接在当前可见聊天回合里执行。ClawSpec 会向主聊天 agent 注入:
672
+
673
+ - 当前 active change 的上下文
674
+ - planning journal
675
+ - 从打包内置的 `skills/` 目录读取的 OpenSpec skill 原文
676
+
677
+ 当前 skill 映射:
678
+
679
+ | 模式 | 注入的 skills |
680
+ | --- | --- |
681
+ | 普通 planning 讨论 | `openspec-explore`、`openspec-propose` |
682
+ | `cs-plan` planning sync | `openspec-explore`、`openspec-propose` |
683
+ | `cs-work` implementation | `openspec-apply-change` |
684
+
685
+ Planning prompt 还会显式约束主聊天 agent:
686
+
687
+ - 没有明确 `cs-plan` 时,不得自行开始 planning sync
688
+ - 普通 planning 讨论时不得实现代码
689
+ - 不得静默切换到别的 change
690
+ - 不得无意义扫描兄弟 change 目录
691
+
692
+ ## 后台 Implementation
693
+
694
+ `cs-work` 做三件事:
695
+
696
+ 1. 执行 `openspec status` 和 `openspec instructions apply --json`
697
+ 2. 写入 `execution-control.json` 并激活 watcher
698
+ 3. 由 watcher 通过 `acpx` 启动 ACP worker
699
+
700
+ 之后 watcher 会负责:
701
+
702
+ - 发启动提示
703
+ - 发 “ACP worker connected” 提示
704
+ - 从 `worker-progress.jsonl` 读取进度
705
+ - 对齐 `execution-result.json`
706
+ - 如果 watcher 一度落后,还会在最终完成消息前把漏掉的进度补发出来
707
+ - 更新 project 状态
708
+ - 对可恢复的 ACP 故障做有上限的重试
709
+ - 在 ACPX 不可用时给出简短可操作的提示
710
+
711
+ ## 恢复与重启模型
712
+
713
+ ClawSpec 设计目标之一就是“后台工作可恢复”:
714
+
715
+ - gateway 启动时:watcher manager 会先扫描活动项目,并优先尝试接管仍然存活的 ACP worker session
716
+ - 如果旧 worker 还活着:ClawSpec 会直接继续监控这条现有 session 的进度文件,不需要你重新执行 `cs-work`
717
+ - 如果旧 worker 已经死掉:ClawSpec 才会把任务重新 arm,再按需要启动替代 worker
718
+ - gateway 停止时:活动后台 session 会被关闭,但会留下可恢复状态
719
+ - ACP worker 崩溃时:watcher 会对可恢复故障做退避重试
720
+ - 达到重试上限时:项目进入 `blocked`
721
+
722
+ 这也是为什么 `cs-work` 不直接把全部实现塞进单个可见聊天回合里。
723
+
724
+ ## 生命周期模型
725
+
726
+ 真实实现里同时追踪 `status` 和 `phase`。下面是简化版状态图:
727
+
728
+ ```mermaid
729
+ stateDiagram-v2
730
+ [*] --> Idle
731
+ Idle --> Ready: /clawspec proposal
732
+ Ready --> Planning: cs-plan
733
+ Planning --> Ready: planning sync finished
734
+ Ready --> Armed: cs-work
735
+ Armed --> Running: watcher 启动 ACP worker
736
+ Running --> Paused: /clawspec pause
737
+ Running --> Blocked: blocker / ACPX unavailable / retry cap
738
+ Running --> Done: tasks complete
739
+ Paused --> Armed: /clawspec continue
740
+ Blocked --> Ready: 修复 planning 问题 + cs-plan
741
+ Blocked --> Armed: 修复实现问题 + cs-work
742
+ Done --> Archived: /clawspec archive
743
+ Ready --> Cancelled: /clawspec cancel
744
+ Paused --> Cancelled: /clawspec cancel
745
+ Blocked --> Cancelled: /clawspec cancel
746
+ ```
747
+
748
+ ## 文件与存储
749
+
750
+ OpenClaw 全局插件状态:
751
+
752
+ ```text
753
+ <openclaw-state-dir>/clawspec/
754
+ active-projects.json
755
+ project-memory.json
756
+ workspace-state.json
757
+ projects/
758
+ <projectId>.json
759
+ ```
760
+
761
+ Repo 本地 runtime 状态:
762
+
763
+ ```text
764
+ <repo>/.openclaw/clawspec/
765
+ state.json
766
+ execution-control.json
767
+ execution-result.json
768
+ worker-progress.jsonl
769
+ progress.md
770
+ changed-files.md
771
+ decision-log.md
772
+ latest-summary.md
773
+ planning-journal.jsonl
774
+ planning-journal.snapshot.json
775
+ rollback-manifest.json
776
+ snapshots/
777
+ <change-name>/
778
+ baseline/
779
+ archives/
780
+ <projectId>/
781
+ ```
782
+
783
+ OpenSpec change 本身仍然放在标准目录:
784
+
785
+ ```text
786
+ <repo>/openspec/changes/<change-name>/
787
+ .openspec.yaml
788
+ proposal.md
789
+ design.md
790
+ tasks.md
791
+ specs/
792
+ ```
793
+
794
+ ## 运行边界
795
+
796
+ - Workspace 按 channel 记忆。
797
+ - 每个 channel 只维护一个 active project。
798
+ - 同一个 repo 跨 channel 只允许一个未完成 change。
799
+ - `tasks.md` 仍然是任务真相源。
800
+ - OpenSpec 仍然是工作流语义的真相源。
801
+ - `/clawspec cancel` 不会执行整仓库级别的 `git reset --hard`。
802
+ - Detached 模式只会停止 prompt 注入和 journal 记录,不会停止 watcher 推送。
803
+
804
+ ## 常见排障
805
+
806
+ ### `cs-work` 提示需要先 planning sync
807
+
808
+ 原因可能是:
809
+
810
+ - planning journal 是 dirty
811
+ - planning artifacts 缺失或过期
812
+ - OpenSpec apply state 仍是 blocked
813
+
814
+ 处理方式:
815
+
816
+ 1. 如果需求还没聊完,继续聊
817
+ 2. 运行 `cs-plan`
818
+ 3. 再运行 `cs-work`
819
+
820
+ ### Worker 已连接,但还没有开始具体 task
821
+
822
+ 这通常说明 ACP worker 已经活着,只是还在消化 implementation prompt,或者正在读取 planning artifacts。
823
+
824
+ 优先检查:
825
+
826
+ 1. watcher 侧消息,例如 “ACP worker connected...”
827
+ 2. worker 自己写出的状态消息,例如 “Preparing <task>: loading context”
828
+ 3. `/clawspec worker status`,重点看 `startup phase` 和 `startup wait`
829
+
830
+ 如果你已经看到了 “Context ready for ...”,说明 worker 已经读完 planning artifacts,接下来就会进入 implementation;但在第一个 `task_start` 出现前,仍然可能还要一点时间。
831
+
832
+ ### Watcher 提示 ACPX 不可用
833
+
834
+ 常见原因:
835
+
836
+ - `acp.enabled` 没开
837
+ - `acp.backend` 不是 `acpx`
838
+ - `plugins.entries.acpx.enabled` 没开
839
+ - 你的 OpenClaw 没有自带 ACPX,也没有单独安装/加载
840
+
841
+ 处理方式:
842
+
843
+ 1. 打开 ACP
844
+ 2. 把 backend 设成 `acpx`
845
+ 3. 启用 `plugins.entries.acpx`
846
+ 4. 如果宿主没自带 ACPX,就先安装或加载它
847
+ 5. 再运行 `cs-work` 或 `/clawspec continue`
848
+
849
+ ### 普通聊天污染了 planning journal
850
+
851
+ 可以用:
852
+
853
+ ```text
854
+ cs-detach
855
+ ```
856
+
857
+ 或者:
858
+
859
+ ```text
860
+ /clawspec detach
861
+ ```
862
+
863
+ 之后如果需要再接回来,使用 `cs-attach` 或 `/clawspec attach`。
864
+
865
+ ### `/clawspec use` 提示已有 unfinished change
866
+
867
+ 这是预期行为。ClawSpec 会阻止你在同一个 repo 上静默丢下一个活动 change。
868
+
869
+ 此时应该做以下之一:
870
+
871
+ - `/clawspec continue`
872
+ - `/clawspec cancel`
873
+ - `/clawspec archive`
874
+
875
+ ### Cancel 没有恢复整个仓库
876
+
877
+ 这是设计如此。Cancel 只会恢复 ClawSpec 为当前 change 跟踪的文件快照,而不是做整仓库级别的 Git 还原。
878
+
879
+ ## 开发与验证
880
+
881
+ 开发时常用检查:
882
+
883
+ ```powershell
884
+ node --experimental-strip-types -e "import('./src/index.ts')"
885
+ node --experimental-strip-types --test test/watcher-work.test.ts
886
+ ```
887
+
888
+ 手工验证流程:
889
+
890
+ ```text
891
+ /clawspec workspace "<workspace-path>"
892
+ /clawspec use "demo-app"
893
+ /clawspec proposal add-something "Build something"
894
+ 在聊天中继续描述需求
895
+ cs-plan
896
+ cs-work
897
+ cs-status
898
+ /clawspec worker status
899
+ /clawspec pause
900
+ /clawspec continue
901
+ /clawspec archive
902
+ ```
903
+
904
+ ## 实现总结
905
+
906
+ ClawSpec 本质上不是“多写几段 prompt”这么简单。它是一个把以下几层拼起来的编排层:
907
+
908
+ - OpenClaw hooks,用于控制可见聊天行为
909
+ - OpenSpec CLI,用于保证工作流语义一致
910
+ - planning journal 和 snapshot,用于跟踪需求变化
911
+ - watcher manager,用于让后台任务具备恢复性
912
+ - ACP worker,用于承载长时间实现任务
913
+
914
+ 也正因为这个拆分,ClawSpec 才能做到一边保持 planning 的聊天体验,一边让 implementation 具备可恢复、可暂停、可继续的后台执行能力。