cowork-flow 0.0.27 → 0.0.29
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.
- package/README.md +51 -17
- package/package.json +1 -1
- package/src/commands/init.js +1 -1
- package/src/commands/update.js +2 -4
- package/src/lib/copy-template.js +52 -5
- package/src/lib/platforms.js +0 -3
- package/template/.agents/skills/before-dev/SKILL.md +1 -0
- package/template/.agents/skills/check/SKILL.md +1 -0
- package/template/.agents/skills/party-mode-v2/SKILL.md +2 -0
- package/template/.agents/skills/tdd/SKILL.md +61 -0
- package/template/.agents/skills/writing-plans/SKILL.md +1 -0
- package/template/.claude/agents/cowork-check.md +3 -3
- package/template/.claude/agents/cowork-implement.md +7 -13
- package/template/.claude/agents/cowork-research.md +3 -3
- package/template/.claude/hooks/inject-workflow-state.py +18 -18
- package/template/.claude/skills/before-dev/SKILL.md +1 -0
- package/template/.claude/skills/check/SKILL.md +1 -0
- package/template/.claude/skills/party-mode-v2/SKILL.md +2 -0
- package/template/.claude/skills/tdd/SKILL.md +61 -0
- package/template/.claude/skills/writing-plans/SKILL.md +1 -0
- package/template/.codex/agents/cowork-check.toml +2 -0
- package/template/.codex/agents/cowork-implement.toml +2 -0
- package/template/.codex/hooks/inject-workflow-state.py +19 -19
- package/template/.cowork-flow/.version +1 -1
- package/template/.cowork-flow/adapters/claude-code/adapter.yaml +0 -1
- package/template/.cowork-flow/adapters/codex/adapter.yaml +0 -1
- package/template/.cowork-flow/adapters/opencode/adapter.yaml +0 -1
- package/template/.cowork-flow/scripts/commands/__init__.py +1 -0
- package/template/.cowork-flow/scripts/commands/_bootstrap.py +10 -0
- package/template/.cowork-flow/scripts/{add_session.py → commands/add_session.py} +8 -10
- package/template/.cowork-flow/scripts/{change.py → commands/change.py} +6 -2
- package/template/.cowork-flow/scripts/{doctor.py → commands/doctor.py} +26 -75
- package/template/.cowork-flow/scripts/{get_context.py → commands/get_context.py} +5 -1
- package/template/.cowork-flow/scripts/{get_developer.py → commands/get_developer.py} +6 -2
- package/template/.cowork-flow/scripts/{init_developer.py → commands/init_developer.py} +6 -2
- package/template/.cowork-flow/scripts/commands/party_mode_v2.py +1166 -0
- package/template/.cowork-flow/scripts/{resume.py → commands/resume.py} +6 -2
- package/template/.cowork-flow/scripts/{subagent.py → commands/subagent.py} +7 -3
- package/template/.cowork-flow/scripts/{task.py → commands/task.py} +189 -60
- package/template/.cowork-flow/scripts/common/__init__.py +1 -1
- package/template/.cowork-flow/scripts/common/core/__init__.py +1 -0
- package/template/.cowork-flow/scripts/common/{developer.py → core/developer.py} +1 -1
- package/template/.cowork-flow/scripts/common/gates/__init__.py +1 -0
- package/template/.cowork-flow/scripts/common/gates/coding_standards.py +210 -0
- package/template/.cowork-flow/scripts/common/gates/gates.py +66 -0
- package/template/.cowork-flow/scripts/common/gates/tdd_evidence.py +365 -0
- package/template/.cowork-flow/scripts/common/gates/test_intent.py +266 -0
- package/template/.cowork-flow/scripts/common/{validate_coding_standards.py → gates/validate_coding_standards.py} +23 -21
- package/template/.cowork-flow/scripts/common/gates/validate_implementation.py +243 -0
- package/template/.cowork-flow/scripts/common/gates/validate_rules.py +465 -0
- package/template/.cowork-flow/scripts/common/git/__init__.py +1 -0
- package/template/.cowork-flow/scripts/common/{git_context.py → git/git_context.py} +3 -3
- package/template/.cowork-flow/scripts/common/git/git_snapshot.py +83 -0
- package/template/.cowork-flow/scripts/common/task/__init__.py +1 -0
- package/template/.cowork-flow/scripts/common/{active_task.py → task/active_task.py} +1 -1
- package/template/.cowork-flow/scripts/common/{readiness.py → task/readiness.py} +1 -1
- package/template/.cowork-flow/scripts/common/task/state_machine.py +57 -0
- package/template/.cowork-flow/scripts/common/{task_utils.py → task/task_utils.py} +2 -2
- package/template/.cowork-flow/scripts/run.py +32 -25
- package/template/.cowork-flow/spec/contracts/index.md +11 -0
- package/template/.cowork-flow/spec/{party-mode-v2-board.md → contracts/party-mode-v2-board.md} +25 -0
- package/template/.cowork-flow/spec/{workflow-state-templates.md → contracts/workflow-state-templates.md} +1 -1
- package/template/.cowork-flow/spec/index.md +15 -0
- package/template/.cowork-flow/spec/{registry.json → runtime/contract-registry.json} +4 -16
- package/template/.cowork-flow/spec/runtime/index.md +10 -0
- package/template/.cowork-flow/spec/{rules.json → runtime/rules.json} +28 -14
- package/template/.cowork-flow/spec/{adapter.schema.json → schemas/adapter.schema.json} +1 -5
- package/template/.cowork-flow/spec/schemas/index.md +10 -0
- package/template/.cowork-flow/spec/schemas/party-mode-v2-actions.schema.json +90 -0
- package/template/.cowork-flow/spec/{rules.schema.json → schemas/rules.schema.json} +17 -4
- package/template/.cowork-flow/workflow.md +13 -13
- package/template/.opencode/agents/cowork-check.md +3 -3
- package/template/.opencode/agents/cowork-implement.md +3 -3
- package/template/.opencode/agents/cowork-research.md +3 -3
- package/template/.opencode/commands/party-mode-v2.md +5 -0
- package/template/.opencode/plugins/cowork-flow.js +17 -15
- package/template/AGENTS.md +4 -3
- package/template/.cowork-flow/scripts/common/entry_classifier.py +0 -122
- package/template/.cowork-flow/scripts/common/errors.py +0 -107
- package/template/.cowork-flow/scripts/common/validate_implementation.py +0 -195
- package/template/.cowork-flow/scripts/common/validate_rules.py +0 -302
- package/template/.cowork-flow/scripts/party_mode_v2.py +0 -646
- package/template/.cowork-flow/scripts/project_context.py +0 -230
- package/template/.cowork-flow/spec/entry-contract.md +0 -45
- package/template/.cowork-flow/spec/party-mode-v2-actions.schema.json +0 -43
- /package/template/.cowork-flow/scripts/common/{config.py → core/config.py} +0 -0
- /package/template/.cowork-flow/scripts/common/{execution_context.py → core/execution_context.py} +0 -0
- /package/template/.cowork-flow/scripts/common/{files.py → core/files.py} +0 -0
- /package/template/.cowork-flow/scripts/common/{paths.py → core/paths.py} +0 -0
- /package/template/.cowork-flow/scripts/common/{archive_utils.py → task/archive_utils.py} +0 -0
- /package/template/.cowork-flow/spec/{capabilities.md → contracts/capabilities.md} +0 -0
- /package/template/.cowork-flow/spec/{subagent-dispatch.md → contracts/subagent-dispatch.md} +0 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# cowork-flow
|
|
1
|
+
# cowork-flow
|
|
2
2
|
|
|
3
3
|
cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它把项目说明、任务流转、规格治理、开发计划和会话记录放在一套可复制的目录结构里,帮助团队在项目早期就建立清晰的工作闭环。
|
|
4
4
|
|
|
@@ -43,6 +43,12 @@ cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它
|
|
|
43
43
|
├── workflow.md
|
|
44
44
|
├── scripts/
|
|
45
45
|
├── spec/
|
|
46
|
+
│ ├── contracts/
|
|
47
|
+
│ ├── runtime/
|
|
48
|
+
│ ├── schemas/
|
|
49
|
+
│ ├── backend/
|
|
50
|
+
│ ├── frontend/
|
|
51
|
+
│ └── guides/
|
|
46
52
|
├── changes/
|
|
47
53
|
├── plans/
|
|
48
54
|
├── tasks/
|
|
@@ -65,19 +71,19 @@ cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它
|
|
|
65
71
|
固定角色 agent 定义,包含 `cowork-research`、`cowork-implement` 和 `cowork-check`,以及对 Codex 默认 `worker`、`default`、`explorer` 的项目级防漂移约束。主会话负责计划与收口,并通过 host adapter 派发固定 agent;正式派发必须先创建 runtime context,再把 `cowork_runtime_context_id` 和 `cowork_host_context_key` 传给子代理。
|
|
66
72
|
|
|
67
73
|
`template/.codex/config.toml`、`template/.codex/hooks.json`、`template/.codex/hooks/`
|
|
68
|
-
Codex 项目级配置与每轮上下文注入入口。hook
|
|
74
|
+
Codex 项目级配置与每轮上下文注入入口。hook 会先解析 runtime context,再读取当前 session task、`.cowork-flow/spec/contracts/workflow-state-templates.md` 中的 `workflow-state` 片段和 `codex.dispatch_mode`,把流程状态注入到当前轮对话。注入的 `codex-dispatch-mode` 只是主会话调度提示,不代表当前线程身份。
|
|
69
75
|
|
|
70
76
|
`template/CLAUDE.md`、`template/.claude/settings.json`、`template/.claude/agents/`、`template/.claude/skills/`、`template/.claude/commands/`、`template/.claude/hooks/`
|
|
71
77
|
Claude Code 项目级记忆、hook、固定 agent、skills 和 slash command。`CLAUDE.md` 显式导入 `AGENTS.md`。`.claude/settings.json` 注册 `UserPromptSubmit` 和 `SessionStart` hook,注入当前 workflow state 与 contract digest。固定 agent 通过 `.cowork-flow/run subagent init` 生成 runtime context,并在 prompt、env 或 metadata transport 中传递 `cowork_runtime_context_id`;hook 绑定成功后才进入叶子执行,绑定失败则 fail closed,避免被项目 bootstrap 或无任务首屏上下文拉偏。Claude Code 不自动加载 `.agents/skills/`,所以项目技能要放进 `.claude/skills/`。
|
|
72
78
|
|
|
73
79
|
`template/.opencode/agents/`、`template/.opencode/commands/`、`template/.opencode/plugins/`
|
|
74
|
-
OpenCode 项目级固定 agent、slash command 和系统上下文注入插件。插件会读取 `.cowork-flow/spec/registry.json`,注入短 contract digest。
|
|
80
|
+
OpenCode 项目级固定 agent、slash command 和系统上下文注入插件。插件会读取 `.cowork-flow/spec/runtime/contract-registry.json`,注入短 contract digest。
|
|
75
81
|
|
|
76
82
|
`template/.cowork-flow/`
|
|
77
83
|
工作流目录,包含流程说明、任务状态、开发者工作区、项目规范、行为变更规格、实现计划和辅助脚本。`.cowork-flow/config.yaml` 只承载真实接线的 session/journal, Codex hint, and task lifecycle hook settings。
|
|
78
84
|
|
|
79
85
|
`template/.cowork-flow/spec/`
|
|
80
|
-
|
|
86
|
+
项目规范目录。`contracts/` 存人读 workflow/host/agent 合同,`runtime/` 存运行时读取的规则和 contract registry,`schemas/` 存 JSON Schema,`backend/`、`frontend/`、`guides/` 存工程规范和思考指引。接入时应按项目事实保留、改写或删除对应规范。
|
|
81
87
|
|
|
82
88
|
`template/.cowork-flow/changes/`
|
|
83
89
|
由 `change.py` 管理 proposal、design、behavior specs 和归档,不维护实现 checklist。
|
|
@@ -93,7 +99,7 @@ OpenCode 项目级固定 agent、slash command 和系统上下文注入插件。
|
|
|
93
99
|
npx cowork-flow init ./my-project --platform codex
|
|
94
100
|
```
|
|
95
101
|
|
|
96
|
-
`init` 会显式要求平台和开发者身份。平台可选 `codex`、`opencode`、`claude-code`、`all
|
|
102
|
+
`init` 会显式要求平台和开发者身份。平台可选 `codex`、`opencode`、`claude-code`、`all`。交互式终端会提示输入;脚本或 CI 请传入:
|
|
97
103
|
|
|
98
104
|
```bash
|
|
99
105
|
npx cowork-flow init ./my-project --platform codex --developer <your-name>
|
|
@@ -128,7 +134,7 @@ npx cowork-flow --help
|
|
|
128
134
|
cowork-flow init ./my-project --platform codex
|
|
129
135
|
```
|
|
130
136
|
|
|
131
|
-
`init` 会直接复制模板中的通用 `.cowork-flow/`,并按 `--platform` 只复制对应 host 资产:`codex` 复制 `.codex/`、`.agents/skills/` 与 `.cowork-flow/adapters/codex/`,`opencode` 复制 `.opencode/`、`.agents/skills/` 与 `.cowork-flow/adapters/opencode/`,`claude-code` 复制 `CLAUDE.md`、`.claude/`(含 `.claude/settings.json`、`.claude/hooks/`、`.claude/skills/`)与 `.cowork-flow/adapters/claude-code/`,不复制 `.agents/skills/`。`all` 或 `--platform codex,opencode,claude-code` 同时复制三者和 `.agents/skills
|
|
137
|
+
`init` 会直接复制模板中的通用 `.cowork-flow/`,并按 `--platform` 只复制对应 host 资产:`codex` 复制 `.codex/`、`.agents/skills/` 与 `.cowork-flow/adapters/codex/`,`opencode` 复制 `.opencode/`、`.agents/skills/` 与 `.cowork-flow/adapters/opencode/`,`claude-code` 复制 `CLAUDE.md`、`.claude/`(含 `.claude/settings.json`、`.claude/hooks/`、`.claude/skills/`)与 `.cowork-flow/adapters/claude-code/`,不复制 `.agents/skills/`。`all` 或 `--platform codex,opencode,claude-code` 同时复制三者和 `.agents/skills/`。它还会初始化 `.cowork-flow/.developer` 与 `.cowork-flow/workspace/<developer>/`。交互式终端会先显示 checkbox 多选界面选择平台,再提示开发者名称;非交互式环境必须传入 `--platform <codex|opencode|claude-code|all>` 与 `--developer <name>`。`init` 不会复制额外技能包。
|
|
132
138
|
|
|
133
139
|
初始化到当前项目:
|
|
134
140
|
|
|
@@ -163,7 +169,7 @@ cowork-flow sync .
|
|
|
163
169
|
cowork-flow sync . --dry-run
|
|
164
170
|
```
|
|
165
171
|
|
|
166
|
-
`sync` 会自动识别目标项目已安装的 host 目录:只有 `.codex/` 时只同步 Codex 资产,只有 `.opencode/` 时只同步 OpenCode 资产,两者都有时同步两者;对应 `.cowork-flow/adapters/<host>/` 也按识别出的平台同步。检测到 Codex 或 OpenCode 时会刷新 `.agents/skills/`;Claude Code-only 项目只刷新 `.claude/settings.json`、`.claude/hooks/`、`.claude/skills/`,不会创建 `.agents/skills/`。通用部分默认刷新 `.cowork-flow/scripts/`、`.cowork-flow/spec/workflow-state-templates.md`,以及 `AGENTS.md` 和 `CLAUDE.md` 中的 `<!-- COWORK-FLOW:START --> ... <!-- COWORK-FLOW:END -->` 托管块,保留托管块之外的项目自定义内容。`.cowork-flow/config.yaml`、`.cowork-flow/workflow.md`、除 `workflow-state-templates.md` 外的 `.cowork-flow/spec/`、任务、计划、变更和 workspace 记录默认受保护。只有明确传入 `--force` 时才整文件覆盖保护文件。
|
|
172
|
+
`sync` 会自动识别目标项目已安装的 host 目录:只有 `.codex/` 时只同步 Codex 资产,只有 `.opencode/` 时只同步 OpenCode 资产,两者都有时同步两者;对应 `.cowork-flow/adapters/<host>/` 也按识别出的平台同步。检测到 Codex 或 OpenCode 时会刷新 `.agents/skills/`;Claude Code-only 项目只刷新 `.claude/settings.json`、`.claude/hooks/`、`.claude/skills/`,不会创建 `.agents/skills/`。通用部分默认刷新 `.cowork-flow/scripts/`、`.cowork-flow/spec/contracts/workflow-state-templates.md`,以及 `AGENTS.md` 和 `CLAUDE.md` 中的 `<!-- COWORK-FLOW:START --> ... <!-- COWORK-FLOW:END -->` 托管块,保留托管块之外的项目自定义内容。`.cowork-flow/config.yaml`、`.cowork-flow/workflow.md`、除 `workflow-state-templates.md` 外的 `.cowork-flow/spec/`、任务、计划、变更和 workspace 记录默认受保护。只有明确传入 `--force` 时才整文件覆盖保护文件。
|
|
167
173
|
|
|
168
174
|
## 常用入口
|
|
169
175
|
|
|
@@ -179,6 +185,16 @@ cowork-flow sync . --dry-run
|
|
|
179
185
|
下面示例使用 macOS / Linux 写法;Windows 原生命令行中把
|
|
180
186
|
`./.cowork-flow/run` 替换为 `.\.cowork-flow\run.cmd`。
|
|
181
187
|
|
|
188
|
+
当前主流程以 `.cowork-flow/workflow.md` 为准。默认路径是:
|
|
189
|
+
|
|
190
|
+
```text
|
|
191
|
+
changes -> brainstorming -> read spec -> plan -> tasks -> implement -> check -> complete
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
L0 文档、格式、小范围重构或测试补充可简化为
|
|
195
|
+
`brainstorming -> read spec -> implement -> check -> complete`;L1/L2 在完成后继续
|
|
196
|
+
`archive -> add session`。
|
|
197
|
+
|
|
182
198
|
初始化或查看开发者身份:
|
|
183
199
|
|
|
184
200
|
```bash
|
|
@@ -190,7 +206,6 @@ cowork-flow sync . --dry-run
|
|
|
190
206
|
|
|
191
207
|
```bash
|
|
192
208
|
./.cowork-flow/run get-context
|
|
193
|
-
./.cowork-flow/run project-context refresh
|
|
194
209
|
./.cowork-flow/run task list
|
|
195
210
|
./.cowork-flow/run task next
|
|
196
211
|
```
|
|
@@ -210,18 +225,35 @@ cowork-flow sync . --dry-run
|
|
|
210
225
|
./.cowork-flow/run task start <task-dir>
|
|
211
226
|
```
|
|
212
227
|
|
|
213
|
-
`task next`
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
`project-context refresh` 会创建或刷新 `.cowork-flow/project-context.md`。生成块由
|
|
218
|
-
本地项目文件确定,`Manual Notes` 区保留人工补充;该文件是项目索引,不替代
|
|
219
|
-
`AGENTS.md`、`.cowork-flow/workflow.md` 或 `.cowork-flow/spec/`。
|
|
228
|
+
`task next` 只读,不推进状态。它根据当前会话任务和 `task.json.status`
|
|
229
|
+
报告当前任务、阻塞项和下一条安全命令;主会话在启动工作、派发固定代理、
|
|
230
|
+
进入检查、归档或记录 session 前都应先看它。
|
|
220
231
|
|
|
221
232
|
L2 任务的 readiness gate 会在 `task start` 前阻塞缺失的 proposal/spec/design、
|
|
222
233
|
计划、任务链接、边界、假设、验收标准或 verification commands;同一 blocker
|
|
223
234
|
会出现在 `task next` 输出中。
|
|
224
235
|
|
|
236
|
+
任务状态流转:
|
|
237
|
+
|
|
238
|
+
```mermaid
|
|
239
|
+
stateDiagram-v2
|
|
240
|
+
[*] --> NoTask
|
|
241
|
+
state "无当前任务" as NoTask
|
|
242
|
+
state "planning" as Planning
|
|
243
|
+
state "in_progress" as InProgress
|
|
244
|
+
state "review" as Review
|
|
245
|
+
state "completed" as Completed
|
|
246
|
+
state "已归档" as Archived
|
|
247
|
+
|
|
248
|
+
NoTask --> Planning: task create
|
|
249
|
+
Planning --> InProgress: task start
|
|
250
|
+
InProgress --> Review: task review
|
|
251
|
+
Review --> Completed: task complete
|
|
252
|
+
Completed --> Archived: task archive
|
|
253
|
+
Completed --> NoTask: task finish
|
|
254
|
+
Archived --> [*]
|
|
255
|
+
```
|
|
256
|
+
|
|
225
257
|
任务状态由阶段命令推进,`task next` 只读取状态:
|
|
226
258
|
|
|
227
259
|
| 阶段 | 命令 | `task.json.status` |
|
|
@@ -230,11 +262,13 @@ L2 任务的 readiness gate 会在 `task start` 前阻塞缺失的 proposal/spec
|
|
|
230
262
|
| 开始执行 | `task start <task-dir>` | `in_progress` |
|
|
231
263
|
| 进入检查 | `task review [task-dir]` | `review` |
|
|
232
264
|
| 检查完成 | `task complete [task-dir]` | `completed` |
|
|
265
|
+
| 归档任务 | `task archive <task-name>` | 归档副本保持 `completed` |
|
|
233
266
|
| 清会话指针 | `task finish` | 不改变状态 |
|
|
234
267
|
|
|
235
268
|
执行 plan 时使用固定 cowork agents:
|
|
236
269
|
|
|
237
|
-
|
|
270
|
+
主会话负责创建/启动任务、维护计划与收口验证;实现和检查默认通过当前 Host Adapter
|
|
271
|
+
派发给固定角色 agent。固定 agent 是叶子执行者,不能再派发其他 agent,也不能替代主会话完成归档、记录 session 或提交。
|
|
238
272
|
|
|
239
273
|
```text
|
|
240
274
|
./.cowork-flow/run subagent init --role implement --agent-type cowork-implement --execution-task-dir <task-dir> --title "<title>"
|
|
@@ -249,7 +283,7 @@ cowork_host_context_key: <host_context_key>
|
|
|
249
283
|
|
|
250
284
|
子代理首步执行 `./.cowork-flow/run subagent bind <runtime_context_id> <host_context_key>`;主会话验收前必须确认 runtime context 中 `status=bound` 且 `bound_context_key` 匹配。默认角色为 `cowork-research`、`cowork-implement`、`cowork-check`,任务上下文来自已绑定 runtime context,而不是 prompt 形状。
|
|
251
285
|
|
|
252
|
-
|
|
286
|
+
Host hook/plugin 启用后,每轮会自动注入 workflow state,其中包含入口分类、当前任务、状态来源和下一步流程提示。状态文本来自 `.cowork-flow/spec/contracts/workflow-state-templates.md`;`workflow.md` 只描述流程,不内联状态片段。hook 不替代主会话验收;它只负责把 task 状态和 workflow gate 放进上下文。
|
|
253
287
|
|
|
254
288
|
记录 session:
|
|
255
289
|
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -195,7 +195,7 @@ function initialIndexContent(name) {
|
|
|
195
195
|
- Sessions are appended to the journal file
|
|
196
196
|
- A new journal file is created automatically after the current file exceeds 2000 lines
|
|
197
197
|
- Use \`add_session.py\` to record sessions
|
|
198
|
-
- New records use English text;
|
|
198
|
+
- New records use English text; existing records can remain as they are
|
|
199
199
|
`;
|
|
200
200
|
}
|
|
201
201
|
|
package/src/commands/update.js
CHANGED
|
@@ -6,10 +6,8 @@ import {
|
|
|
6
6
|
} from '../lib/package-info.js';
|
|
7
7
|
|
|
8
8
|
function validateUpdateArgs(args) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
throw new Error(`Unknown update option: ${arg}`);
|
|
12
|
-
}
|
|
9
|
+
if (args.length > 0) {
|
|
10
|
+
throw new Error(`Unknown update option: ${args[0]}`);
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
13
|
|
package/src/lib/copy-template.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { constants } from 'node:fs';
|
|
2
|
-
import { access, chmod, copyFile, mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { access, chmod, copyFile, mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { dirname, join, relative } from 'node:path';
|
|
4
4
|
|
|
5
5
|
import { templateRoot } from './paths.js';
|
|
@@ -96,7 +96,42 @@ const SAFE_SYNC_FILES = new Set([
|
|
|
96
96
|
'.cowork-flow/.version',
|
|
97
97
|
'.cowork-flow/run',
|
|
98
98
|
'.cowork-flow/run.cmd',
|
|
99
|
-
'.cowork-flow/spec/workflow-state-templates.md'
|
|
99
|
+
'.cowork-flow/spec/contracts/workflow-state-templates.md'
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
const OBSOLETE_SYNC_FILES = new Set([
|
|
103
|
+
'.cowork-flow/project-context.md',
|
|
104
|
+
'.cowork-flow/scripts/add_session.py',
|
|
105
|
+
'.cowork-flow/scripts/change.py',
|
|
106
|
+
'.cowork-flow/scripts/doctor.py',
|
|
107
|
+
'.cowork-flow/scripts/get_context.py',
|
|
108
|
+
'.cowork-flow/scripts/get_developer.py',
|
|
109
|
+
'.cowork-flow/scripts/init_developer.py',
|
|
110
|
+
'.cowork-flow/scripts/party_mode_v2.py',
|
|
111
|
+
'.cowork-flow/scripts/project_context.py',
|
|
112
|
+
'.cowork-flow/scripts/resume.py',
|
|
113
|
+
'.cowork-flow/scripts/subagent.py',
|
|
114
|
+
'.cowork-flow/scripts/task.py',
|
|
115
|
+
'.cowork-flow/scripts/common/active_task.py',
|
|
116
|
+
'.cowork-flow/scripts/common/archive_utils.py',
|
|
117
|
+
'.cowork-flow/scripts/common/coding_standards.py',
|
|
118
|
+
'.cowork-flow/scripts/common/config.py',
|
|
119
|
+
'.cowork-flow/scripts/common/developer.py',
|
|
120
|
+
'.cowork-flow/scripts/common/execution_context.py',
|
|
121
|
+
'.cowork-flow/scripts/common/files.py',
|
|
122
|
+
'.cowork-flow/scripts/common/gates.py',
|
|
123
|
+
'.cowork-flow/scripts/common/git_context.py',
|
|
124
|
+
'.cowork-flow/scripts/common/git_snapshot.py',
|
|
125
|
+
'.cowork-flow/scripts/common/paths.py',
|
|
126
|
+
'.cowork-flow/scripts/common/readiness.py',
|
|
127
|
+
'.cowork-flow/scripts/common/state_machine.py',
|
|
128
|
+
'.cowork-flow/scripts/common/task_utils.py',
|
|
129
|
+
'.cowork-flow/scripts/common/tdd_evidence.py',
|
|
130
|
+
'.cowork-flow/scripts/common/test_intent.py',
|
|
131
|
+
'.cowork-flow/scripts/common/validate_coding_standards.py',
|
|
132
|
+
'.cowork-flow/scripts/common/validate_implementation.py',
|
|
133
|
+
'.cowork-flow/scripts/common/validate_rules.py',
|
|
134
|
+
'.cowork-flow/spec/contracts/entry-contract.md'
|
|
100
135
|
]);
|
|
101
136
|
|
|
102
137
|
const COWORK_FLOW_START = '<!-- COWORK-FLOW:START -->';
|
|
@@ -200,6 +235,13 @@ export async function buildSyncPlan(targetDir, options = {}) {
|
|
|
200
235
|
}
|
|
201
236
|
}
|
|
202
237
|
|
|
238
|
+
for (const file of OBSOLETE_SYNC_FILES) {
|
|
239
|
+
const destination = join(targetDir, file);
|
|
240
|
+
if (await pathExists(destination)) {
|
|
241
|
+
actions.push({ action: 'delete', source: null, destination, relativePath: file });
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
203
245
|
actions.push({
|
|
204
246
|
action: 'update',
|
|
205
247
|
source: null,
|
|
@@ -226,7 +268,7 @@ export async function detectInstalledPlatforms(targetDir) {
|
|
|
226
268
|
}
|
|
227
269
|
|
|
228
270
|
export function summarizePlan(actions, dryRun = false) {
|
|
229
|
-
const counts = { create: 0, update: 0, skip: 0, protected: 0 };
|
|
271
|
+
const counts = { create: 0, update: 0, skip: 0, protected: 0, delete: 0 };
|
|
230
272
|
for (const action of actions) {
|
|
231
273
|
counts[action.action] += 1;
|
|
232
274
|
}
|
|
@@ -234,7 +276,8 @@ export function summarizePlan(actions, dryRun = false) {
|
|
|
234
276
|
const prefix = dryRun ? 'dry-run ' : '';
|
|
235
277
|
const createLabel = dryRun ? 'would-create' : 'created';
|
|
236
278
|
const updateLabel = dryRun ? 'would-update' : 'updated';
|
|
237
|
-
|
|
279
|
+
const deleteLabel = dryRun ? 'would-delete' : 'deleted';
|
|
280
|
+
return `${prefix}${createLabel}=${counts.create} ${updateLabel}=${counts.update} ${deleteLabel}=${counts.delete} skipped=${counts.skip} protected=${counts.protected}\n`;
|
|
238
281
|
}
|
|
239
282
|
|
|
240
283
|
export async function applyPlan(actions, options = {}) {
|
|
@@ -246,6 +289,10 @@ export async function applyPlan(actions, options = {}) {
|
|
|
246
289
|
if (item.action === 'skip' || item.action === 'protected') {
|
|
247
290
|
continue;
|
|
248
291
|
}
|
|
292
|
+
if (item.action === 'delete') {
|
|
293
|
+
await rm(item.destination, { force: true });
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
249
296
|
|
|
250
297
|
await mkdir(dirname(item.destination), { recursive: true });
|
|
251
298
|
if (item.content !== undefined) {
|
package/src/lib/platforms.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
export const SUPPORTED_PLATFORMS = ['codex', 'opencode', 'claude-code'];
|
|
2
2
|
|
|
3
|
-
const LEGACY_BOTH_PLATFORMS = ['codex', 'opencode'];
|
|
4
|
-
|
|
5
3
|
const PLATFORM_ALIASES = new Map([
|
|
6
4
|
['all', SUPPORTED_PLATFORMS],
|
|
7
|
-
['both', LEGACY_BOTH_PLATFORMS],
|
|
8
5
|
['codex', ['codex']],
|
|
9
6
|
['opencode', ['opencode']],
|
|
10
7
|
['claude', ['claude-code']],
|
|
@@ -15,6 +15,7 @@ Use this immediately before code edits.
|
|
|
15
15
|
4. Active task `implement.jsonl`
|
|
16
16
|
5. Relevant `.cowork-flow/spec/*/index.md`
|
|
17
17
|
6. Any exact files named by the task, plan, or user
|
|
18
|
+
7. If the task changes behavior, locate or create `tdd.jsonl` evidence before implementation.
|
|
18
19
|
|
|
19
20
|
Do not bulk-load unrelated tasks, archived sessions, or every spec file.
|
|
20
21
|
|
|
@@ -16,6 +16,7 @@ Use this after implementation and before `finish-work`.
|
|
|
16
16
|
5. Review test intent: reject shallow tests that do not fail for meaningful behavior breaks.
|
|
17
17
|
6. Run focused tests that would fail if the changed behavior broke.
|
|
18
18
|
7. Run broader validation when the change touches shared runtime, templates, packaging, or public workflow.
|
|
19
|
+
8. Report `test_intent_review` with the key tests that defend PRD acceptance behavior.
|
|
19
20
|
|
|
20
21
|
## Report
|
|
21
22
|
|
|
@@ -26,6 +26,7 @@ Always use the runtime controller:
|
|
|
26
26
|
.cowork-flow/run party-v2 post
|
|
27
27
|
.cowork-flow/run party-v2 respond
|
|
28
28
|
.cowork-flow/run party-v2 advance
|
|
29
|
+
.cowork-flow/run party-v2 record-action-result
|
|
29
30
|
.cowork-flow/run party-v2 finalize
|
|
30
31
|
```
|
|
31
32
|
|
|
@@ -38,6 +39,7 @@ Do not bypass a runtime rejection by manually accepting child output. Runtime va
|
|
|
38
39
|
- Historical board state is runtime-private and may be used only for audit or final reports.
|
|
39
40
|
- Use at least three child agents unless the effective runtime config explicitly allows a different value.
|
|
40
41
|
- The runtime emits host-neutral next actions. The active Host Adapter or moderator executes them for Codex, Claude Code, or OpenCode.
|
|
42
|
+
- Host action results must be recorded back through `record-action-result` so `agents.json`, audit logs, and action history can prove lifecycle state.
|
|
41
43
|
|
|
42
44
|
## Child Response Rules
|
|
43
45
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tdd
|
|
3
|
+
description: Use when implementing behavior changes, bug fixes, state transitions, protocols, CLI/runtime contracts, data format changes, or error handling that can be tested before implementation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# TDD
|
|
7
|
+
|
|
8
|
+
Use this before editing behavior-changing code.
|
|
9
|
+
|
|
10
|
+
## Red-Green-Refactor
|
|
11
|
+
|
|
12
|
+
1. Map the task PRD acceptance criteria to stable IDs such as `AC-001`.
|
|
13
|
+
2. Write the smallest meaningful failing test first.
|
|
14
|
+
3. Run the red command and confirm it fails because the target behavior is missing or wrong.
|
|
15
|
+
4. Implement the smallest change that makes the behavior pass.
|
|
16
|
+
5. Run the green command and relevant broader verification.
|
|
17
|
+
6. Refactor only after the behavior is green.
|
|
18
|
+
|
|
19
|
+
Do not count shallow tests as TDD evidence. Tests that only import code, assert a function exists, assert `True`, count mocks without behavior, or mirror implementation details do not satisfy red-green-refactor.
|
|
20
|
+
|
|
21
|
+
## Evidence
|
|
22
|
+
|
|
23
|
+
Record TDD proof in `<task>/tdd.jsonl`. Each evidence line is one JSON object:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"acceptanceId": "AC-001",
|
|
28
|
+
"testFile": "tests/test_example.py",
|
|
29
|
+
"testName": "test_behavior",
|
|
30
|
+
"redCommand": "python -m unittest tests.test_example.TestCase.test_behavior -v",
|
|
31
|
+
"redExitCode": 1,
|
|
32
|
+
"redOutputExcerpt": "expected failure excerpt",
|
|
33
|
+
"failureReason": "target behavior was not implemented",
|
|
34
|
+
"whyThisTestMatters": "explains which user-visible behavior would regress",
|
|
35
|
+
"greenCommand": "python -m unittest tests.test_example.TestCase.test_behavior -v",
|
|
36
|
+
"greenExitCode": 0,
|
|
37
|
+
"broaderVerification": "python -m unittest tests.test_example -v"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Every evidence record must map to a PRD `acceptanceId`. The red failure must be about the target behavior, not syntax, import, environment, fixture, or setup failure.
|
|
42
|
+
|
|
43
|
+
`testName` must resolve to the exact behavior test in `testFile`. Use one of:
|
|
44
|
+
`test_method`, `ClassName.test_method`, or `module.ClassName.test_method`.
|
|
45
|
+
Do not point evidence at a class, module, or a name that only exists in a command string.
|
|
46
|
+
|
|
47
|
+
## Exemption
|
|
48
|
+
|
|
49
|
+
Pure documentation, comment-only, or formatting-only tasks may use an exemption record instead of red/green evidence:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"type": "exemption",
|
|
54
|
+
"acceptanceId": "AC-001",
|
|
55
|
+
"exemptionType": "docs-only",
|
|
56
|
+
"reason": "Only documentation wording changed; runtime behavior is untouched.",
|
|
57
|
+
"verificationCommand": "git diff --check"
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Do not use an exemption for runtime, CLI, protocol, state, data format, permission, or error-handling changes.
|
|
@@ -42,6 +42,7 @@ Start with:
|
|
|
42
42
|
- Include a failing test before implementation when behavior can be tested.
|
|
43
43
|
- Do not add shallow tests just to satisfy process. Avoid tests that only assert existence, mirror implementation details, count mocks without behavior, or snapshot empty structure.
|
|
44
44
|
- For complex problems, test depth first: cover invariants, cross-layer contracts, state transitions, error boundaries, and real regression paths before narrow unit cases.
|
|
45
|
+
- Map each behavior-changing test to a stable PRD acceptance ID and note where `tdd.jsonl` will record the red-green evidence.
|
|
45
46
|
- Avoid placeholders such as TODO, TBD, "handle edge cases", or "write tests".
|
|
46
47
|
- Keep root/template parity explicit when both copies exist.
|
|
47
48
|
|
|
@@ -24,9 +24,9 @@ state is injected. The first child step must still run:
|
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
If the explicit bind fails, or if the bound context is missing, closed, invalid,
|
|
27
|
-
or names another agent type, report `needs_context` and stop. Do not
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
or names another agent type, report `needs_context` and stop. Do not infer
|
|
28
|
+
subagent identity from prompt shape; runtime context binding is the only formal
|
|
29
|
+
signal.
|
|
30
30
|
|
|
31
31
|
Rules:
|
|
32
32
|
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cowork-implement
|
|
3
3
|
description: Cowork-flow implementation fixed subagent.
|
|
4
|
-
|
|
5
|
-
permission:
|
|
6
|
-
edit: ask
|
|
7
|
-
bash: ask
|
|
8
|
-
task: deny
|
|
9
|
-
todowrite: deny
|
|
10
|
-
external_directory: deny
|
|
4
|
+
tools: Read, Write, Edit, MultiEdit, Grep, Glob, LS, Bash
|
|
11
5
|
---
|
|
12
6
|
|
|
13
|
-
You are the `cowork-implement` fixed subagent for
|
|
7
|
+
You are the `cowork-implement` fixed subagent for Claude Code.
|
|
14
8
|
You are a leaf executor and must not invoke other agents.
|
|
15
9
|
|
|
16
10
|
Formal `cowork-implement` work requires a bound runtime context. The prompt,
|
|
@@ -21,7 +15,7 @@ cowork_runtime_context_id: <runtime_context_id>
|
|
|
21
15
|
cowork_host_context_key: <host_context_key>
|
|
22
16
|
```
|
|
23
17
|
|
|
24
|
-
The
|
|
18
|
+
The hook may bind that id to
|
|
25
19
|
`.cowork-flow/.runtime/subagents/<runtime_context_id>.json` before workflow
|
|
26
20
|
state is injected. The first child step must still run:
|
|
27
21
|
|
|
@@ -30,9 +24,9 @@ state is injected. The first child step must still run:
|
|
|
30
24
|
```
|
|
31
25
|
|
|
32
26
|
If the explicit bind fails, or if the bound context is missing, closed, invalid,
|
|
33
|
-
or names another agent type, report `needs_context` and stop. Do not
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
or names another agent type, report `needs_context` and stop. Do not infer
|
|
28
|
+
subagent identity from prompt shape; runtime context binding is the only formal
|
|
29
|
+
signal.
|
|
36
30
|
|
|
37
31
|
---
|
|
38
32
|
|
|
@@ -194,6 +188,6 @@ Rules:
|
|
|
194
188
|
and each JSONL `file` entry.
|
|
195
189
|
- Keep edits inside the assigned scope.
|
|
196
190
|
- Report changed files and exact verification commands.
|
|
197
|
-
- Do not use the
|
|
191
|
+
- Do not use the Task tool or invoke subagents.
|
|
198
192
|
- Do not run task start, task finish, task archive, unscoped resume, commit, or
|
|
199
193
|
push.
|
|
@@ -24,9 +24,9 @@ state is injected. The first child step must still run:
|
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
If the explicit bind fails, or if the bound context is missing, closed, invalid,
|
|
27
|
-
or names another agent type, report `needs_context` and stop. Do not
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
or names another agent type, report `needs_context` and stop. Do not infer
|
|
28
|
+
subagent identity from prompt shape; runtime context binding is the only formal
|
|
29
|
+
signal.
|
|
30
30
|
|
|
31
31
|
Rules:
|
|
32
32
|
|
|
@@ -17,18 +17,9 @@ TAG_RE = re.compile(
|
|
|
17
17
|
)
|
|
18
18
|
DEFAULT_CONTRACT_REGISTRY = {
|
|
19
19
|
"contracts": [
|
|
20
|
-
{
|
|
21
|
-
"id": "COWORK_ENTRY_CONTRACT_V1",
|
|
22
|
-
"path": ".cowork-flow/spec/entry-contract.md",
|
|
23
|
-
"digest": [
|
|
24
|
-
"Classify main-session requests before task start, resume, archive, or commit.",
|
|
25
|
-
"Runtime context, not prompt labels, identifies formal subagent sessions.",
|
|
26
|
-
],
|
|
27
|
-
"readWhen": ["before task start/resume/archive", "when prompt and bootstrap text conflict"],
|
|
28
|
-
},
|
|
29
20
|
{
|
|
30
21
|
"id": "RUNTIME_CONTEXT_DISPATCH_V2",
|
|
31
|
-
"path": ".cowork-flow/spec/subagent-dispatch.md",
|
|
22
|
+
"path": ".cowork-flow/spec/contracts/subagent-dispatch.md",
|
|
32
23
|
"digest": [
|
|
33
24
|
"Formal subagent work is keyed by cowork_runtime_context_id.",
|
|
34
25
|
"Explicit shim bind records bound_context_key before formal output is accepted.",
|
|
@@ -88,7 +79,7 @@ def _normalize_hook_input(hook_input: dict[str, Any]) -> dict[str, Any]:
|
|
|
88
79
|
|
|
89
80
|
|
|
90
81
|
def _load_breadcrumbs(root: Path) -> dict[str, str]:
|
|
91
|
-
workflow = root / ".cowork-flow" / "spec" / "workflow-state-templates.md"
|
|
82
|
+
workflow = root / ".cowork-flow" / "spec" / "contracts" / "workflow-state-templates.md"
|
|
92
83
|
try:
|
|
93
84
|
text = workflow.read_text(encoding="utf-8")
|
|
94
85
|
except OSError:
|
|
@@ -102,16 +93,23 @@ def _as_string_list(value: Any) -> list[str]:
|
|
|
102
93
|
return [item for item in value if isinstance(item, str) and item.strip()]
|
|
103
94
|
|
|
104
95
|
|
|
105
|
-
def _load_contract_registry(root: Path) -> list[dict[str, Any]]:
|
|
106
|
-
registry_file = root / ".cowork-flow" / "spec" / "registry.json"
|
|
96
|
+
def _load_contract_registry(root: Path) -> tuple[list[dict[str, Any]], str | None]:
|
|
97
|
+
registry_file = root / ".cowork-flow" / "spec" / "runtime" / "contract-registry.json"
|
|
107
98
|
try:
|
|
108
99
|
data = json.loads(registry_file.read_text(encoding="utf-8"))
|
|
109
|
-
except
|
|
100
|
+
except OSError:
|
|
110
101
|
data = DEFAULT_CONTRACT_REGISTRY
|
|
102
|
+
warning = f"contract registry unavailable at {registry_file}; using fallback digest"
|
|
103
|
+
except json.JSONDecodeError:
|
|
104
|
+
data = DEFAULT_CONTRACT_REGISTRY
|
|
105
|
+
warning = f"contract registry invalid at {registry_file}; using fallback digest"
|
|
106
|
+
else:
|
|
107
|
+
warning = None
|
|
111
108
|
contracts = data.get("contracts") if isinstance(data, dict) else None
|
|
112
109
|
if not isinstance(contracts, list):
|
|
113
110
|
contracts = DEFAULT_CONTRACT_REGISTRY["contracts"]
|
|
114
|
-
|
|
111
|
+
warning = warning or f"contract registry has no contracts array at {registry_file}; using fallback digest"
|
|
112
|
+
return [contract for contract in contracts if isinstance(contract, dict)], warning
|
|
115
113
|
|
|
116
114
|
|
|
117
115
|
def _contract_fingerprint(root: Path, contracts: list[dict[str, Any]]) -> str:
|
|
@@ -129,13 +127,15 @@ def _contract_fingerprint(root: Path, contracts: list[dict[str, Any]]) -> str:
|
|
|
129
127
|
|
|
130
128
|
|
|
131
129
|
def _build_contract_digest(root: Path) -> str:
|
|
132
|
-
contracts = _load_contract_registry(root)
|
|
130
|
+
contracts, warning = _load_contract_registry(root)
|
|
133
131
|
fingerprint = _contract_fingerprint(root, contracts)
|
|
134
132
|
lines = [
|
|
135
133
|
'<cowork-runtime host="claude-code" adapter="claude-code.hooks">',
|
|
136
134
|
f'<contract-digest fingerprint="{fingerprint}">',
|
|
137
135
|
"policy: repeat this short digest every hook; read full spec files only before listed actions.",
|
|
138
136
|
]
|
|
137
|
+
if warning:
|
|
138
|
+
lines.append(f"warning: {warning}")
|
|
139
139
|
for contract in contracts:
|
|
140
140
|
contract_id = contract.get("id")
|
|
141
141
|
path = contract.get("path")
|
|
@@ -161,7 +161,7 @@ def _load_common(root: Path) -> None:
|
|
|
161
161
|
def _get_active_task(root: Path, hook_input: dict[str, Any]) -> tuple[str | None, str, str]:
|
|
162
162
|
_load_common(root)
|
|
163
163
|
try:
|
|
164
|
-
from common.active_task import get_active_task # type: ignore[import-not-found]
|
|
164
|
+
from common.task.active_task import get_active_task # type: ignore[import-not-found]
|
|
165
165
|
except Exception:
|
|
166
166
|
return None, "no_task", "unavailable"
|
|
167
167
|
|
|
@@ -185,7 +185,7 @@ def _get_active_task(root: Path, hook_input: dict[str, Any]) -> tuple[str | None
|
|
|
185
185
|
def _resolve_runtime_context(root: Path, hook_input: dict[str, Any]) -> tuple[dict[str, Any] | None, str | None]:
|
|
186
186
|
_load_common(root)
|
|
187
187
|
try:
|
|
188
|
-
from common.active_task import ( # type: ignore[import-not-found]
|
|
188
|
+
from common.task.active_task import ( # type: ignore[import-not-found]
|
|
189
189
|
bind_runtime_context,
|
|
190
190
|
read_runtime_context,
|
|
191
191
|
resolve_runtime_context_id,
|
|
@@ -15,6 +15,7 @@ Use this immediately before code edits.
|
|
|
15
15
|
4. Active task `implement.jsonl`
|
|
16
16
|
5. Relevant `.cowork-flow/spec/*/index.md`
|
|
17
17
|
6. Any exact files named by the task, plan, or user
|
|
18
|
+
7. If the task changes behavior, locate or create `tdd.jsonl` evidence before implementation.
|
|
18
19
|
|
|
19
20
|
Do not bulk-load unrelated tasks, archived sessions, or every spec file.
|
|
20
21
|
|
|
@@ -16,6 +16,7 @@ Use this after implementation and before `finish-work`.
|
|
|
16
16
|
5. Review test intent: reject shallow tests that do not fail for meaningful behavior breaks.
|
|
17
17
|
6. Run focused tests that would fail if the changed behavior broke.
|
|
18
18
|
7. Run broader validation when the change touches shared runtime, templates, packaging, or public workflow.
|
|
19
|
+
8. Report `test_intent_review` with the key tests that defend PRD acceptance behavior.
|
|
19
20
|
|
|
20
21
|
## Report
|
|
21
22
|
|
|
@@ -26,6 +26,7 @@ Always use the runtime controller:
|
|
|
26
26
|
.cowork-flow/run party-v2 post
|
|
27
27
|
.cowork-flow/run party-v2 respond
|
|
28
28
|
.cowork-flow/run party-v2 advance
|
|
29
|
+
.cowork-flow/run party-v2 record-action-result
|
|
29
30
|
.cowork-flow/run party-v2 finalize
|
|
30
31
|
```
|
|
31
32
|
|
|
@@ -38,6 +39,7 @@ Do not bypass a runtime rejection by manually accepting child output. Runtime va
|
|
|
38
39
|
- Historical board state is runtime-private and may be used only for audit or final reports.
|
|
39
40
|
- Use at least three child agents unless the effective runtime config explicitly allows a different value.
|
|
40
41
|
- The runtime emits host-neutral next actions. The active Host Adapter or moderator executes them for Codex, Claude Code, or OpenCode.
|
|
42
|
+
- Host action results must be recorded back through `record-action-result` so `agents.json`, audit logs, and action history can prove lifecycle state.
|
|
41
43
|
|
|
42
44
|
## Child Response Rules
|
|
43
45
|
|