@house365/comate 0.9.11 → 0.9.12
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/docs/COMATE_MANUAL.md +3 -3
- package/package.json +1 -1
- package/skills/comate/SKILL.md +2 -2
- package/skills/comate/scripts/comate.sh +11 -1
- package/skills/comate/tests/comate.bats +34 -14
- package/skills/comate-gate/SKILL.md +20 -31
- package/skills/comate-gate/scaffold/docs/knowledge-base/README.md +6 -7
- package/skills/comate-gate/scaffold/docs/knowledge-base/requirements/_templates/PRD.md +2 -2
package/docs/COMATE_MANUAL.md
CHANGED
|
@@ -137,14 +137,14 @@ docs/
|
|
|
137
137
|
├── architecture/README.md # 架构规范占位(契约事实源,需项目自建)
|
|
138
138
|
└── knowledge-base/
|
|
139
139
|
├── README.md # PRD → comate 流程说明 + 命名约定
|
|
140
|
-
├── requirements/_templates/PRD.md # PRD
|
|
140
|
+
├── requirements/_templates/PRD.md # PRD 模板
|
|
141
141
|
└── integrations/_TEMPLATE/ # 第三方对接档案模板(README + api-snapshot)
|
|
142
142
|
```
|
|
143
143
|
|
|
144
144
|
- 路径与 `comate-lib.sh` 硬编码的 `comate_kb_root=docs/knowledge-base` 对齐,PRD 放 `requirements/<YYYYMMDD-功能名>/` 下。
|
|
145
145
|
- **幂等且不覆盖**:逐文件跳过已存在的,重跑 `comate init` 不动你已改过的 docs。
|
|
146
146
|
- `architecture/` 只给占位 README(架构内容项目专属),是 PRD 门禁「契约对齐」的事实源,需按项目实际补齐。
|
|
147
|
-
-
|
|
147
|
+
- PRD 是需求入口,具体实现约束由 change 的 proposal/design/tasks 承接。
|
|
148
148
|
|
|
149
149
|
### 2.6 comate 本身的技能布局
|
|
150
150
|
|
|
@@ -235,7 +235,7 @@ comate usage --json -s 2026-08-01 # 其余参数原样透传给 ccusage
|
|
|
235
235
|
1. `archived: true` 或变更已在归档中 -> 流程完成
|
|
236
236
|
2. `verify_result: pass` 且 `archived` 不为 `true` -> 调用 `/comate-archive`
|
|
237
237
|
3. `verify_result: fail` -> 验证失败决策阻塞点(决策点 4)
|
|
238
|
-
4. `phase: verify`
|
|
238
|
+
4. `phase: verify` -> 调用 `/comate-verify`。`tasks.md` 全部勾选不能单独触发 verify;从 verify-fail 回到 build 后必须按 build 路由继续修复。
|
|
239
239
|
5. `phase: build` 或有设计文档但计划/执行不完整 -> 按工作流路由
|
|
240
240
|
6. `phase: design` 或有变更但无设计文档 -> 调用 `/comate-design`
|
|
241
241
|
7. `phase: open` 或有活动变更但 `.comate.yaml` 缺失 -> 调用 `/comate-open`
|
package/package.json
CHANGED
package/skills/comate/SKILL.md
CHANGED
|
@@ -185,8 +185,8 @@ agent 做决策只需读本节,其余参见末尾「参考附录」。决策
|
|
|
185
185
|
1. `archived: true` 或 change 已移入 archive → 流程完成
|
|
186
186
|
2. `verify_result: pass` 且 `archived` 非 `true` → 调用 `/comate-archive`
|
|
187
187
|
3. `verify_result: fail` → 验证失败决策阻塞点(决策点 4)
|
|
188
|
-
4. `phase: verify`
|
|
189
|
-
5. `phase: build` 或有 Design Doc 但 plan/执行未完成 → 按 workflow 路由:`fix`→`/comate-fix`,`full`→`/comate-build`
|
|
188
|
+
4. `phase: verify` → 调用 `/comate-verify`。`tasks.md` 全勾不能单独触发 verify;验证失败回退到 build 后,必须继续按 build 路由修复。
|
|
189
|
+
5. `phase: build` 或有 Design Doc 但 plan/执行未完成 → 按 workflow 路由:`fix`→`/comate-fix`,`full`→`/comate-build`
|
|
190
190
|
6. `phase: design` 或有 change 但无 Design Doc → 调用 `/comate-design`
|
|
191
191
|
7. `phase: open` 或有活跃 change 但 `.comate.yaml` 缺失 → 调用 `/comate-open`
|
|
192
192
|
8. 无活跃 change → 调用 `/comate-open`
|
|
@@ -1398,13 +1398,23 @@ dependency_archived() {
|
|
|
1398
1398
|
# gate — phase 0: PRD quality gate + split precondition
|
|
1399
1399
|
# =====================================================================
|
|
1400
1400
|
|
|
1401
|
-
# require_prd <prd> — ensure the PRD path is
|
|
1401
|
+
# require_prd <prd> — ensure the PRD path is real, non-empty, and conventionally named.
|
|
1402
|
+
validate_prd_filename() {
|
|
1403
|
+
local prd="$1" base
|
|
1404
|
+
base=$(basename "$prd")
|
|
1405
|
+
case "$base" in
|
|
1406
|
+
PRD-[0-9][0-9][0-9]-?*.md) return 0 ;;
|
|
1407
|
+
*) die "$COMATE_USAGE" "ERROR: PRD filename must match PRD-NNN-title.md: $base" ;;
|
|
1408
|
+
esac
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1402
1411
|
require_prd() {
|
|
1403
1412
|
local prd="$1"
|
|
1404
1413
|
[ -n "$prd" ] || die "$COMATE_USAGE" "ERROR: PRD path required"
|
|
1405
1414
|
case "$prd" in *..*) die "$COMATE_USAGE" "ERROR: PRD path cannot contain '..': $prd" ;; esac
|
|
1406
1415
|
[ -f "$prd" ] || die "$COMATE_CORRUPT" "ERROR: PRD not found: $prd"
|
|
1407
1416
|
file_nonempty "$prd" || die "$COMATE_CORRUPT" "ERROR: PRD is empty: $prd"
|
|
1417
|
+
validate_prd_filename "$prd"
|
|
1408
1418
|
echo "$prd"
|
|
1409
1419
|
}
|
|
1410
1420
|
|
|
@@ -237,6 +237,18 @@ seed_open() {
|
|
|
237
237
|
[ "$(comate state demo get verification_report)" = "null" ]
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
@test "verify-fail keeps build authoritative when tasks remain checked" {
|
|
241
|
+
comate state demo init full
|
|
242
|
+
printf '%s\n' '# Tasks' '- [x] already implemented' > openspec/changes/demo/tasks.md
|
|
243
|
+
comate state demo set phase verify >/dev/null
|
|
244
|
+
comate state demo set verify_result fail >/dev/null
|
|
245
|
+
comate state demo transition verify-fail
|
|
246
|
+
[ "$(comate state demo get phase)" = "build" ]
|
|
247
|
+
[ "$(comate state demo get verify_result)" = "pending" ]
|
|
248
|
+
# The router must use the persisted phase; task completion is not a phase.
|
|
249
|
+
[ "$(comate state demo get phase)" != "verify" ]
|
|
250
|
+
}
|
|
251
|
+
|
|
240
252
|
@test "recover reports phase-local progress" {
|
|
241
253
|
comate state demo init full
|
|
242
254
|
comate state demo set phase_step open.review-awaiting >/dev/null
|
|
@@ -346,8 +358,8 @@ SH
|
|
|
346
358
|
local d="openspec/changes/demo"
|
|
347
359
|
printf '# p\n' > "$d/proposal.md"; printf '# d\n' > "$d/design.md"; printf -- '- [x] t1\n' > "$d/tasks.md"
|
|
348
360
|
mkdir -p docs/knowledge-base/cb bin
|
|
349
|
-
printf '#
|
|
350
|
-
comate sources demo track docs/knowledge-base/cb/
|
|
361
|
+
printf '# source\n' > docs/knowledge-base/cb/source.md
|
|
362
|
+
comate sources demo track docs/knowledge-base/cb/source.md >/dev/null 2>&1
|
|
351
363
|
cat > bin/openspec <<'SH'
|
|
352
364
|
#!/bin/bash
|
|
353
365
|
set -e
|
|
@@ -427,13 +439,13 @@ SH
|
|
|
427
439
|
@test "sources track records kb file and flips source_kind to file" {
|
|
428
440
|
comate state demo init full
|
|
429
441
|
mkdir -p docs/knowledge-base/cb
|
|
430
|
-
printf '#
|
|
431
|
-
run comate sources demo track docs/knowledge-base/cb/
|
|
442
|
+
printf '# source\n' > docs/knowledge-base/cb/source.md
|
|
443
|
+
run comate sources demo track docs/knowledge-base/cb/source.md --note "main entry"
|
|
432
444
|
[ "$status" -eq 0 ]
|
|
433
445
|
[ "$(comate state demo get source_kind)" = "file" ]
|
|
434
446
|
[ "$(comate state demo get source_manifest)" = "openspec/changes/demo/.comate/sources.manifest" ]
|
|
435
447
|
run comate sources demo list
|
|
436
|
-
[[ "$output" == *"path:docs/knowledge-base/cb/
|
|
448
|
+
[[ "$output" == *"path:docs/knowledge-base/cb/source.md"* ]]
|
|
437
449
|
[[ "$output" == *"note:main entry"* ]]
|
|
438
450
|
}
|
|
439
451
|
|
|
@@ -448,9 +460,9 @@ SH
|
|
|
448
460
|
@test "sources check detects drift after file edited" {
|
|
449
461
|
comate state demo init full
|
|
450
462
|
mkdir -p docs/knowledge-base/cb
|
|
451
|
-
printf '#
|
|
452
|
-
comate sources demo track docs/knowledge-base/cb/
|
|
453
|
-
printf 'edited\n' >> docs/knowledge-base/cb/
|
|
463
|
+
printf '# source\n' > docs/knowledge-base/cb/source.md
|
|
464
|
+
comate sources demo track docs/knowledge-base/cb/source.md >/dev/null 2>&1
|
|
465
|
+
printf 'edited\n' >> docs/knowledge-base/cb/source.md
|
|
454
466
|
run comate sources demo check
|
|
455
467
|
[ "$status" -eq 1 ]
|
|
456
468
|
[[ "$output" == *"drifted"* ]]
|
|
@@ -459,9 +471,9 @@ SH
|
|
|
459
471
|
@test "sources find reverse-looks-up a tracked file" {
|
|
460
472
|
comate state demo init full
|
|
461
473
|
mkdir -p docs/knowledge-base/cb
|
|
462
|
-
printf '#
|
|
463
|
-
comate sources demo track docs/knowledge-base/cb/
|
|
464
|
-
run comate sources find docs/knowledge-base/cb/
|
|
474
|
+
printf '# source\n' > docs/knowledge-base/cb/source.md
|
|
475
|
+
comate sources demo track docs/knowledge-base/cb/source.md >/dev/null 2>&1
|
|
476
|
+
run comate sources find docs/knowledge-base/cb/source.md
|
|
465
477
|
[ "$status" -eq 0 ]
|
|
466
478
|
[[ "$output" == *"demo"* ]]
|
|
467
479
|
}
|
|
@@ -471,11 +483,11 @@ SH
|
|
|
471
483
|
local d="openspec/changes/demo"
|
|
472
484
|
printf '# p\n' > "$d/proposal.md"; printf '# d\n' > "$d/design.md"; printf -- '- [x] t1\n' > "$d/tasks.md"
|
|
473
485
|
mkdir -p docs/knowledge-base/cb
|
|
474
|
-
printf '#
|
|
475
|
-
comate sources demo track docs/knowledge-base/cb/
|
|
486
|
+
printf '# source\n' > docs/knowledge-base/cb/source.md
|
|
487
|
+
comate sources demo track docs/knowledge-base/cb/source.md >/dev/null 2>&1
|
|
476
488
|
comate guard demo open --apply >/dev/null 2>&1
|
|
477
489
|
comate handoff demo build --write >/dev/null 2>&1
|
|
478
|
-
printf 'edited\n' >> docs/knowledge-base/cb/
|
|
490
|
+
printf 'edited\n' >> docs/knowledge-base/cb/source.md
|
|
479
491
|
run comate guard demo build --json
|
|
480
492
|
[ "$status" -eq 1 ]
|
|
481
493
|
[[ "$output" == *'"block":true'* ]]
|
|
@@ -521,6 +533,14 @@ seed_prd() {
|
|
|
521
533
|
[ -f "docs/knowledge-base/requirements/test/PRD-001.gate.yaml" ]
|
|
522
534
|
}
|
|
523
535
|
|
|
536
|
+
@test "gate rejects PRD filenames outside the naming convention" {
|
|
537
|
+
mkdir -p docs/knowledge-base/requirements/test
|
|
538
|
+
printf '# PRD\n' > docs/knowledge-base/requirements/test/PRD-1.md
|
|
539
|
+
run comate gate docs/knowledge-base/requirements/test/PRD-1.md review
|
|
540
|
+
[ "$status" -eq 2 ]
|
|
541
|
+
[[ "$output" == *"PRD-NNN-title.md"* ]]
|
|
542
|
+
}
|
|
543
|
+
|
|
524
544
|
@test "gate names key off PRD-NNN stem, dropping title" {
|
|
525
545
|
local prd; prd=$(seed_prd)
|
|
526
546
|
run comate gate "$prd" review
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: comate-gate
|
|
3
|
-
description: "comate 阶段 0:PRD 门禁与拆分。用 /comate-gate 调用。对原始 PRD 做质量审阅+评分+阻断闸门,通过后按依赖/独立性判定拆成 1 或 N 个 change,逐个交给 comate-open。门禁状态钉在 PRD 同级
|
|
3
|
+
description: "comate 阶段 0:PRD 门禁与拆分。用 /comate-gate 调用。对原始 PRD 做质量审阅+评分+阻断闸门,通过后按依赖/独立性判定拆成 1 或 N 个 change,逐个交给 comate-open。门禁状态钉在 PRD 同级 gate 文件,门禁未通过禁止建 change。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# comate 阶段 0:PRD 门禁与拆分(Gate)
|
|
@@ -11,13 +11,11 @@ description: "comate 阶段 0:PRD 门禁与拆分。用 /comate-gate 调用。
|
|
|
11
11
|
1. **门禁**:审阅 PRD 质量、百分制评分、建阻断台账。阻断问题未清零,**禁止建任何 change**。
|
|
12
12
|
2. **拆分**:按依赖/整体性/独立性/规模判定该 PRD 变成几个 change,粒度由用户拍板(AI 只给建议)。
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
---
|
|
14
|
+
---
|
|
17
15
|
|
|
18
16
|
## 核心铁律
|
|
19
17
|
|
|
20
|
-
- **门禁状态是可验证的文件真相源**:钉在 PRD
|
|
18
|
+
- **门禁状态是可验证的文件真相源**:钉在 PRD 同级的 gate 文件。评审报告是给人看的派生物,**不是**状态源。PRD 命名按本 skill 的前置规范执行,派生文件名由脚本确定性生成。
|
|
21
19
|
- **AskUserQuestion 是真阻塞点**:文字提示、推荐方案、默认值、历史偏好、用户未反对,都**不能**替代明确回答。
|
|
22
20
|
- **只审不改**:门禁只暴露 PRD 问题,不替 PRD 补内容、不替产品拍板。
|
|
23
21
|
- **门禁未通过禁止建 change**:`gate_status ∈ {passed, passed-with-tbd}` 且 PRD 哈希未漂移,才允许 comate-open 建 change(由 `gate check` 硬强制)。
|
|
@@ -55,34 +53,25 @@ bash "$COMATE" gate <prd> check # comate-open 建 change 前的
|
|
|
55
53
|
### 1. 定位 PRD
|
|
56
54
|
|
|
57
55
|
- 用户给了路径/编号 → 直接读该文件。
|
|
58
|
-
- 未给 → 用 Glob
|
|
56
|
+
- 未给 → 用 Glob 列出候选(默认搜索 `docs/knowledge-base/requirements/**/*.md`,若项目无此结构再探测 `docs/**/*.md`),按命中数分类(对齐 `comate/reference/decision-points.md` 首节三类框架):
|
|
59
57
|
- **恰好 1 个候选** → 无 ≥2 有效选项,属"自动处理":直接选中该 PRD 并**报告选了哪份**,不 AskUserQuestion。
|
|
60
58
|
- **多个候选** → 属"用户决策":用 **AskUserQuestion** 让用户选一个。
|
|
61
59
|
- **0 个候选** → 属"停止条件":报告在约定路径下未找到 PRD,请用户提供路径或确认 PRD 位置,不发明选项。
|
|
62
|
-
- 读取后重点提取:**功能清单**(各功能项 + 优先级 P0/P1/P2)、**范围(In/Out
|
|
63
|
-
- 若 PRD 明显未定稿(状态字段非「已定稿」等),用 **AskUserQuestion** 提示可能未冻结并暂停确认;确认前只审阅,不建 gate。
|
|
64
|
-
|
|
65
|
-
### 1.5
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
| 对象 | 规范 |
|
|
70
|
-
|
|
71
|
-
| 功能目录 | `<YYYYMMDD-功能名>/` |
|
|
72
|
-
| PRD 文件 | 目录内 `PRD-<三位序号>-<功能名>.md
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
1. 先 **Grep** 全仓搜旧文件名/旧路径的所有引用(正文、其它文档、`.comate.yaml` 的 `source_manifest`、gate.yaml 的 `prd_path`/`review_report`)。
|
|
78
|
-
2. 用 **AskUserQuestion** 给出「旧名 → 建议新名」让用户确认(改名影响引用,不自作主张;功能名/日期推断不出时一并问)。
|
|
79
|
-
3. 确认后 **`git mv`** 改名(目录、PRD 文件;已存在的旧 gate.yaml/报告一并 `git mv` 到新名),保留 git 历史,**不要** Write 新文件+删旧。
|
|
80
|
-
4. **Edit** 把第 1 步搜到的引用全部改成新名/新路径。
|
|
81
|
-
5. 再 **Grep** 一次旧名确认零残留。
|
|
82
|
-
|
|
83
|
-
已规范或用户确认改名后,才进第 2 步门禁——此时 `gate review` 生成的 gate.yaml/报告自然是新名。若 PRD 名已规范,本步无操作,直接进门禁。
|
|
84
|
-
|
|
85
|
-
### 2. 门禁:质量审阅 + 评分(不可跳过)
|
|
60
|
+
- 读取后重点提取:**功能清单**(各功能项 + 优先级 P0/P1/P2)、**范围(In/Out)**、**第三方依赖**、**验收标准**、文档状态。检查内容是否可审阅即可,不要求 Markdown 标题、表格或模板字段完全一致。
|
|
61
|
+
- 若 PRD 明显未定稿(状态字段非「已定稿」等),用 **AskUserQuestion** 提示可能未冻结并暂停确认;确认前只审阅,不建 gate。
|
|
62
|
+
|
|
63
|
+
### 1.5 命名规范化(必要前置检查)
|
|
64
|
+
|
|
65
|
+
PRD 的路径和文件名需要稳定、可追踪,以便 gate 状态和评审报告确定性派生。进入门禁前检查:
|
|
66
|
+
|
|
67
|
+
| 对象 | 规范 |
|
|
68
|
+
|------|------|
|
|
69
|
+
| 功能目录 | `<YYYYMMDD-功能名>/` |
|
|
70
|
+
| PRD 文件 | 目录内 `PRD-<三位序号>-<功能名>.md` |
|
|
71
|
+
|
|
72
|
+
发现不规范时,先列出旧名和建议新名,等待用户确认后再用 `git mv` 改名,并同步修正引用。命名规范是流程前置条件;PRD 的正文格式不要求完全套用模板,只需能被审阅并包含可判断的需求内容。
|
|
73
|
+
|
|
74
|
+
### 2. 门禁:质量审阅 + 评分(不可跳过)
|
|
86
75
|
|
|
87
76
|
先初始化 gate(钉当前 PRD 哈希、拿到报告路径):
|
|
88
77
|
|
|
@@ -111,7 +100,7 @@ bash "$COMATE" gate <prd> review
|
|
|
111
100
|
- **仓库事实**(已有架构约定、字段、接口、对接档案):先用 Read/Glob/rg 核实并引用来源,不丢给用户决定。
|
|
112
101
|
- **产品决策**(范围、优先级、用户可见行为、状态流转、权限、数据口径、失败处理、验收规则):必须用 **AskUserQuestion** 问用户,不得用推荐方案/历史偏好/「待确认」代替确认。
|
|
113
102
|
|
|
114
|
-
**写评审报告(必生成)** 到 `gate review` 回显的 `review_report`
|
|
103
|
+
**写评审报告(必生成)** 到 `gate review` 回显的 `review_report` 路径(与 PRD 同级,由脚本确定性命名)。内容含:评分 + 评级 + 一句话总评、问题台账表(`ID` / 维度 / 严重程度 / 原文依据 / 影响章节 / 是否阻断 / 建议 / 产品回填列)、逐条问题。若无问题,明确写「审阅通过,未发现阻断项」。
|
|
115
104
|
|
|
116
105
|
**阻断规则**:影响范围、用户行为、状态流转、数据契约、权限、异常处理或验收标准的问题标「阻断」。把当前未关闭的阻断问题数写入 gate:
|
|
117
106
|
|
|
@@ -26,14 +26,13 @@ comate 采用**简化需求流**:只保留 **PRD**(产品需求文档),通过 `/
|
|
|
26
26
|
|
|
27
27
|
PRD 门禁状态钉在同级 `PRD-<三位序号>.gate.yaml`(机器真相源,含 `gate_status` / `score` / `blocking_open` / `prd_hash` / `spawned_changes`)。评审报告为 `PRD-<三位序号>-REVIEW.md`(人类可读,含问题台账)。PRD 通过门禁后被改会因哈希漂移自动失效(`stale`),需重跑 gate。
|
|
28
28
|
|
|
29
|
-
扇出的 comate change 内部用 proposal / design / tasks 承接 PRD
|
|
29
|
+
扇出的 comate change 内部用 proposal / design / tasks 承接 PRD 的功能项内容,PRD 直接作为 change 的源文档被 `sources track` 钉住。
|
|
30
30
|
|
|
31
|
-
## 命名约定
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
- PRD
|
|
35
|
-
- gate
|
|
36
|
-
- 评审报告: 自动生成,`PRD-<三位序号>-REVIEW.md`,与 PRD 同级,如 `PRD-001-REVIEW.md`
|
|
31
|
+
## 命名约定
|
|
32
|
+
|
|
33
|
+
- 功能目录:`<YYYYMMDD-功能名>/`
|
|
34
|
+
- PRD:目录内 `PRD-<三位序号>-<功能名>.md`
|
|
35
|
+
- gate 和评审报告:由脚本根据 PRD 路径自动生成,不手工命名。
|
|
37
36
|
|
|
38
37
|
## 横向 (integrations/)
|
|
39
38
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# PRD-<序号>-<功能名>: <产品标题>
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
> PRD =
|
|
3
|
+
> 复制本文件到需求目录,按项目约定命名,删除本行与所有 `<...>` 占位说明。
|
|
4
|
+
> PRD = 产品需求文档,回答「做成什么样」。本 PRD 由 `/comate-gate` 直接读取:先过质量门禁(审阅、评分、阻断检查),通过后按依赖和独立性拆成 1 或 N 个 comate change。
|
|
5
5
|
|
|
6
6
|
| 字段 | 内容 |
|
|
7
7
|
|------|------|
|