@house365/comate 0.5.0 → 0.7.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.
- package/README.md +27 -9
- package/bin/cli.mjs +6 -0
- package/bin/doctor.mjs +86 -2
- package/bin/init-run.mjs +1 -1
- package/bin/init.mjs +2 -2
- package/bin/usage.mjs +252 -0
- package/docs/COMATE_MANUAL.md +710 -669
- package/package.json +3 -2
- package/skills/comate/SKILL.md +17 -20
- package/skills/comate/reference/decision-points.md +3 -3
- package/skills/comate/reference/prerequisites.md +1 -2
- package/skills/comate/scripts/comate-lib.sh +29 -12
- package/skills/comate/scripts/comate.sh +10 -10
- package/skills/comate/tests/comate.bats +31 -26
- package/skills/comate-build/SKILL.md +3 -3
- package/skills/comate-fix/SKILL.md +153 -0
- package/skills/{comate-intake → comate-gate}/SKILL.md +26 -6
- package/skills/{comate-intake → comate-gate}/scaffold/docs/README.md +2 -2
- package/skills/{comate-intake → comate-gate}/scaffold/docs/architecture/README.md +2 -2
- package/skills/{comate-intake → comate-gate}/scaffold/docs/knowledge-base/README.md +8 -8
- package/skills/comate-gate/scaffold/docs/knowledge-base/integrations/README.md +31 -0
- package/skills/{comate-intake → comate-gate}/scaffold/docs/knowledge-base/requirements/_templates/PRD.md +2 -2
- package/skills/comate-grill/SKILL.md +6 -6
- package/skills/comate-kb-integration/SKILL.md +128 -0
- package/skills/comate-kb-integration/scripts/fetch_rendered_doc.py +84 -0
- package/skills/comate-open/SKILL.md +5 -5
- package/skills/comate-hotfix/SKILL.md +0 -115
- package/skills/comate-tweak/SKILL.md +0 -109
- /package/skills/{comate-intake → comate-gate}/scaffold/docs/knowledge-base/integrations/_TEMPLATE/README.md +0 -0
- /package/skills/{comate-intake → comate-gate}/scaffold/docs/knowledge-base/integrations/_TEMPLATE/api-snapshot.md +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@house365/comate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "comate —— OpenSpec + Superpowers 规约驱动的 AI 开发编排器(Agent Skills)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,11 +41,12 @@
|
|
|
41
41
|
"node": ">=20"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
+
"ccusage": "^20.0.19",
|
|
44
45
|
"skills": "^1.5.21"
|
|
45
46
|
},
|
|
46
47
|
"scripts": {
|
|
47
48
|
"postinstall": "node bin/postinstall.mjs",
|
|
48
|
-
"test": "node bin/init.test.mjs && bash skills/comate/tests/run.sh",
|
|
49
|
+
"test": "node bin/init.test.mjs && node bin/usage.test.mjs && bash skills/comate/tests/run.sh",
|
|
49
50
|
"doctor": "cd skills && bash comate/scripts/comate.sh doctor",
|
|
50
51
|
"prepublish-check": "node scripts/prepublish-check.mjs",
|
|
51
52
|
"pack-check": "node scripts/pack-check.mjs",
|
package/skills/comate/SKILL.md
CHANGED
|
@@ -6,7 +6,7 @@ description: "comate —— OpenSpec + Superpowers 规格驱动开发编排器
|
|
|
6
6
|
# comate —— OpenSpec + Superpowers 规格驱动开发流
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
**核心原则:brainstorming 不可跳过。每个变更都必须经过深度设计(
|
|
9
|
+
**核心原则:brainstorming 不可跳过。每个变更都必须经过深度设计(fix 预设除外)。**
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -18,18 +18,17 @@ agent 做决策只需读本节,其余参见末尾「参考附录」。决策
|
|
|
18
18
|
|
|
19
19
|
**Step 0:活跃 change 发现 + 意图探测**
|
|
20
20
|
|
|
21
|
-
1. 先探测预设;命中
|
|
21
|
+
1. 先探测预设;命中 fix 条件则直接调用 `/comate-fix`,不进入普通 open 分支。
|
|
22
22
|
2. 无预设命中时,运行 `openspec list --json` 获取所有活跃 change。
|
|
23
23
|
|
|
24
24
|
**预设探测优先级最高**:
|
|
25
|
-
- 用户明确描述 bug
|
|
26
|
-
-
|
|
27
|
-
- **用户输入指向一份原始 PRD**(给了 PRD 路径/编号,或明确说「这是 PRD / 从这份需求文档开始」,典型路径 `docs/knowledge-base/**/PRD-*.md`)**且无对应活跃 change** → 直接调用 `/comate-intake`(阶段 0:先过门禁,再拆分建 change)。不要直接调 `/comate-open`——PRD 必须先过质量门禁。
|
|
25
|
+
- 用户明确描述 bug 修复或文案/配置/文档/prompt 小调整 + 满足 fix 条件 → 直接调用 `/comate-fix`
|
|
26
|
+
- **用户输入指向一份原始 PRD**(给了 PRD 路径/编号,或明确说「这是 PRD / 从这份需求文档开始」,典型路径 `docs/knowledge-base/**/PRD-*.md`)**且无对应活跃 change** → 直接调用 `/comate-gate`(阶段 0:先过门禁,再拆分建 change)。不要直接调 `/comate-open`——PRD 必须先过质量门禁。
|
|
28
27
|
- 无预设命中 → 按下表处理
|
|
29
28
|
|
|
30
29
|
| 活跃 change | 用户输入 | 行为 |
|
|
31
30
|
|-------------|----------|------|
|
|
32
|
-
| 无 | 指向原始 PRD | → 调用 `/comate-
|
|
31
|
+
| 无 | 指向原始 PRD | → 调用 `/comate-gate` |
|
|
33
32
|
| 无 | 非预设输入 | → 调用 `/comate-open` |
|
|
34
33
|
| 恰好 1 个 | `/comate <描述>` | → **询问**:继续该 change 还是新建 |
|
|
35
34
|
| 多个 | `/comate <描述>` | → **询问**:继续已有还是新建;继续则列出供选择 |
|
|
@@ -60,7 +59,7 @@ agent 做决策只需读本节,其余参见末尾「参考附录」。决策
|
|
|
60
59
|
2. `verify_result: pass` 且 `archived` 非 `true` → 调用 `/comate-archive`
|
|
61
60
|
3. `verify_result: fail` → 验证失败决策阻塞点(决策点 4)
|
|
62
61
|
4. `phase: verify` 或 tasks.md 全勾 → 调用 `/comate-verify`
|
|
63
|
-
5. `phase: build` 或有 Design Doc 但 plan/执行未完成 → 按 workflow 路由:`
|
|
62
|
+
5. `phase: build` 或有 Design Doc 但 plan/执行未完成 → 按 workflow 路由:`fix`→`/comate-fix`,`full`→`/comate-build`
|
|
64
63
|
6. `phase: design` 或有 change 但无 Design Doc → 调用 `/comate-design`
|
|
65
64
|
7. `phase: open` 或有活跃 change 但 `.comate.yaml` 缺失 → 调用 `/comate-open`
|
|
66
65
|
8. 无活跃 change → 调用 `/comate-open`
|
|
@@ -69,9 +68,7 @@ agent 做决策只需读本节,其余参见末尾「参考附录」。决策
|
|
|
69
68
|
|
|
70
69
|
### 预设升级判定
|
|
71
70
|
|
|
72
|
-
**
|
|
73
|
-
|
|
74
|
-
**tweak → full**(任一满足即升级):改动 ≥ 5 文件 / 跨模块协调 / 需新增 ≥ 5 测试用例 / 配置项增删(非值修改)。
|
|
71
|
+
**fix → full**:见 `/comate-fix` 的两种模式升级条件(bug 模式 3+ 文件 / 架构变更 / schema 变更 / 新 API / 跨模块;调整模式 5+ 文件 / 多模块协调 / 5+ 测试 / 配置项增删 / 新 capability / delta spec)。
|
|
75
72
|
|
|
76
73
|
### 错误处理速查
|
|
77
74
|
|
|
@@ -101,17 +98,17 @@ agent 做决策只需读本节,其余参见末尾「参考附录」。决策
|
|
|
101
98
|
|
|
102
99
|
| 命令 | 阶段 | Owner | 产物 |
|
|
103
100
|
|------|------|-------|------|
|
|
104
|
-
| `/comate-
|
|
101
|
+
| `/comate-gate` | 0. PRD 门禁与拆分 | Claude | `<PRD>.gate.yaml`, 评审报告, N 个 change |
|
|
105
102
|
| `/comate-open` | 1. 开题 | OpenSpec | proposal.md, design.md, tasks.md |
|
|
106
103
|
| `/comate-design` | 2. 深度设计 | Superpowers | Design Doc, delta spec |
|
|
107
104
|
| `/comate-build` | 3. 计划与构建 | Superpowers | 实施计划, 代码提交 |
|
|
108
105
|
| `/comate-verify` | 4. 验证收尾 | 双方 | 验证报告, 分支处理 |
|
|
109
106
|
| `/comate-archive` | 5. 归档 | OpenSpec | delta→main spec 同步, design doc 标注, 归档 |
|
|
110
|
-
| `/comate-
|
|
111
|
-
| `/comate-
|
|
107
|
+
| `/comate-fix` | 预设 | 双方 | 快速小改动(bug 修复 + 非 bug 调整,跳过 brainstorming) |
|
|
108
|
+
| `/comate-kb-integration` | 工具 | Claude | 第三方对接档案(从官方文档 URL 生成 integrations 目录档案) |
|
|
112
109
|
|
|
113
110
|
```
|
|
114
|
-
[原始 PRD] ──→ /comate-
|
|
111
|
+
[原始 PRD] ──→ /comate-gate ──┐ (门禁+拆分,扇出 N 个 change)
|
|
115
112
|
(Claude) │
|
|
116
113
|
/comate ▼
|
|
117
114
|
↓ 自动探测
|
|
@@ -119,7 +116,7 @@ agent 做决策只需读本节,其余参见末尾「参考附录」。决策
|
|
|
119
116
|
(OpenSpec) (Superpowers) (Superpowers) (双方) (OpenSpec)
|
|
120
117
|
```
|
|
121
118
|
|
|
122
|
-
需求来自对话时从 `/comate-open` 起步;来自原始 PRD 时先过 `/comate-
|
|
119
|
+
需求来自对话时从 `/comate-open` 起步;来自原始 PRD 时先过 `/comate-gate` 门禁再拆分。
|
|
123
120
|
|
|
124
121
|
---
|
|
125
122
|
|
|
@@ -142,7 +139,7 @@ fi
|
|
|
142
139
|
之后全程复用 `$COMATE`:
|
|
143
140
|
|
|
144
141
|
```bash
|
|
145
|
-
bash "$COMATE" state <name> init <full|
|
|
142
|
+
bash "$COMATE" state <name> init <full|fix>
|
|
146
143
|
bash "$COMATE" state <name> transition <event>
|
|
147
144
|
bash "$COMATE" state <name> check <phase> [--json]
|
|
148
145
|
bash "$COMATE" state <name> recover <phase>
|
|
@@ -167,10 +164,10 @@ bash "$COMATE" doctor
|
|
|
167
164
|
| 字段 | 含义 |
|
|
168
165
|
|------|------|
|
|
169
166
|
| `schema_version` | 状态文件格式版本(当前 1) |
|
|
170
|
-
| `workflow` | `full` / `
|
|
167
|
+
| `workflow` | `full` / `fix` |
|
|
171
168
|
| `phase` | `open` / `design` / `build` / `verify` / `archive` |
|
|
172
169
|
| `build_mode` | `subagent-driven-development` / `executing-plans` / `direct` |
|
|
173
|
-
| `tdd_mode` | `tdd` / `direct`(build→verify 前必须已选;
|
|
170
|
+
| `tdd_mode` | `tdd` / `direct`(build→verify 前必须已选;fix 默认 `direct`) |
|
|
174
171
|
| `isolation` | `branch` / `worktree`(build→verify 前必须已选) |
|
|
175
172
|
| `verify_mode` | `light` / `full`(由 scale 评估写入) |
|
|
176
173
|
| `verify_result` | `pending` / `pass` / `fail` |
|
|
@@ -187,7 +184,7 @@ bash "$COMATE" doctor
|
|
|
187
184
|
- `build → verify` 前 `isolation` 必须为 `branch` 或 `worktree`
|
|
188
185
|
- `build → verify` 前 `build_mode` 必须已选
|
|
189
186
|
- `build → verify` 前 `tdd_mode` 必须为 `tdd` 或 `direct`
|
|
190
|
-
- `build_mode: direct` 默认仅
|
|
187
|
+
- `build_mode: direct` 默认仅 fix;full 流程需 `direct_override: true`
|
|
191
188
|
- `verify → archive` 前 `verification_report` 指向真实文件、`branch_status: handled`、`impl_hash` 与当前 plan+tasks 一致
|
|
192
189
|
|
|
193
190
|
### 文件结构
|
|
@@ -212,7 +209,7 @@ docs/superpowers/ # Superpowers —— HOW
|
|
|
212
209
|
|
|
213
210
|
### 最佳实践
|
|
214
211
|
|
|
215
|
-
1. brainstorming 不可跳过(
|
|
212
|
+
1. brainstorming 不可跳过(fix 除外)
|
|
216
213
|
2. delta spec 是活文档,build 阶段随时改,归档时同步
|
|
217
214
|
3. 交接包由脚本生成(`handoff`),guard 校验 source/hash/mode
|
|
218
215
|
4. tasks.md 实时同步,每完成一个任务勾选并提交
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
暂停请用户选择:本地合并 / 推送建 PR / 保持分支 / 丢弃工作。仅在用户选择且对应操作完成后,才写 `branch_status: handled`。
|
|
56
56
|
引用:`comate-verify` Step 3。
|
|
57
57
|
|
|
58
|
-
6. **预设升级确认**(
|
|
59
|
-
|
|
60
|
-
引用:`comate-
|
|
58
|
+
6. **预设升级确认**(fix → full)
|
|
59
|
+
命中升级条件(见 `comate-fix` SKILL 的「升级条件」,bug 模式与调整模式各有阈值)时,暂停请用户确认升级为完整 `/comate`。不得直接进入 `/comate-design`,不得自动补 Design Doc。用户确认后先 `state set <name> workflow full` 再进入完整流程。
|
|
60
|
+
引用:`comate-fix`「升级条件」。
|
|
61
61
|
|
|
62
62
|
7. **构建期范围扩张**(build)
|
|
63
63
|
实施中发现需要重新设计或拆分新 change 时暂停。判定基准:以 tasks.md 初始任务总数为准,新增任务超过总数一半(50% 阈值)即视为超范围,请用户决定是否拆分。中等规模(接口变更、新增组件)确认后加载 `superpowers:brainstorming` 更新设计;大规模(全新 capability)确认后用 `/comate-open` 拆独立 change。
|
|
@@ -81,8 +81,7 @@ skills/
|
|
|
81
81
|
├── comate-build/SKILL.md # 阶段 3
|
|
82
82
|
├── comate-verify/SKILL.md # 阶段 4
|
|
83
83
|
├── comate-archive/SKILL.md # 阶段 5
|
|
84
|
-
├── comate-
|
|
85
|
-
└── comate-tweak/SKILL.md # 预设
|
|
84
|
+
├── comate-fix/SKILL.md # 预设(bug + 调整)
|
|
86
85
|
```
|
|
87
86
|
|
|
88
87
|
各 phase skill 通过 `*/comate/scripts/comate.sh` glob 定位脚本,共享 `comate/reference/*` 和 `comate/scripts/*`。若目标平台支持嵌套 skill 发现,也可改回 `comate/<phase>/SKILL.md` 子目录布局,纯命名调整,不影响脚本。
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Single source of truth for: YAML flat read/write, field-order template + enums,
|
|
5
5
|
# hashing, logging, exit-code contract. Other scripts `source` this file.
|
|
6
6
|
#
|
|
7
|
-
# - all YAML logic lives here
|
|
7
|
+
# - all YAML logic lives here
|
|
8
8
|
# - .comate.yaml is a declared flat `key: value` subset; validate_flat_yaml enforces it.
|
|
9
9
|
# - yaml_set does full-rewrite + atomic mv + write-back verification.
|
|
10
10
|
# - stable exit codes — 0 OK | 1 BLOCK | 2 USAGE | 3 ENV | 4 CORRUPT.
|
|
@@ -81,7 +81,7 @@ readonly COMATE_SCHEMA_VERSION=1
|
|
|
81
81
|
# --- Enum table: key -> space-separated legal values ---
|
|
82
82
|
declare -A ENUMS=(
|
|
83
83
|
[schema_version]="1"
|
|
84
|
-
[workflow]="full
|
|
84
|
+
[workflow]="full fix"
|
|
85
85
|
[phase]="open design build verify archive"
|
|
86
86
|
[build_mode]="subagent-driven-development executing-plans direct"
|
|
87
87
|
[tdd_mode]="tdd direct"
|
|
@@ -460,23 +460,40 @@ declare -A GATE_ENUMS=(
|
|
|
460
460
|
[gate_status]="reviewing blocked passed passed-with-tbd stale"
|
|
461
461
|
)
|
|
462
462
|
|
|
463
|
+
# gate_stem_for <prd> — derive the short stem used to name a PRD's gate.yaml
|
|
464
|
+
# and review report. A conforming PRD file is `PRD-<NNN>-<title>.md`, whose
|
|
465
|
+
# gate/report drop the title and key off `PRD-<NNN>` (so one dir with
|
|
466
|
+
# PRD-001/PRD-002 gets PRD-001.gate.yaml / PRD-002.gate.yaml). Non-conforming
|
|
467
|
+
# names (no PRD-NNN prefix) fall back to the full basename so callers still get
|
|
468
|
+
# a stable, collision-free stem instead of an error.
|
|
469
|
+
gate_stem_for() {
|
|
470
|
+
local base
|
|
471
|
+
base=$(basename "$1")
|
|
472
|
+
base="${base%.markdown}"
|
|
473
|
+
base="${base%.md}"
|
|
474
|
+
if [[ "$base" =~ ^([Pp][Rr][Dd]-[0-9]+) ]]; then
|
|
475
|
+
echo "${BASH_REMATCH[1]}"
|
|
476
|
+
else
|
|
477
|
+
echo "$base"
|
|
478
|
+
fi
|
|
479
|
+
}
|
|
480
|
+
|
|
463
481
|
# gate_path_for <prd> — echo the gate.yaml path adjacent to the PRD.
|
|
464
|
-
#
|
|
482
|
+
# Named `<stem>.gate.yaml` where stem is PRD-<NNN> (see gate_stem_for).
|
|
465
483
|
gate_path_for() {
|
|
466
|
-
local prd="$1"
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
echo "${
|
|
484
|
+
local prd="$1" dir stem
|
|
485
|
+
dir=$(dirname "$prd")
|
|
486
|
+
stem=$(gate_stem_for "$prd")
|
|
487
|
+
echo "${dir}/${stem}.gate.yaml"
|
|
470
488
|
}
|
|
471
489
|
|
|
472
490
|
# gate_report_for <prd> — echo the review report path (PRD same dir).
|
|
491
|
+
# Named `<stem>-REVIEW.md` where stem is PRD-<NNN> (see gate_stem_for).
|
|
473
492
|
gate_report_for() {
|
|
474
|
-
local prd="$1" dir
|
|
493
|
+
local prd="$1" dir stem
|
|
475
494
|
dir=$(dirname "$prd")
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
base="${base%.md}"
|
|
479
|
-
echo "${dir}/PRD-REVIEW-${base}.md"
|
|
495
|
+
stem=$(gate_stem_for "$prd")
|
|
496
|
+
echo "${dir}/${stem}-REVIEW.md"
|
|
480
497
|
}
|
|
481
498
|
|
|
482
499
|
# gate_yaml_set <file> <key> <value> — gate-file analogue of yaml_set: validate
|
|
@@ -57,7 +57,7 @@ usage_top() {
|
|
|
57
57
|
cat >&2 <<'EOF'
|
|
58
58
|
Usage: comate.sh <command> ...
|
|
59
59
|
|
|
60
|
-
state <name> init <workflow> full |
|
|
60
|
+
state <name> init <workflow> full | fix
|
|
61
61
|
state <name> get <field>
|
|
62
62
|
state <name> set <field> <value>
|
|
63
63
|
state <name> transition <event> open-complete|design-complete|build-complete|verify-pass|verify-fail|archived
|
|
@@ -102,7 +102,7 @@ state_init() {
|
|
|
102
102
|
local name="$1" workflow="${2:-}"
|
|
103
103
|
validate_change_name "$name"
|
|
104
104
|
validate_enum workflow "$workflow"
|
|
105
|
-
[ -n "$workflow" ] || die "$COMATE_USAGE" "Usage: comate.sh state <name> init <full|
|
|
105
|
+
[ -n "$workflow" ] || die "$COMATE_USAGE" "Usage: comate.sh state <name> init <full|fix>"
|
|
106
106
|
|
|
107
107
|
local dir yaml
|
|
108
108
|
dir=$(comate_change_dir "$name")
|
|
@@ -128,7 +128,7 @@ state_init() {
|
|
|
128
128
|
# Workflow defaults: full leaves decisions null; presets prefill.
|
|
129
129
|
local build_mode="null" tdd_mode="null" isolation="null" verify_mode="null"
|
|
130
130
|
case "$workflow" in
|
|
131
|
-
|
|
131
|
+
fix)
|
|
132
132
|
build_mode="direct"; tdd_mode="direct"; isolation="branch"; verify_mode="light" ;;
|
|
133
133
|
esac
|
|
134
134
|
|
|
@@ -212,8 +212,8 @@ _require_build_decisions() {
|
|
|
212
212
|
subagent-driven-development|executing-plans|direct) ;;
|
|
213
213
|
*) die "$COMATE_BLOCK" "ERROR: build_mode must be selected, got '${build_mode:-null}'" ;;
|
|
214
214
|
esac
|
|
215
|
-
if [ "$build_mode" = "direct" ] && [ "$workflow" != "
|
|
216
|
-
die "$COMATE_BLOCK" "ERROR: build_mode=direct is only allowed for
|
|
215
|
+
if [ "$build_mode" = "direct" ] && [ "$workflow" != "fix" ] && [ "$direct_override" != "true" ]; then
|
|
216
|
+
die "$COMATE_BLOCK" "ERROR: build_mode=direct is only allowed for fix unless direct_override=true"
|
|
217
217
|
fi
|
|
218
218
|
case "$tdd_mode" in
|
|
219
219
|
tdd|direct) ;;
|
|
@@ -561,7 +561,7 @@ state_recover() {
|
|
|
561
561
|
_field_status "isolation" "$isolation"
|
|
562
562
|
_field_status "build_mode" "$build_mode"
|
|
563
563
|
_field_status "tdd_mode" "$tdd_mode"
|
|
564
|
-
if [ "$build_mode" = "direct" ] && [ "$workflow" != "
|
|
564
|
+
if [ "$build_mode" = "direct" ] && [ "$workflow" != "fix" ]; then
|
|
565
565
|
_field_status "direct_override" "$direct_override"
|
|
566
566
|
fi
|
|
567
567
|
echo ""
|
|
@@ -790,9 +790,9 @@ _g_build_mode_allowed() {
|
|
|
790
790
|
build_mode=$(yaml_get "$G_YAML" build_mode)
|
|
791
791
|
direct_override=$(yaml_get "$G_YAML" direct_override)
|
|
792
792
|
[ "$build_mode" != "direct" ] && return 0
|
|
793
|
-
case "$workflow" in
|
|
793
|
+
case "$workflow" in fix) return 0 ;; esac
|
|
794
794
|
[ "$direct_override" = "true" ] && return 0
|
|
795
|
-
echo "build_mode=direct only allowed for
|
|
795
|
+
echo "build_mode=direct only allowed for fix unless direct_override=true"
|
|
796
796
|
return 1
|
|
797
797
|
}
|
|
798
798
|
_g_tdd_mode_selected() {
|
|
@@ -1508,7 +1508,7 @@ gate_check() {
|
|
|
1508
1508
|
local prd; prd=$(require_prd "$1")
|
|
1509
1509
|
local gate; gate=$(gate_path_for "$prd")
|
|
1510
1510
|
if [ ! -f "$gate" ]; then
|
|
1511
|
-
die "$COMATE_BLOCK" "BLOCK: no gate for $prd — run /comate-
|
|
1511
|
+
die "$COMATE_BLOCK" "BLOCK: no gate for $prd — run /comate-gate to review the PRD before creating a change"
|
|
1512
1512
|
fi
|
|
1513
1513
|
local st; st=$(yaml_get "$gate" gate_status)
|
|
1514
1514
|
case "$st" in
|
|
@@ -1516,7 +1516,7 @@ gate_check() {
|
|
|
1516
1516
|
*) die "$COMATE_BLOCK" "BLOCK: gate_status='$st' (not passed) — a change cannot be spawned until the PRD gate passes" ;;
|
|
1517
1517
|
esac
|
|
1518
1518
|
if _gate_is_stale "$gate" "$prd"; then
|
|
1519
|
-
die "$COMATE_BLOCK" "BLOCK: PRD changed since it passed the gate (hash mismatch) — re-run /comate-
|
|
1519
|
+
die "$COMATE_BLOCK" "BLOCK: PRD changed since it passed the gate (hash mismatch) — re-run /comate-gate to re-gate before spawning a change"
|
|
1520
1520
|
fi
|
|
1521
1521
|
log_pass "[GATE] check PASS ($st) — $prd"
|
|
1522
1522
|
return "$COMATE_OK"
|
|
@@ -50,21 +50,14 @@ seed_open() {
|
|
|
50
50
|
[ "$(comate state demo get isolation)" = "null" ]
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
@test "init
|
|
54
|
-
comate state demo init
|
|
53
|
+
@test "init fix prefills preset defaults" {
|
|
54
|
+
comate state demo init fix
|
|
55
55
|
[ "$(comate state demo get build_mode)" = "direct" ]
|
|
56
56
|
[ "$(comate state demo get tdd_mode)" = "direct" ]
|
|
57
57
|
[ "$(comate state demo get isolation)" = "branch" ]
|
|
58
58
|
[ "$(comate state demo get verify_mode)" = "light" ]
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
@test "init tweak prefills tdd direct" {
|
|
62
|
-
comate state demo init tweak
|
|
63
|
-
[ "$(comate state demo get build_mode)" = "direct" ]
|
|
64
|
-
[ "$(comate state demo get tdd_mode)" = "direct" ]
|
|
65
|
-
[ "$(comate state demo get isolation)" = "branch" ]
|
|
66
|
-
}
|
|
67
|
-
|
|
68
61
|
@test "init records base_ref and base_branch" {
|
|
69
62
|
comate state demo init full
|
|
70
63
|
run comate state demo get base_ref
|
|
@@ -155,14 +148,14 @@ seed_open() {
|
|
|
155
148
|
[ "$(comate state demo get phase)" = "design" ]
|
|
156
149
|
}
|
|
157
150
|
|
|
158
|
-
@test "open-complete routes
|
|
159
|
-
comate state demo init
|
|
151
|
+
@test "open-complete routes fix to build" {
|
|
152
|
+
comate state demo init fix
|
|
160
153
|
comate state demo transition open-complete
|
|
161
154
|
[ "$(comate state demo get phase)" = "build" ]
|
|
162
155
|
}
|
|
163
156
|
|
|
164
157
|
@test "build-complete blocked without isolation" {
|
|
165
|
-
comate state demo init
|
|
158
|
+
comate state demo init fix
|
|
166
159
|
comate state demo transition open-complete
|
|
167
160
|
comate state demo set isolation null >/dev/null
|
|
168
161
|
run comate state demo transition build-complete
|
|
@@ -248,7 +241,7 @@ seed_open() {
|
|
|
248
241
|
# --- build->verify drift ---
|
|
249
242
|
|
|
250
243
|
@test "verify guard blocks when tasks change after build handoff" {
|
|
251
|
-
comate state demo init
|
|
244
|
+
comate state demo init fix
|
|
252
245
|
local d="openspec/changes/demo"
|
|
253
246
|
printf '# p\n' > "$d/proposal.md"; printf '# d\n' > "$d/design.md"; printf -- '- [x] t1\n' > "$d/tasks.md"
|
|
254
247
|
comate guard demo open --apply >/dev/null 2>&1
|
|
@@ -422,7 +415,7 @@ SH
|
|
|
422
415
|
}
|
|
423
416
|
|
|
424
417
|
@test "build guard blocks when tracked source drifts" {
|
|
425
|
-
comate state demo init
|
|
418
|
+
comate state demo init fix
|
|
426
419
|
local d="openspec/changes/demo"
|
|
427
420
|
printf '# p\n' > "$d/proposal.md"; printf '# d\n' > "$d/design.md"; printf -- '- [x] t1\n' > "$d/tasks.md"
|
|
428
421
|
mkdir -p docs/knowledge-base/cb
|
|
@@ -461,13 +454,25 @@ seed_prd() {
|
|
|
461
454
|
local prd; prd=$(seed_prd)
|
|
462
455
|
run comate gate "$prd" review
|
|
463
456
|
[ "$status" -eq 0 ]
|
|
464
|
-
[ -f "docs/knowledge-base/requirements/test/PRD-001
|
|
457
|
+
[ -f "docs/knowledge-base/requirements/test/PRD-001.gate.yaml" ]
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
@test "gate names key off PRD-NNN stem, dropping title" {
|
|
461
|
+
local prd; prd=$(seed_prd)
|
|
462
|
+
run comate gate "$prd" review
|
|
463
|
+
[ "$status" -eq 0 ]
|
|
464
|
+
# gate.yaml and review report drop the -demo title, key off PRD-001
|
|
465
|
+
[ -f "docs/knowledge-base/requirements/test/PRD-001.gate.yaml" ]
|
|
466
|
+
[ ! -f "docs/knowledge-base/requirements/test/PRD-001-demo.gate.yaml" ]
|
|
467
|
+
[[ "$output" == *"PRD-001-REVIEW.md"* ]]
|
|
468
|
+
grep -q "review_report: docs/knowledge-base/requirements/test/PRD-001-REVIEW.md" \
|
|
469
|
+
"docs/knowledge-base/requirements/test/PRD-001.gate.yaml"
|
|
465
470
|
}
|
|
466
471
|
|
|
467
472
|
@test "gate review writes reviewing status and pins prd_hash" {
|
|
468
473
|
local prd; prd=$(seed_prd)
|
|
469
474
|
comate gate "$prd" review >/dev/null
|
|
470
|
-
local gate="docs/knowledge-base/requirements/test/PRD-001
|
|
475
|
+
local gate="docs/knowledge-base/requirements/test/PRD-001.gate.yaml"
|
|
471
476
|
run comate gate "$prd" status
|
|
472
477
|
[ "$status" -eq 0 ]
|
|
473
478
|
[[ "$output" == *"reviewing"* ]]
|
|
@@ -509,7 +514,7 @@ seed_prd() {
|
|
|
509
514
|
comate gate "$prd" set score 90 >/dev/null
|
|
510
515
|
comate gate "$prd" set blocking_open 0 >/dev/null
|
|
511
516
|
printf '# 评审报告\n' > \
|
|
512
|
-
"docs/knowledge-base/requirements/test/PRD-
|
|
517
|
+
"docs/knowledge-base/requirements/test/PRD-001-REVIEW.md"
|
|
513
518
|
run comate gate "$prd" pass
|
|
514
519
|
[ "$status" -eq 0 ]
|
|
515
520
|
run comate gate "$prd" check
|
|
@@ -522,7 +527,7 @@ seed_prd() {
|
|
|
522
527
|
comate gate "$prd" set score 65 >/dev/null
|
|
523
528
|
comate gate "$prd" set blocking_open 0 >/dev/null
|
|
524
529
|
printf '# 评审报告\n' > \
|
|
525
|
-
"docs/knowledge-base/requirements/test/PRD-
|
|
530
|
+
"docs/knowledge-base/requirements/test/PRD-001-REVIEW.md"
|
|
526
531
|
run comate gate "$prd" pass --tbd
|
|
527
532
|
[ "$status" -eq 0 ]
|
|
528
533
|
run comate gate "$prd" status
|
|
@@ -535,7 +540,7 @@ seed_prd() {
|
|
|
535
540
|
comate gate "$prd" set score 90 >/dev/null
|
|
536
541
|
comate gate "$prd" set blocking_open 0 >/dev/null
|
|
537
542
|
printf '# 评审报告\n' > \
|
|
538
|
-
"docs/knowledge-base/requirements/test/PRD-
|
|
543
|
+
"docs/knowledge-base/requirements/test/PRD-001-REVIEW.md"
|
|
539
544
|
comate gate "$prd" pass >/dev/null
|
|
540
545
|
# mutate PRD after passing
|
|
541
546
|
printf '\n额外内容\n' >> "$prd"
|
|
@@ -550,14 +555,14 @@ seed_prd() {
|
|
|
550
555
|
comate gate "$prd" set score 90 >/dev/null
|
|
551
556
|
comate gate "$prd" set blocking_open 0 >/dev/null
|
|
552
557
|
printf '# 评审报告\n' > \
|
|
553
|
-
"docs/knowledge-base/requirements/test/PRD-
|
|
558
|
+
"docs/knowledge-base/requirements/test/PRD-001-REVIEW.md"
|
|
554
559
|
comate gate "$prd" pass >/dev/null
|
|
555
560
|
printf '\n改动\n' >> "$prd"
|
|
556
561
|
run comate gate "$prd" status
|
|
557
562
|
[ "$status" -eq 0 ]
|
|
558
563
|
[[ "$output" == *"stale"* ]]
|
|
559
564
|
# gate.yaml should still say passed (status is computed, not written by status cmd)
|
|
560
|
-
local gate="docs/knowledge-base/requirements/test/PRD-001
|
|
565
|
+
local gate="docs/knowledge-base/requirements/test/PRD-001.gate.yaml"
|
|
561
566
|
local stored; stored=$(grep '^gate_status:' "$gate" | awk '{print $2}')
|
|
562
567
|
[ "$stored" = "passed" ]
|
|
563
568
|
}
|
|
@@ -568,11 +573,11 @@ seed_prd() {
|
|
|
568
573
|
comate gate "$prd" set score 90 >/dev/null
|
|
569
574
|
comate gate "$prd" set blocking_open 0 >/dev/null
|
|
570
575
|
printf '# 报告\n' > \
|
|
571
|
-
"docs/knowledge-base/requirements/test/PRD-
|
|
576
|
+
"docs/knowledge-base/requirements/test/PRD-001-REVIEW.md"
|
|
572
577
|
comate gate "$prd" pass >/dev/null
|
|
573
578
|
run comate gate "$prd" spawned login-flow
|
|
574
579
|
[ "$status" -eq 0 ]
|
|
575
|
-
local gate="docs/knowledge-base/requirements/test/PRD-001
|
|
580
|
+
local gate="docs/knowledge-base/requirements/test/PRD-001.gate.yaml"
|
|
576
581
|
local sc; sc=$(grep '^spawned_changes:' "$gate" | sed 's/spawned_changes: //')
|
|
577
582
|
[[ "$sc" == *"login-flow"* ]]
|
|
578
583
|
}
|
|
@@ -583,11 +588,11 @@ seed_prd() {
|
|
|
583
588
|
comate gate "$prd" set score 90 >/dev/null
|
|
584
589
|
comate gate "$prd" set blocking_open 0 >/dev/null
|
|
585
590
|
printf '# 报告\n' > \
|
|
586
|
-
"docs/knowledge-base/requirements/test/PRD-
|
|
591
|
+
"docs/knowledge-base/requirements/test/PRD-001-REVIEW.md"
|
|
587
592
|
comate gate "$prd" pass >/dev/null
|
|
588
593
|
comate gate "$prd" spawned login-flow >/dev/null
|
|
589
594
|
comate gate "$prd" spawned logout-flow >/dev/null
|
|
590
|
-
local gate="docs/knowledge-base/requirements/test/PRD-001
|
|
595
|
+
local gate="docs/knowledge-base/requirements/test/PRD-001.gate.yaml"
|
|
591
596
|
local sc; sc=$(grep '^spawned_changes:' "$gate" | sed 's/spawned_changes: //')
|
|
592
597
|
[[ "$sc" == *"login-flow"* ]]
|
|
593
598
|
[[ "$sc" == *"logout-flow"* ]]
|
|
@@ -612,7 +617,7 @@ seed_prd() {
|
|
|
612
617
|
comate gate "$prd" set score 90 >/dev/null
|
|
613
618
|
comate gate "$prd" set blocking_open 0 >/dev/null
|
|
614
619
|
printf '# 报告\n' > \
|
|
615
|
-
"docs/knowledge-base/requirements/test/PRD-
|
|
620
|
+
"docs/knowledge-base/requirements/test/PRD-001-REVIEW.md"
|
|
616
621
|
comate gate "$prd" pass >/dev/null
|
|
617
622
|
printf '\n改动\n' >> "$prd"
|
|
618
623
|
# re-run review after PRD change — should reset to reviewing
|
|
@@ -82,7 +82,7 @@ bash "$COMATE" state <name> set plan docs/superpowers/plans/YYYY-MM-DD-feature.m
|
|
|
82
82
|
对仍有多个有效选项的维度,**一次 AskUserQuestion 问清全部**,选 `branch` 时**分支名也在同一次确认**,不得先问是否继续再二次追问配置或命名。已在 3b 自动写入的维度不再列入问题。每个选项附推荐理由(推荐只说明倾向,不代替用户拍板):
|
|
83
83
|
|
|
84
84
|
- **工作区隔离**:`branch` 新建分支(简单快速,≤3 文件推荐)/ `worktree` 独立工作区(需并行或当前分支有未提交工作时推荐)。
|
|
85
|
-
- **执行方式**:`subagent-driven-development`(任务 ≥3、独立、需双阶段审查)/ `executing-plans`(任务 ≤2 且无跨模块依赖,或来自
|
|
85
|
+
- **执行方式**:`subagent-driven-development`(任务 ≥3、独立、需双阶段审查)/ `executing-plans`(任务 ≤2 且无跨模块依赖,或来自 fix 预设)。
|
|
86
86
|
- **TDD 模式**:`tdd`(涉及业务逻辑/新功能/API,推荐)/ `direct`(无需测试覆盖或用户明确跳过)。
|
|
87
87
|
|
|
88
88
|
用户选择后(连同 3b 已自动应用的维度)写入:
|
|
@@ -95,7 +95,7 @@ bash "$COMATE" state <name> set tdd_mode <tdd|direct>
|
|
|
95
95
|
|
|
96
96
|
`isolation` 是脚本级硬约束,保持 `null` 时 `build → verify` 的 guard 和 `state transition build-complete` 都会失败。
|
|
97
97
|
|
|
98
|
-
`build_mode: direct` 默认仅
|
|
98
|
+
`build_mode: direct` 默认仅 fix 预设使用。full 流程只有用户明确要求跳过计划执行技能、且已记录显式 override 时才允许:
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
101
|
bash "$COMATE" state <name> set direct_override true
|
|
@@ -109,7 +109,7 @@ bash "$COMATE" state <name> set build_mode direct
|
|
|
109
109
|
| 选项 | 含义 | 适用场景 |
|
|
110
110
|
|------|------|---------|
|
|
111
111
|
| `tdd` | 每个任务先写失败测试再实现 | 推荐。涉及业务逻辑、新功能、API 的改动 |
|
|
112
|
-
| `direct` | 直接实现,不强制 TDD 流程 | 不需要测试覆盖的改动,或用户选择跳过测试直接写代码。
|
|
112
|
+
| `direct` | 直接实现,不强制 TDD 流程 | 不需要测试覆盖的改动,或用户选择跳过测试直接写代码。fix 预设默认 `direct` |
|
|
113
113
|
|
|
114
114
|
`tdd_mode` 是脚本级硬约束,full 流程在离开 build 阶段前必须选择 `tdd` 或 `direct`,否则 guard 和 `state transition build-complete` 都会失败。
|
|
115
115
|
|