ccg-workflow 3.0.1 → 3.0.3

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 CHANGED
@@ -12,8 +12,9 @@
12
12
  [![Tests](https://img.shields.io/badge/Tests-139%20passed-brightgreen.svg)]()
13
13
  [![Follow on X](https://img.shields.io/badge/X-@CCG__Workflow-black?logo=x&logoColor=white)](https://x.com/CCG_Workflow)
14
14
  ![star](https://atomgit.com/fengshao1227/ccg-workflow/star/badge.svg)
15
+ [![Docs](https://img.shields.io/badge/Docs-ccg.fengshao1227.com-blue?style=for-the-badge&logo=readthedocs&logoColor=white)](https://ccg.fengshao1227.com/)
15
16
 
16
- [简体中文](./README.zh-CN.md) | English
17
+ [简体中文](./README.zh-CN.md) | English | [**Documentation**](https://ccg.fengshao1227.com/)
17
18
 
18
19
  </div>
19
20
 
@@ -249,4 +250,4 @@ MIT
249
250
 
250
251
  ---
251
252
 
252
- v3.0.0 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
253
+ v3.0.3 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
package/README.zh-CN.md CHANGED
@@ -13,8 +13,9 @@
13
13
  [![Tests](https://img.shields.io/badge/Tests-139%20passed-brightgreen.svg)]()
14
14
  [![Follow on X](https://img.shields.io/badge/X-@CCG__Workflow-black?logo=x&logoColor=white)](https://x.com/CCG_Workflow)
15
15
  ![star](https://atomgit.com/fengshao1227/ccg-workflow/star/badge.svg)
16
+ [![Docs](https://img.shields.io/badge/文档站-ccg.fengshao1227.com-blue?style=for-the-badge&logo=readthedocs&logoColor=white)](https://ccg.fengshao1227.com/)
16
17
 
17
- [简体中文](./README.zh-CN.md) | English
18
+ [简体中文](./README.zh-CN.md) | English | [**完整文档**](https://ccg.fengshao1227.com/)
18
19
 
19
20
  </div>
20
21
 
@@ -244,4 +245,4 @@ MIT
244
245
 
245
246
  ---
246
247
 
247
- v3.0.0 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
248
+ v3.0.3 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { z as diagnoseMcpConfig, A as isWindows, B as readClaudeCodeConfig, C as fixWindowsMcpConfig, D as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, E as configMcp, F as version } from './shared/ccg-workflow.2vO_S-e7.mjs';
4
+ import { z as diagnoseMcpConfig, A as isWindows, B as readClaudeCodeConfig, C as fixWindowsMcpConfig, D as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, E as configMcp, F as version } from './shared/ccg-workflow.DxKAcBrr.mjs';
5
5
  import 'inquirer';
6
6
  import 'ora';
7
7
  import 'node:child_process';
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { c as changeLanguage, x as checkForUpdates, y as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, t as getCurrentVersion, v as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, k as installWorkflows, p as migrateToV1_4_0, q as needsMigration, r as readCcgConfig, s as showMainMenu, o as uninstallAceTool, n as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.2vO_S-e7.mjs';
1
+ export { c as changeLanguage, x as checkForUpdates, y as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, t as getCurrentVersion, v as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, k as installWorkflows, p as migrateToV1_4_0, q as needsMigration, r as readCcgConfig, s as showMainMenu, o as uninstallAceTool, n as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.DxKAcBrr.mjs';
2
2
  import 'ansis';
3
3
  import 'inquirer';
4
4
  import 'ora';
@@ -10,7 +10,7 @@ import fs from 'fs-extra';
10
10
  import { parse, stringify } from 'smol-toml';
11
11
  import i18next from 'i18next';
12
12
 
13
- const version = "3.0.1";
13
+ const version = "3.0.3";
14
14
 
15
15
  function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
16
16
  return {
@@ -1028,6 +1028,10 @@ async function installSkillFiles(ctx) {
1028
1028
  overwrite: true,
1029
1029
  errorOnExist: false
1030
1030
  });
1031
+ const securityDir = join(skillsDestDir, "domains", "security");
1032
+ if (await fs.pathExists(securityDir)) {
1033
+ await fs.remove(securityDir);
1034
+ }
1031
1035
  const replacePathsInDir = async (dir) => {
1032
1036
  const entries = await fs.readdir(dir, { withFileTypes: true });
1033
1037
  for (const entry of entries) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccg-workflow",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Claude + Codex + Gemini multi-model collaboration system - smart routing development workflow",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.17.1",
@@ -46,8 +46,14 @@ Read ~/.claude/.ccg/config.toml
46
46
  | 不确定 | 双模型并行 | 各用对应 debugger |
47
47
 
48
48
  ### 实施阶段
49
- - 外部模型**仅提供建议**,Claude 执行所有文件修改
50
- - 外部模型有**零文件写入权限**
49
+
50
+ **默认模式**(Claude 执行):
51
+ - 外部模型仅提供建议,Claude 执行所有文件修改
52
+
53
+ **Codex Builder 模式**(用户选择时):
54
+ - backend 模型 + `$BACKEND/builder.md` — **有完整写权限**,直接写代码到文件系统
55
+ - Claude 监控进度,审查产出,必要时接管
56
+ - 适用于 M-L 复杂度、低中风险的明确实施任务
51
57
 
52
58
  ## 3. 调用模板
53
59
 
@@ -71,7 +77,7 @@ Bash({
71
77
 
72
78
  变量说明:
73
79
  - `$MODEL` — 选定的模型名(`codex` / `gemini` / `claude`)
74
- - `$ROLE` — 角色文件名(`analyzer` / `architect` / `reviewer` / `debugger` / `optimizer` / `tester`)
80
+ - `$ROLE` — 角色文件名(`analyzer` / `architect` / `reviewer` / `debugger` / `optimizer` / `tester` / `builder`)
75
81
  - `$TASK_CONTENT` — 任务内容(需求 + 上下文)
76
82
  - `$OUTPUT_FORMAT` — 期望输出格式
77
83
  - `$SHORT_DESCRIPTION` — 简短描述(用于进度显示)
@@ -93,3 +93,115 @@ TeamCreate 失败(Agent Teams 未启用)→ Claude 自己按计划顺序实
93
93
  - 代码块标明语言
94
94
  - 变更摘要用 git diff 格式
95
95
  - 研究结果用表格对比
96
+
97
+ ## 8. Spec Evolution Protocol — Spec 反馈环
98
+
99
+ > 让 `.ccg/spec/` 从静态文档变为随项目开发自动进化的活知识库。
100
+
101
+ ### 触发条件
102
+
103
+ 任务归档前(status → "archived"),如果以下任一条件成立,**必须执行 Spec Evolution**:
104
+ - 本次开发中发现了可复用的编码模式或约定
105
+ - 外部模型审查提出了有价值的规范建议
106
+ - 修复了一个非显而易见的坑(未来可能再踩)
107
+ - 引入了新的第三方库/API/架构模式
108
+
109
+ ### 执行步骤
110
+
111
+ 1. **提炼经验**:分析 `git diff` + review.md(如有),提取可复用的经验教训
112
+ 2. **分类归属**:判断经验属于哪个 Spec 域:
113
+ - 后端相关 → `.ccg/spec/backend/index.md`
114
+ - 前端相关 → `.ccg/spec/frontend/index.md`
115
+ - 跨模块/通用 → `.ccg/spec/guides/index.md`
116
+ 3. **草拟更新**:以追加方式写出建议新增的 Spec 条目(不覆盖现有内容)
117
+ 4. **展示给用户**:
118
+ ```
119
+ 📝 Spec Evolution — 本次开发经验提炼
120
+
121
+ 建议新增到 .ccg/spec/backend/index.md:
122
+ - [规范条目](来源:{task-name},{日期})
123
+
124
+ 确认写入?[Y/n]
125
+ ```
126
+ 5. **用户确认后写入**(⛔ 不可静默写入 Spec)
127
+ 6. **无值得提炼的经验 → 跳过**(不要强行凑条目)
128
+
129
+ ### 条目质量标准
130
+
131
+ 好的 Spec 条目:
132
+ - ✅ 具体:引用真实文件路径和 API 签名
133
+ - ✅ 说明 Why:不只说"要这样做",还说"因为…"
134
+ - ✅ 可验证:子 Agent 能根据条目判断对错
135
+
136
+ 坏的 Spec 条目:
137
+ - ❌ 空泛:"写好的代码" / "注意安全"
138
+ - ❌ 一次性:只对本次任务有价值,对未来无意义
139
+
140
+ ## 9. Loop Detection & Recovery — 死循环检测
141
+
142
+ > workflow-state Hook 自动追踪每轮的 phase + nextAction。连续 3 轮无变化触发 Break-Loop Protocol。
143
+
144
+ ### 机制
145
+
146
+ - Hook 在每轮用户消息时写入 `.ccg/tasks/{name}/.turns.json`(最近 10 轮滚动缓冲)
147
+ - 检测规则:连续 3 轮 `phase` + `nextAction` 完全相同 → 判定为死循环
148
+ - 触发后在 `<ccg-state>` 面包屑中注入 `⚠️ LOOP DETECTED` 警告
149
+
150
+ ### Break-Loop Protocol(Claude 收到警告后必须执行)
151
+
152
+ 1. **立即停止**当前重复动作
153
+ 2. **根因分析**(5 Why):
154
+ - 是外部依赖阻塞?(网络/API/权限)→ 告知用户
155
+ - 是策略不适配?→ 建议升级策略
156
+ - 是信息不足?→ 向用户提问
157
+ - 是实现路径走死?→ 换方案
158
+ 3. **更新 task.json**:`nextAction` 必须变更为新的动作描述(打破循环)
159
+ 4. **如果连续 2 次触发 Break-Loop**(即 6 轮无进展)→ 强制暂停,输出完整状态摘要请用户介入
160
+
161
+ ## 10. Ralph Loop — 迭代审查协议
162
+
163
+ > 审查不是一次性动作。每轮 spawn 新 Agent(干净上下文),读取磁盘最新状态重新验证,循环自修复。
164
+
165
+ ### 适用场景
166
+
167
+ 策略中标注为 `[Ralph Loop]` 的审查阶段,使用迭代审查代替一次性审查。
168
+
169
+ ### 标准流程
170
+
171
+ ```
172
+ Round N (N=1,2,...,MAX_ROUNDS):
173
+ 1. 双模型并行审查(每次 spawn 新 Agent,干净上下文)
174
+ 2. 质量关卡(verify-security / verify-quality / verify-change)
175
+ 3. 综合审查报告,按 Critical / Warning / Info 分级
176
+ 4. 展示给用户,询问:
177
+ - 有 Critical → "发现 N 个 Critical 问题,是否修复后再审?[Y/n]"
178
+ - 无 Critical → "审查通过,是否需要再审一轮?[y/N]"
179
+ 5. 用户选择继续 →
180
+ a. spawn fix-dev(新 Agent,干净上下文)修复 Critical 问题
181
+ b. 进度追加到 .ccg/tasks/{name}/fix-log.jsonl
182
+ c. 回到 Round N+1
183
+ 6. 用户选择停止 → 退出循环,进入下一阶段
184
+ ```
185
+
186
+ ### 关键规则
187
+
188
+ - **每轮审查必须是新 Agent** — 不复用上一轮的 Agent 上下文,避免"上下文污染越修越烂"
189
+ - **fix-dev 也是新 Agent** — 从磁盘读取最新代码状态,只修分配的问题
190
+ - **最多 3 轮**(MAX_ROUNDS=3)— 超过 3 轮说明问题根深,应该回退到规划阶段
191
+ - **用户始终有决定权** — 每轮结束后由用户决定是否继续,不自动循环
192
+ - **fix-log.jsonl 追踪进度** — 每轮结果追加一行 JSON,格式:
193
+ ```jsonl
194
+ {"round": 1, "critical": 2, "warning": 5, "fixed": ["file1:issue", "file2:issue"], "ts": "ISO"}
195
+ {"round": 2, "critical": 0, "warning": 3, "fixed": ["file3:issue"], "ts": "ISO"}
196
+ ```
197
+
198
+ ### context.jsonl 角色标注
199
+
200
+ 策展 context.jsonl 时,按角色标注 `roles` 字段:
201
+ ```jsonl
202
+ {"file": ".ccg/spec/backend/index.md", "reason": "后端规范", "roles": ["implement", "review"]}
203
+ {"file": ".ccg/tasks/{name}/plan.md", "reason": "实施计划", "roles": ["implement"]}
204
+ {"file": ".ccg/tasks/{name}/research/lib-comparison.md", "reason": "库选型", "roles": ["research", "implement"]}
205
+ ```
206
+
207
+ SubAgent-context Hook 自动按角色过滤:无 `roles` 字段 = 注入所有角色。
@@ -144,6 +144,13 @@ Gate: 用户已确认修复方向 ✓
144
144
  📍 Next: /ccg commit 提交修复
145
145
  ```
146
146
 
147
+ #### Spec Evolution(归档前必须执行)
148
+
149
+ 参考 `phase-guide.md § 8 Spec Evolution Protocol` 执行:
150
+ 1. 分析本次调试的根因和修复方案,提炼可复用的调试经验和防御性编码约定
151
+ 2. 如有值得记录的经验(特别是非显而易见的坑)→ 草拟 Spec 条目,展示给用户确认后追加到 `.ccg/spec/{domain}/index.md`
152
+ 3. 无值得提炼的经验 → 跳过
153
+
147
154
  **Task 更新**:`status → "archived"`
148
155
 
149
156
  **归档任务**:
@@ -136,19 +136,31 @@ TaskOutput({ task_id: "$FRONTEND_TASK_ID", block: true, timeout: 600000 })
136
136
  nextAction → "等待用户审批计划"
137
137
  ```
138
138
 
139
- **⛔ HARD STOP**:展示完整计划,并告知用户:
139
+ **⛔ HARD STOP**:展示完整计划,并询问用户选择执行模式:
140
+
140
141
  ```
141
- 审批后将使用 Agent Teams 并行实施(多个 Builder 同时写代码)。
142
+ 计划审批 + 执行模式选择
143
+
144
+ 请审批以上计划,并选择谁来写代码:
145
+ [1] Agent Teams(Claude Builders 并行写,多文件同时进行)
146
+ [2] Codex(Codex 写代码,更快更便宜,Claude 监控审查)
142
147
  ```
143
- 等待用户明确审批。未审批不可进入 Phase 4。
148
+
149
+ 等待用户明确审批 + 选择。未审批不可进入 Phase 4。
144
150
 
145
151
  用户确认后:`task.json: gate → null`
146
152
 
147
- ### Phase 4: 实施(Agent Teams 并行)
153
+ ### Phase 4: 实施
148
154
 
149
155
  `[模式:执行]`
150
156
 
151
- **Gate check**: 用户已审批计划
157
+ **Gate check**: 用户已审批计划 + 选择了执行模式
158
+
159
+ 根据用户选择的执行模式执行:
160
+
161
+ ---
162
+
163
+ #### 模式 A: Agent Teams 并行(用户选 [1])
152
164
 
153
165
  **⛔⛔⛔ 你的第一个动作必须是 TeamCreate。不是 Write,不是 Bash,不是 Read,是 TeamCreate。⛔⛔⛔**
154
166
 
@@ -225,21 +237,56 @@ SendMessage({ to: "reviewer", message: { type: "shutdown_request" } })
225
237
  2. 按 plan.md 中的 Layer 顺序逐文件实施
226
238
  3. 仍然遵守质量关卡
227
239
 
228
- ### Phase 5: 优化审查 + 质量关卡 [required]
240
+ ---
241
+
242
+ #### 模式 B: Codex 实施(用户选 [2])
243
+
244
+ **Task 更新**:`currentPhase → "4-implementation"`, `nextAction → "Codex Builder 执行 plan"`
245
+
246
+ Claude 作为主导者,调用 Codex 写代码:
247
+
248
+ **Step 1**: 将 plan.md 转为 Codex 可执行的任务描述(包含具体文件路径、变更说明、验证命令)
249
+
250
+ **Step 2**: 调用 codeagent-wrapper + builder 角色:
251
+
252
+ ```
253
+ Bash({
254
+ command: "~/.claude/bin/codeagent-wrapper {{LITE_MODE_FLAG}}--progress --backend codex {{GEMINI_MODEL_FLAG}}- \"$WORKDIR\" <<'CODEAGENT_EOF'\nROLE_FILE: ~/.claude/.ccg/prompts/codex/builder.md\n<TASK>\n按以下计划实施,逐个任务完成并验证。\n\n{plan.md 完整内容,包含文件路径、具体变更、验证命令}\n</TASK>\nOUTPUT: Execution Report (每个 task 的 PASS/FAIL + 变更文件列表)\nCODEAGENT_EOF",
255
+ run_in_background: true,
256
+ timeout: 3600000,
257
+ description: "Codex Builder: 执行实施计划"
258
+ })
259
+ ```
260
+
261
+ **Step 3**: 等待 Codex 完成,读取执行报告
262
+
263
+ **Step 4**: Claude 审查产出:
264
+ 1. `git diff` 检查所有变更
265
+ 2. 确认变更在 plan 范围内(scope check)
266
+ 3. 如有小问题(<10 行)→ Claude 直接修复
267
+ 4. 如有大问题 → 再次调用 Codex 修复,或切换到 Claude 自己写
268
+
269
+ **降级**:如果 Codex 返回错误或超时 → 告知用户 "Codex 执行失败,切换到 Agent Teams" → 按模式 A 执行
270
+
271
+ ### Phase 5: 迭代审查 [required · Ralph Loop]
229
272
 
230
273
  `[模式:优化]`
231
274
 
232
275
  **Gate check**: 实施已完成
233
276
 
234
- **Task 更新**:`currentPhase → "5-optimization"`, `nextAction → "双模型审查 + 质量关卡"`
277
+ **Task 更新**:`currentPhase → "5-optimization"`, `nextAction → "Ralph Loop Round 1: 双模型审查 + 质量关卡"`
278
+
279
+ 参考 `phase-guide.md § 10 Ralph Loop` 执行迭代审查。最多 3 轮。
235
280
 
236
- #### 5a. 双模型交叉审查
281
+ #### Round N 流程(N=1,2,3)
237
282
 
238
- **并行调用**:
283
+ **5a. 双模型交叉审查(每轮 spawn 新 Agent,干净上下文)**
284
+
285
+ **并行调用**(`run_in_background: true`):
239
286
  - **backend 模型**:reviewer 角色 — 关注安全、性能、错误处理
240
287
  - **frontend 模型**:reviewer 角色 — 关注可访问性、设计一致性
241
288
 
242
- #### 5b. 质量关卡
289
+ **5b. 质量关卡**
243
290
 
244
291
  **⛔ 以下 Skill 必须逐个调用执行,不可跳过,不可用自己的判断替代:**
245
292
 
@@ -247,17 +294,35 @@ SendMessage({ to: "reviewer", message: { type: "shutdown_request" } })
247
294
  2. 调用 Skill `verify-quality` — 等待报告
248
295
  3. 调用 Skill `verify-change` — 等待报告
249
296
 
250
- 任何关卡报告 **Critical** → 必须修复后重新运行该关卡,才能进入 Phase 6。
251
-
252
- #### 5c. 综合报告
297
+ **5c. 综合报告**
253
298
 
254
299
  整合审查意见 + 质量关卡结果,按严重度分级:
255
300
  - **Critical**:必须修复(阻塞交付)
256
301
  - **Warning**:建议修复
257
302
  - **Info**:供参考
258
303
 
259
- 展示审查结果,用户确认后执行必要的优化。
260
- **持久化**:写入 `.ccg/tasks/{task-name}/review.md`
304
+ **持久化**:写入 `.ccg/tasks/{task-name}/review.md`(每轮覆盖)
305
+
306
+ 追加进度到 `.ccg/tasks/{task-name}/fix-log.jsonl`:
307
+ ```jsonl
308
+ {"round": N, "critical": X, "warning": Y, "info": Z, "ts": "ISO"}
309
+ ```
310
+
311
+ **5d. 用户决定(⛔ 必须等待)**
312
+
313
+ 展示审查结果后询问用户:
314
+ - 有 Critical → `发现 N 个 Critical 问题。修复后再审一轮?[Y/n]`
315
+ - 无 Critical 但有 Warning → `无 Critical 问题。需要再审一轮处理 Warning?[y/N]`
316
+ - 全部通过 → 直接进入 Phase 6
317
+
318
+ 用户选择继续 →
319
+ 1. spawn fix-dev(**新 Agent,干净上下文**)修复 Critical/Warning
320
+ 2. fix-dev 完成后回到 5a 开始 Round N+1
321
+ 3. 追加修复记录到 fix-log.jsonl
322
+
323
+ 用户选择停止 → 进入 Phase 6
324
+
325
+ **第 3 轮仍有 Critical** → 强制停止,建议回退到 Phase 3 重新规划。
261
326
 
262
327
  ### Phase 6: 最终验收
263
328
 
@@ -277,6 +342,13 @@ SendMessage({ to: "reviewer", message: { type: "shutdown_request" } })
277
342
  📍 Next: /ccg commit 提交,或查看 .ccg/tasks/{task-name}/ 中的完整记录
278
343
  ```
279
344
 
345
+ #### Spec Evolution(归档前必须执行)
346
+
347
+ 参考 `phase-guide.md § 8 Spec Evolution Protocol` 执行:
348
+ 1. 分析本次 `git diff` + `review.md`,提炼可复用的编码约定和经验教训
349
+ 2. 如有值得记录的经验 → 草拟 Spec 条目,展示给用户确认后追加到 `.ccg/spec/{domain}/index.md`
350
+ 3. 无值得提炼的经验 → 跳过(不强行凑)
351
+
280
352
  **Task 更新**:`status → "archived"`
281
353
 
282
354
  **归档任务**:将 `.ccg/tasks/{task-name}/` 移动到 `.ccg/tasks/archive/YYYY-MM/{task-name}/`
@@ -145,7 +145,17 @@ TaskOutput({ task_id: "<id>", block: true, timeout: 600000 })
145
145
  nextAction → "等待用户审批计划"
146
146
  ```
147
147
 
148
- **⛔ HARD STOP**:展示计划,等待用户确认后才能进入 Phase 5。
148
+ **⛔ HARD STOP**:展示计划,并询问用户选择执行模式:
149
+
150
+ ```
151
+ ⛔ 计划审批 + 执行模式选择
152
+
153
+ 请审批以上计划,并选择谁来写代码:
154
+ [1] Claude 自己写(精细控制,逐步实施)
155
+ [2] Codex(Codex 写代码,更快更便宜,Claude 监控审查)
156
+ ```
157
+
158
+ 等待用户明确审批 + 选择。
149
159
 
150
160
  用户确认后:
151
161
  ```
@@ -154,40 +164,75 @@ TaskOutput({ task_id: "<id>", block: true, timeout: 600000 })
154
164
 
155
165
  ### Phase 5: 实施
156
166
 
167
+ 根据用户选择的执行模式:
168
+
169
+ #### 模式 A: Claude 自己写(用户选 [1])
170
+
157
171
  1. 严格按计划执行
158
172
  2. 遵循项目现有代码规范
159
173
  3. 每完成一个主要步骤,简要报告进度
160
174
  4. 遇到计划外的问题时告知用户,不自行扩大范围
161
175
 
176
+ #### 模式 B: Codex 实施(用户选 [2])
177
+
178
+ Claude 作为主导者调用 Codex 写代码:
179
+
180
+ 1. 将 plan.md 转为 Codex 可执行的任务描述
181
+ 2. 调用 codeagent-wrapper + builder 角色(参考 model-router.md 调用模板,`$ROLE = builder`)
182
+ 3. 等待 Codex 完成,读取执行报告
183
+ 4. `git diff` 审查产出,确认在 plan 范围内
184
+ 5. 小问题 Claude 直接修复,大问题再调 Codex 或切换模式 A
185
+
186
+ **降级**:Codex 失败/超时 → 切换到模式 A
187
+
162
188
  **Task 更新**:`currentPhase → "5-implement"`, `nextAction → "按计划执行实施"`
163
189
 
164
- ### Phase 6: 验证 + 双模型审查 + 质量关卡
190
+ ### Phase 6: 迭代审查 [Ralph Loop]
165
191
 
166
192
  1. `git diff` 展示所有变更
167
193
  2. 运行测试(如果有)
168
194
 
169
- **⛔ 双模型交叉审查(变更 >30 行时必须执行):**
195
+ 参考 `phase-guide.md § 10 Ralph Loop` 执行迭代审查(变更 >30 行时,最多 3 轮)。
196
+
197
+ #### Round N 流程
198
+
199
+ **⛔ 双模型交叉审查(每轮 spawn 新调用,干净上下文):**
170
200
  3. 并行调用双模型(`run_in_background: true`,使用 model-router.md 模板):
171
201
  - backend 模型 + reviewer 角色 — 安全、性能、错误处理
172
202
  - frontend 模型 + reviewer 角色 — 设计一致性(如涉及前端)
173
203
  4. 综合审查意见
174
204
 
175
- **⛔ 质量关卡(变更 >30 行时必须逐个调用 Skill,不可跳过):**
205
+ **⛔ 质量关卡(必须逐个调用 Skill,不可跳过):**
176
206
  5. 调用 Skill `verify-quality` — 等待报告
177
207
  6. 调用 Skill `verify-security` — 等待报告(涉及 auth/input/crypto 时)
178
208
  7. 调用 Skill `verify-change` — 等待报告
179
- 8. Critical 问题必须修复
180
- 4. 检查是否满足验收标准
181
- 5. 输出结果:
209
+
210
+ **用户决定(⛔ 必须等待):**
211
+ - 有 Critical → `发现 N 个 Critical 问题。修复后再审一轮?[Y/n]`
212
+ - 无 Critical → `审查通过。需要再审一轮?[y/N]`
213
+ - 用户选择继续 → 修复 Critical 后回到 Round N+1
214
+ - 用户选择停止 → 退出审查循环
215
+
216
+ 追加进度到 `.ccg/tasks/{task-name}/fix-log.jsonl`。
217
+
218
+ 8. 检查是否满足验收标准
219
+ 9. 输出结果:
182
220
  ```
183
221
  ✅ 开发完成
184
222
  变更: [N] 文件,[M] 行
185
223
  实现: [摘要]
186
224
  测试: [通过/跳过/失败情况]
187
- 质量: [Critical: N, Warning: N, Info: N]
225
+ 审查: [N] 轮,[Critical: N, Warning: N, Info: N]
188
226
  📍 Next: 可以用 /ccg:commit 提交
189
227
  ```
190
228
 
229
+ #### Spec Evolution(归档前必须执行)
230
+
231
+ 参考 `phase-guide.md § 8 Spec Evolution Protocol` 执行:
232
+ 1. 分析本次 `git diff` + 审查结果,提炼可复用的编码约定
233
+ 2. 如有值得记录的经验 → 草拟 Spec 条目,展示给用户确认后追加到 `.ccg/spec/{domain}/index.md`
234
+ 3. 无值得提炼的经验 → 跳过
235
+
191
236
  **Task 更新**:`status → "archived"`
192
237
 
193
238
  **归档任务**:
@@ -110,12 +110,16 @@ Gate: 所有步骤已执行 ✓
110
110
  Step [N/M]: [描述] — ✅ 测试通过 / ❌ 测试失败
111
111
  ```
112
112
 
113
- ### Phase 5: 最终验证 + 双模型审查 + 质量关卡
113
+ ### Phase 5: 迭代审查 [Ralph Loop]
114
114
 
115
115
  1. 运行完整测试套件
116
116
  2. 对比基线:确保不引入新的失败
117
117
 
118
- **⛔ 双模型交叉审查(必须执行,使用 model-router.md 调用模板):**
118
+ 参考 `phase-guide.md § 10 Ralph Loop` 执行迭代审查(最多 3 轮)。
119
+
120
+ #### Round N 流程
121
+
122
+ **⛔ 双模型交叉审查(每轮 spawn 新调用,干净上下文):**
119
123
 
120
124
  3. 获取变更:`git diff` 全量输出
121
125
  4. 并行调用双模型审查(`run_in_background: true`):
@@ -129,22 +133,35 @@ Step [N/M]: [描述] — ✅ 测试通过 / ❌ 测试失败
129
133
  7. 调用 Skill `verify-security` — 等待报告
130
134
  8. 调用 Skill `verify-change` — 等待报告
131
135
 
132
- **综合报告**:双模型审查 + 质量关卡,按严重度分级:
133
- - Critical → 必须修复后重新验证
134
- - Warning → 建议修复
135
- - Info供参考
136
+ **综合报告**:双模型审查 + 质量关卡,按严重度分级
137
+
138
+ **用户决定(⛔ 必须等待):**
139
+ - Critical `发现 N 个 Critical 问题。修复后再审一轮?[Y/n]`
140
+ - 无 Critical → `审查通过。需要再审一轮?[y/N]`
141
+ - 用户选择继续 → 修复后回到 Round N+1
142
+ - 用户选择停止 → 退出审查循环
143
+
144
+ 追加进度到 `.ccg/tasks/{task-name}/fix-log.jsonl`。
136
145
 
137
146
  9. `git diff` 展示全部变更
138
- 5. 输出结果:
147
+ 10. 对比基线,确认无回归
148
+ 11. 输出结果:
139
149
  ```
140
150
  ✅ 重构完成
141
151
  步骤: [N] 步全部通过
142
152
  变更: [文件数] 文件,[行数] 行
143
153
  测试: 基线 [N] 通过 → 重构后 [N] 通过
144
- 质量: [Critical: N, Warning: N, Info: N]
154
+ 审查: [N] 轮,[Critical: N, Warning: N, Info: N]
145
155
  📍 Next: /ccg:commit 提交
146
156
  ```
147
157
 
158
+ #### Spec Evolution(归档前必须执行)
159
+
160
+ 参考 `phase-guide.md § 8 Spec Evolution Protocol` 执行:
161
+ 1. 分析本次重构的 `git diff`,提炼可复用的重构模式和架构约定
162
+ 2. 如有值得记录的经验 → 草拟 Spec 条目,展示给用户确认后追加到 `.ccg/spec/{domain}/index.md`
163
+ 3. 无值得提炼的经验 → 跳过
164
+
148
165
  **Task 更新**:`status → "archived"`
149
166
 
150
167
  **归档任务**:
@@ -106,6 +106,13 @@ Gate: 双模型审查已返回 ✓
106
106
 
107
107
  如果有 Critical 发现,询问用户是否立即修复(可切换到 `direct-fix` 策略)。
108
108
 
109
+ #### Spec Evolution(审查完成后执行)
110
+
111
+ 参考 `phase-guide.md § 8 Spec Evolution Protocol` 执行:
112
+ 1. 从审查发现中提炼可复用的编码规范(特别是 Critical/Warning 级反复出现的模式)
113
+ 2. 如有值得记录的经验 → 草拟 Spec 条目,展示给用户确认后追加到 `.ccg/spec/{domain}/index.md`
114
+ 3. 无值得提炼的经验 → 跳过
115
+
109
116
  ---
110
117
 
111
118
  ## 铁律
@@ -3,6 +3,8 @@
3
3
  // Injects spec + task context when:
4
4
  // 1. codeagent-wrapper is about to be called (Bash)
5
5
  // 2. Agent Team member is about to be spawned (Agent)
6
+ // Supports role-based filtering: context.jsonl entries with "roles" field
7
+ // are only injected when the agent's detected role matches.
6
8
 
7
9
  'use strict';
8
10
 
@@ -28,12 +30,11 @@ try {
28
30
  // Determine trigger type
29
31
  const command = toolInput.command || '';
30
32
  const teamName = toolInput.team_name || '';
31
- const agentPrompt = toolInput.prompt || '';
33
+ const agentName = toolInput.name || '';
32
34
 
33
35
  const isCodeagentCall = command.includes('codeagent-wrapper');
34
36
  const isTeamSpawn = !!teamName;
35
37
 
36
- // Only activate for codeagent-wrapper calls or Agent Team spawns
37
38
  if (!isCodeagentCall && !isTeamSpawn) {
38
39
  process.exit(0);
39
40
  }
@@ -45,20 +46,60 @@ try {
45
46
  const task = getActiveTask(root);
46
47
  if (!task) process.exit(0);
47
48
 
49
+ // --- Role detection ---
50
+ const ROLE_FILE_MAP = {
51
+ 'reviewer': 'review',
52
+ 'analyzer': 'research',
53
+ 'debugger': 'debug',
54
+ 'tester': 'review',
55
+ 'architect': 'implement',
56
+ 'optimizer': 'implement',
57
+ 'frontend': 'implement'
58
+ };
59
+ const AGENT_NAME_PATTERNS = [
60
+ { pattern: /dev|builder|fix|impl/i, role: 'implement' },
61
+ { pattern: /review|check|audit/i, role: 'review' },
62
+ { pattern: /research|scout|explore|analy/i, role: 'research' },
63
+ { pattern: /debug|diagnos/i, role: 'debug' }
64
+ ];
65
+
66
+ let detectedRole = 'implement'; // default
67
+
68
+ if (isCodeagentCall) {
69
+ const roleMatch = command.match(/ROLE_FILE:.*\/(\w+)\.md/);
70
+ if (roleMatch) {
71
+ detectedRole = ROLE_FILE_MAP[roleMatch[1]] || 'implement';
72
+ }
73
+ } else if (isTeamSpawn && agentName) {
74
+ for (const { pattern, role } of AGENT_NAME_PATTERNS) {
75
+ if (pattern.test(agentName)) {
76
+ detectedRole = role;
77
+ break;
78
+ }
79
+ }
80
+ }
81
+
48
82
  const contextParts = [];
49
83
 
50
- // Inject active task info for team members
51
84
  if (isTeamSpawn) {
52
85
  contextParts.push(`<ccg-active-task>
53
86
  Active task: ${task.dir}
54
87
  Task: ${task.title || task.id} (${task.status})
55
88
  Strategy: ${task.strategy}
56
89
  Phase: ${task.currentPhase}
90
+ Agent role: ${detectedRole}
57
91
  </ccg-active-task>`);
58
92
  }
59
93
 
60
- // Read context.jsonl entries (specs + research refs)
61
- const entries = readContextJsonl(task.dir);
94
+ // Read context.jsonl with role-based filtering
95
+ const allEntries = readContextJsonl(task.dir);
96
+ const entries = allEntries.filter(entry => {
97
+ if (!entry.roles || !Array.isArray(entry.roles) || entry.roles.length === 0) {
98
+ return true; // no roles field = inject to all
99
+ }
100
+ return entry.roles.includes(detectedRole) || entry.roles.includes('all');
101
+ });
102
+
62
103
  if (entries.length > 0) {
63
104
  const specContents = [];
64
105
  for (const entry of entries) {
@@ -75,7 +116,7 @@ Phase: ${task.currentPhase}
75
116
  }
76
117
  }
77
118
 
78
- // Read PRD and plan
119
+ // Read PRD and plan (always inject, role-independent)
79
120
  const prd = readFileSafe(path.join(task.dir, 'requirements.md'));
80
121
  const plan = readFileSafe(path.join(task.dir, 'plan.md'));
81
122
 
@@ -93,21 +134,23 @@ Phase: ${task.currentPhase}
93
134
  contextParts.push(taskContext.join('\n'));
94
135
  }
95
136
 
96
- // Read research files
97
- const researchDir = path.join(task.dir, 'research');
98
- if (fs.existsSync(researchDir)) {
99
- try {
100
- const researchFiles = fs.readdirSync(researchDir).filter(f => f.endsWith('.md'));
101
- if (researchFiles.length > 0) {
102
- const researchContents = researchFiles.map(f => {
103
- const content = readFileSafe(path.join(researchDir, f));
104
- return content ? `--- research/${f} ---\n${content.substring(0, 1500)}` : null;
105
- }).filter(Boolean);
106
- if (researchContents.length > 0) {
107
- contextParts.push(`<ccg-research>\n${researchContents.join('\n\n')}\n</ccg-research>`);
137
+ // Read research files (only for research + implement roles)
138
+ if (detectedRole === 'research' || detectedRole === 'implement') {
139
+ const researchDir = path.join(task.dir, 'research');
140
+ if (fs.existsSync(researchDir)) {
141
+ try {
142
+ const researchFiles = fs.readdirSync(researchDir).filter(f => f.endsWith('.md'));
143
+ if (researchFiles.length > 0) {
144
+ const researchContents = researchFiles.map(f => {
145
+ const content = readFileSafe(path.join(researchDir, f));
146
+ return content ? `--- research/${f} ---\n${content.substring(0, 1500)}` : null;
147
+ }).filter(Boolean);
148
+ if (researchContents.length > 0) {
149
+ contextParts.push(`<ccg-research>\n${researchContents.join('\n\n')}\n</ccg-research>`);
150
+ }
108
151
  }
109
- }
110
- } catch { /* silent */ }
152
+ } catch { /* silent */ }
153
+ }
111
154
  }
112
155
 
113
156
  if (contextParts.length === 0) process.exit(0);
@@ -152,6 +152,27 @@ function seedContextJsonl(taskDir, projectRoot) {
152
152
  try { fs.writeFileSync(jsonlPath, lines.join('\n') + '\n', 'utf-8'); } catch { /* silent */ }
153
153
  }
154
154
 
155
+ function trackTurn(taskDir, phase, nextAction) {
156
+ const turnsPath = path.join(taskDir, '.turns.json');
157
+ let turns = [];
158
+ try { turns = JSON.parse(fs.readFileSync(turnsPath, 'utf-8')); } catch { /* fresh */ }
159
+ turns.push({ phase: phase || '', next: nextAction || '', ts: Date.now() });
160
+ if (turns.length > 10) turns = turns.slice(-10);
161
+ try { fs.writeFileSync(turnsPath, JSON.stringify(turns), 'utf-8'); } catch { /* silent */ }
162
+ return turns;
163
+ }
164
+
165
+ function detectLoop(turns, threshold) {
166
+ threshold = threshold || 3;
167
+ if (turns.length < threshold) return null;
168
+ const recent = turns.slice(-threshold);
169
+ const key = `${recent[0].phase}|${recent[0].next}`;
170
+ const allSame = recent.every(t => `${t.phase}|${t.next}` === key);
171
+ if (!allSame) return null;
172
+ const elapsed = (recent[recent.length - 1].ts - recent[0].ts) / 1000;
173
+ return { phase: recent[0].phase, nextAction: recent[0].next, count: threshold, elapsedSec: Math.round(elapsed) };
174
+ }
175
+
155
176
  module.exports = {
156
177
  findProjectRoot,
157
178
  getActiveTask,
@@ -163,5 +184,7 @@ module.exports = {
163
184
  outputHook,
164
185
  archiveTask,
165
186
  autoCommitTask,
166
- seedContextJsonl
187
+ seedContextJsonl,
188
+ trackTurn,
189
+ detectLoop
167
190
  };
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  // CCG Workflow State Hook — UserPromptSubmit
3
3
  // Injects per-turn breadcrumb based on active task state.
4
+ // Includes loop detection: warns when same phase+nextAction repeats 3+ turns.
4
5
  // Runs on EVERY user message. Must be fast (<1s) and never crash.
5
6
 
6
7
  'use strict';
7
8
 
8
9
  try {
9
- const { findProjectRoot, getActiveTask, outputHook } = require('./task-utils.js');
10
+ const { findProjectRoot, getActiveTask, outputHook, trackTurn, detectLoop } = require('./task-utils.js');
10
11
 
11
12
  const cwd = process.env.CLAUDE_PROJECT_DIR || process.cwd();
12
13
  const root = findProjectRoot(cwd);
@@ -19,6 +20,9 @@ try {
19
20
  process.exit(0);
20
21
  }
21
22
 
23
+ const turns = trackTurn(task.dir, task.currentPhase, task.nextAction);
24
+ const loop = detectLoop(turns, 3);
25
+
22
26
  const lines = [
23
27
  '<ccg-state>',
24
28
  `Task: ${task.title || task.id} (${task.status})`,
@@ -31,6 +35,18 @@ try {
31
35
  }
32
36
 
33
37
  lines.push(`Next: ${task.nextAction || 'Continue current phase'}`);
38
+
39
+ if (loop) {
40
+ lines.push('');
41
+ lines.push(`⚠️ LOOP DETECTED: Phase "${loop.phase}" with same nextAction repeated ${loop.count} turns (${loop.elapsedSec}s).`);
42
+ lines.push('🔄 BREAK-LOOP PROTOCOL:');
43
+ lines.push(' 1. STOP current approach immediately');
44
+ lines.push(' 2. Root-cause analysis: why is this phase not progressing?');
45
+ lines.push(' 3. Options: (a) try alternative approach, (b) escalate to user, (c) upgrade strategy');
46
+ lines.push(' 4. If blocked by external dependency → tell user explicitly');
47
+ lines.push(' 5. Do NOT repeat the same action — that is what caused this loop');
48
+ }
49
+
34
50
  lines.push('</ccg-state>');
35
51
 
36
52
  outputHook('UserPromptSubmit', lines.join('\n'));
@@ -0,0 +1,61 @@
1
+ # Codex Role: Builder (Implementation Agent)
2
+
3
+ > For: /ccg:go strategies Phase 4/5 (execution), when user selects Codex as executor
4
+
5
+ You are an implementation engineer. Claude has already planned the work — your job is to **write the code** exactly as specified in the plan.
6
+
7
+ ## PERMISSIONS
8
+
9
+ - **FULL file system write permission** - You CAN and SHOULD create/modify/delete files
10
+ - **FULL shell access** - You CAN run tests, linters, build commands
11
+ - You operate in the project working directory provided
12
+
13
+ ## Execution Rules
14
+
15
+ 1. **Read context first** — Before writing, read all files referenced in the plan to understand existing patterns
16
+ 2. **Follow the plan exactly** — Do not add features, refactor, or "improve" things not in the plan
17
+ 3. **One task at a time** — Complete each task fully before moving to the next
18
+ 4. **Validate after each task** — Run the specified test/lint command after each change
19
+ 5. **Fix validation failures** — If a test fails after your change, fix it (max 3 attempts per task)
20
+ 6. **Stay in scope** — Only modify files listed in the plan. If you discover a necessary change outside scope, note it in your output but do NOT make it
21
+ 7. **Report progress** — After each task, output a status line
22
+
23
+ ## Output Format
24
+
25
+ After completing all tasks, output a summary:
26
+
27
+ ```
28
+ ## Execution Report
29
+
30
+ ### Task 1: [description]
31
+ - Status: PASS / FAIL
32
+ - Files changed: [list]
33
+ - Validation: [command] → [pass/fail]
34
+
35
+ ### Task 2: [description]
36
+ - Status: PASS / FAIL
37
+ - Files changed: [list]
38
+ - Validation: [command] → [pass/fail]
39
+
40
+ ---
41
+ OVERALL: [PASS/FAIL]
42
+ Total files changed: [N]
43
+ All validations passed: [yes/no]
44
+ ```
45
+
46
+ ## What NOT to Do
47
+
48
+ - ❌ Do NOT refactor code outside the plan scope
49
+ - ❌ Do NOT add comments explaining your changes
50
+ - ❌ Do NOT install new dependencies unless the plan explicitly says to
51
+ - ❌ Do NOT modify test files unless the plan explicitly includes them
52
+ - ❌ Do NOT ask questions — if the plan is ambiguous, make the simplest choice that satisfies the spec
53
+
54
+ ## .context Awareness
55
+
56
+ If the project has a `.context/` directory:
57
+ 1. Read `.context/prefs/coding-style.md` before writing code — follow those conventions
58
+ 2. Follow all coding conventions defined in prefs/
59
+
60
+ If the project has `.ccg/spec/`:
61
+ 1. Read relevant spec files — follow those coding standards
@@ -4,7 +4,11 @@ When the user's request matches trigger keywords below, automatically READ the c
4
4
 
5
5
  **IMPORTANT**: Read the skill file FIRST, then respond. Do NOT fabricate domain knowledge from training data when a skill file exists.
6
6
 
7
- ## Security Domain (`domains/security/`)
7
+ ## Security Domain (`domains/security/`) — NOT installed by default
8
+
9
+ > Security domain files contain red team/pentest reference content that may trigger antivirus false positives.
10
+ > They are NOT installed by default. To enable, manually copy from the npm package:
11
+ > `cp -r $(npm root -g)/ccg-workflow/templates/skills/domains/security/ ~/.claude/skills/ccg/domains/security/`
8
12
 
9
13
  | Trigger Keywords | Skill File | Description |
10
14
  |------------------|-----------|-------------|