ccgx-workflow 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.mjs +180 -2
  3. package/dist/index.mjs +3 -2
  4. package/dist/shared/{ccgx-workflow.Bl0vlpC_.mjs → ccgx-workflow.BrRMgXjP.mjs} +22 -13
  5. package/package.json +1 -1
  6. package/templates/commands/agents/code-fixer.md +1 -1
  7. package/templates/commands/agents/codebase-mapper.md +1 -1
  8. package/templates/commands/agents/debug-session-manager.md +1 -1
  9. package/templates/commands/agents/debugger.md +1 -1
  10. package/templates/commands/agents/interface-auditor.md +40 -12
  11. package/templates/commands/agents/phase-runner.md +27 -27
  12. package/templates/commands/agents/plan-checker.md +4 -4
  13. package/templates/commands/analyze.md +10 -10
  14. package/templates/commands/autonomous.md +45 -46
  15. package/templates/commands/cancel.md +8 -8
  16. package/templates/commands/codex-exec.md +2 -2
  17. package/templates/commands/debate.md +5 -5
  18. package/templates/commands/debug.md +8 -8
  19. package/templates/commands/execute.md +6 -6
  20. package/templates/commands/init.md +1 -1
  21. package/templates/commands/optimize.md +10 -10
  22. package/templates/commands/plan.md +15 -15
  23. package/templates/commands/result.md +1 -1
  24. package/templates/commands/review.md +120 -65
  25. package/templates/commands/spec-impl.md +1 -1
  26. package/templates/commands/spec-plan.md +2 -2
  27. package/templates/commands/spec-research.md +1 -1
  28. package/templates/commands/spec-review.md +1 -1
  29. package/templates/commands/status.md +15 -15
  30. package/templates/commands/team-exec.md +1 -1
  31. package/templates/commands/team.md +6 -6
  32. package/templates/commands/test.md +9 -9
  33. package/templates/commands/verify-work.md +8 -8
  34. package/templates/commands/verify.md +3 -3
  35. package/templates/commands/workflow.md +2 -2
  36. package/templates/rules/ccg-skills.md +1 -1
  37. package/templates/scripts/ccgx-call-plugin.mjs +324 -0
  38. package/templates/skills/tools/extract-learnings/SKILL.md +1 -3
  39. package/templates/skills/tools/forensics/SKILL.md +0 -2
  40. package/templates/skills/tools/health/SKILL.md +0 -2
  41. package/templates/skills/tools/map-codebase/SKILL.md +0 -2
  42. package/templates/skills/tools/verify-change/SKILL.md +2 -2
  43. package/templates/skills/tools/verify-module/SKILL.md +2 -2
  44. package/templates/skills/tools/verify-quality/SKILL.md +2 -2
  45. package/templates/skills/tools/verify-security/SKILL.md +2 -2
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  > `ccgx-workflow` is a deep rewrite of [`ccg-workflow`](https://www.npmjs.com/package/ccg-workflow) v3.x.
17
17
  > The original project went unmaintained after 2026-05 (the original author's
18
18
  > GitHub homepage went offline), leaving its multi-model collaboration users
19
- > exposed to drift. This project re-architected from v4.0 onward:
19
+ > exposed to drift. This project re-architected from the ground up:
20
20
  > fresh-context subagent protocols, Plan-Critic-Verify quality tiers,
21
21
  > OS-level three-layer process isolation, broker tx_id anti-drift,
22
22
  > and 8 plugin patches with a one-shot repatch script.
package/dist/cli.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { d as diagnoseMcpConfig, i as isWindows, r as readClaudeCodeConfig, f as fixWindowsMcpConfig, w as writeClaudeCodeConfig, a as readCcgConfig, b as initI18n, c as i18n, s as showMainMenu, e as init, g as configMcp, v as version } from './shared/ccgx-workflow.Bl0vlpC_.mjs';
4
+ import { d as diagnoseMcpConfig, i as isWindows, r as readClaudeCodeConfig, f as fixWindowsMcpConfig, w as writeClaudeCodeConfig, a as readCcgConfig, b as initI18n, c as i18n, s as showMainMenu, e as init, g as configMcp, v as version } from './shared/ccgx-workflow.BrRMgXjP.mjs';
5
+ import { execSync } from 'node:child_process';
5
6
  import 'inquirer';
6
7
  import 'ora';
7
- import 'node:child_process';
8
8
  import 'node:util';
9
9
  import 'node:os';
10
10
  import 'node:url';
@@ -12,6 +12,7 @@ import 'pathe';
12
12
  import 'fs-extra';
13
13
  import 'smol-toml';
14
14
  import 'node:fs';
15
+ import 'node:path/posix';
15
16
  import 'node:path';
16
17
  import 'i18next';
17
18
 
@@ -74,6 +75,177 @@ async function fixMcp() {
74
75
  }
75
76
  }
76
77
 
78
+ function categorize(cmdLine) {
79
+ const cmd = cmdLine.toLowerCase();
80
+ if (/quasar|vite|webpack|next\b|nuxt|astro|svelte-kit|pnpm.*run.*dev|npm.*run.*dev|yarn.*run.*dev|yarn dev|pnpm dev|npm run dev/.test(cmd)) {
81
+ return "dev-server";
82
+ }
83
+ if (/ccg-phase-runner-launcher|ccgx-call-plugin/.test(cmd)) return "phase-runner";
84
+ if (/codex-companion|codex-cli|@openai\/codex|openai-codex.*codex/.test(cmd)) return "codex-cli";
85
+ if (/gemini-companion|@google\/gemini-cli|google-gemini.*gemini/.test(cmd)) return "gemini-cli";
86
+ if (/playwright|context7|contextweaver|fast-context|ace-tool/.test(cmd)) return "mcp-server";
87
+ return "other";
88
+ }
89
+ function listNodeProcessesWindows() {
90
+ const ps = `Get-CimInstance Win32_Process -Filter "Name='node.exe'" | ForEach-Object {
91
+ $cd = $_.CreationDate
92
+ $h = if ($cd) { ((Get-Date) - $cd).TotalHours } else { 0 }
93
+ $cmd = if ($_.CommandLine) { $_.CommandLine } else { '' }
94
+ "$($_.ProcessId)|$h|$cmd"
95
+ }`;
96
+ let out;
97
+ try {
98
+ out = execSync(`powershell -NoProfile -Command "${ps.replace(/\n\s+/g, " ")}"`, {
99
+ encoding: "utf-8",
100
+ maxBuffer: 16 * 1024 * 1024
101
+ });
102
+ } catch {
103
+ return [];
104
+ }
105
+ const procs = [];
106
+ for (const line of out.split(/\r?\n/)) {
107
+ const trimmed = line.trim();
108
+ if (!trimmed) continue;
109
+ const sep1 = trimmed.indexOf("|");
110
+ const sep2 = trimmed.indexOf("|", sep1 + 1);
111
+ if (sep1 < 0 || sep2 < 0) continue;
112
+ const pid = Number.parseInt(trimmed.slice(0, sep1), 10);
113
+ const ageHours = Number.parseFloat(trimmed.slice(sep1 + 1, sep2));
114
+ const cmdLine = trimmed.slice(sep2 + 1);
115
+ if (Number.isNaN(pid)) continue;
116
+ procs.push({
117
+ pid,
118
+ ageHours: Number.isFinite(ageHours) ? ageHours : 0,
119
+ cmdLine,
120
+ category: categorize(cmdLine)
121
+ });
122
+ }
123
+ return procs;
124
+ }
125
+ function listNodeProcessesPosix() {
126
+ let out;
127
+ try {
128
+ out = execSync("ps -eo pid,etime,command", { encoding: "utf-8", maxBuffer: 16 * 1024 * 1024 });
129
+ } catch {
130
+ return [];
131
+ }
132
+ const procs = [];
133
+ for (const line of out.split("\n").slice(1)) {
134
+ const m = line.match(/^\s*(\d+)\s+(\S+)\s+(.+)$/);
135
+ if (!m) continue;
136
+ const cmdLine = m[3];
137
+ if (!/(^|\/)node(\s|$)/.test(cmdLine)) continue;
138
+ const pid = Number.parseInt(m[1], 10);
139
+ const etime = m[2];
140
+ const parts = etime.split(/[-:]/).map((s) => Number.parseInt(s, 10));
141
+ let ageHours = 0;
142
+ if (parts.length === 4) ageHours = parts[0] * 24 + parts[1] + parts[2] / 60;
143
+ else if (parts.length === 3) ageHours = parts[0] + parts[1] / 60;
144
+ else if (parts.length === 2) ageHours = parts[0] / 60;
145
+ procs.push({
146
+ pid,
147
+ ageHours,
148
+ cmdLine,
149
+ category: categorize(cmdLine)
150
+ });
151
+ }
152
+ return procs;
153
+ }
154
+ function listNodeProcesses() {
155
+ return isWindows() ? listNodeProcessesWindows() : listNodeProcessesPosix();
156
+ }
157
+ function killProcessWindows(pid) {
158
+ try {
159
+ execSync(`powershell -NoProfile -Command "Stop-Process -Id ${pid} -Force -ErrorAction Stop"`, { stdio: "pipe" });
160
+ return { ok: true, method: "Stop-Process" };
161
+ } catch {
162
+ }
163
+ try {
164
+ execSync(`taskkill /F /PID ${pid}`, { stdio: "pipe" });
165
+ return { ok: true, method: "taskkill /F" };
166
+ } catch {
167
+ }
168
+ try {
169
+ execSync(`wmic process where "ProcessId=${pid}" delete`, { stdio: "pipe" });
170
+ return { ok: true, method: "wmic delete" };
171
+ } catch (e) {
172
+ return { ok: false, method: "all-failed", error: e instanceof Error ? e.message : String(e) };
173
+ }
174
+ }
175
+ function killProcessPosix(pid) {
176
+ try {
177
+ execSync(`kill -TERM ${pid}`, { stdio: "pipe" });
178
+ return { ok: true, method: "SIGTERM" };
179
+ } catch {
180
+ }
181
+ try {
182
+ execSync(`kill -KILL ${pid}`, { stdio: "pipe" });
183
+ return { ok: true, method: "SIGKILL" };
184
+ } catch (e) {
185
+ return { ok: false, method: "all-failed", error: e instanceof Error ? e.message : String(e) };
186
+ }
187
+ }
188
+ async function killOrphans(options = {}) {
189
+ const dryRun = options.dryRun ?? true;
190
+ const minAgeHours = options.minAgeHours ?? 1;
191
+ console.log(ansis.cyan.bold("\n ccgx kill-orphans"));
192
+ console.log(ansis.gray(` ${dryRun ? "[DRY-RUN]" : "[KILL MODE]"} target: orphan node processes >${minAgeHours}h
193
+ `));
194
+ const all = listNodeProcesses();
195
+ if (all.length === 0) {
196
+ console.log(ansis.yellow(" No node processes found (or unable to list)."));
197
+ return;
198
+ }
199
+ const groups = /* @__PURE__ */ new Map();
200
+ for (const p of all) {
201
+ if (!groups.has(p.category)) groups.set(p.category, []);
202
+ groups.get(p.category).push(p);
203
+ }
204
+ console.log(ansis.bold(" Inventory:"));
205
+ for (const cat of ["mcp-server", "codex-cli", "gemini-cli", "phase-runner", "dev-server", "other"]) {
206
+ const list = groups.get(cat) ?? [];
207
+ if (list.length === 0) continue;
208
+ const oldestH = Math.max(...list.map((p) => p.ageHours));
209
+ const tag = cat === "dev-server" ? ansis.green("SAFE") : cat === "other" ? ansis.gray("UNKN") : ansis.yellow("ORPH");
210
+ console.log(` ${tag} ${cat.padEnd(14)} ${String(list.length).padStart(3)} processes (oldest ${oldestH.toFixed(1)}h)`);
211
+ }
212
+ console.log();
213
+ const ORPHAN_CATS = ["mcp-server", "codex-cli", "gemini-cli", "phase-runner"];
214
+ const targets = all.filter((p) => ORPHAN_CATS.includes(p.category) && p.ageHours >= minAgeHours);
215
+ if (targets.length === 0) {
216
+ console.log(ansis.green(` \u2713 No orphans >${minAgeHours}h to clean.`));
217
+ return;
218
+ }
219
+ console.log(ansis.bold(` Targets (${targets.length}):`));
220
+ for (const p of targets) {
221
+ const cmdShort = p.cmdLine.length > 70 ? `${p.cmdLine.slice(0, 70)}...` : p.cmdLine;
222
+ console.log(` PID ${String(p.pid).padStart(6)} ${p.ageHours.toFixed(1).padStart(5)}h ${ansis.gray(p.category.padEnd(14))} ${cmdShort}`);
223
+ }
224
+ console.log();
225
+ if (dryRun) {
226
+ console.log(ansis.gray(` Run with --kill to actually terminate (skips dev-server / other categories).`));
227
+ return;
228
+ }
229
+ const killer = isWindows() ? killProcessWindows : killProcessPosix;
230
+ let killed = 0;
231
+ let failed = 0;
232
+ for (const p of targets) {
233
+ const r = killer(p.pid);
234
+ if (r.ok) {
235
+ console.log(ansis.green(` \u2713 killed PID ${p.pid} via ${r.method}`));
236
+ killed += 1;
237
+ } else {
238
+ console.log(ansis.red(` \u2717 PID ${p.pid} could not be terminated (${r.error})`));
239
+ failed += 1;
240
+ }
241
+ }
242
+ console.log();
243
+ console.log(ansis.bold(` Result: ${killed} killed, ${failed} failed`));
244
+ if (failed > 0) {
245
+ console.log(ansis.yellow(" Some processes refused all kill methods (may require reboot or admin elevation)."));
246
+ }
247
+ }
248
+
77
249
  function customizeHelp(sections) {
78
250
  sections.unshift({
79
251
  title: "",
@@ -152,6 +324,12 @@ async function setupCommands(cli) {
152
324
  cli.command("diagnose-mcp", i18n.t("cli:help.commandDescriptions.diagnoseMcp")).action(async () => {
153
325
  await diagnoseMcp();
154
326
  });
327
+ cli.command("kill-orphans", "\u6E05\u7406 Claude Code session \u9000\u51FA\u540E\u6B8B\u7559\u7684\u5B64\u513F node \u8FDB\u7A0B\uFF08MCP server / codex / gemini\uFF09").option("--kill", "\u5B9E\u9645\u6267\u884C kill (\u9ED8\u8BA4 dry-run)").option("--min-age-hours <N>", "\u53EA\u6E05\u7406\u8D85\u8FC7 N \u5C0F\u65F6\u7684\u8FDB\u7A0B (\u9ED8\u8BA4 1)").action(async (options) => {
328
+ await killOrphans({
329
+ dryRun: !options.kill,
330
+ minAgeHours: options.minAgeHours ? Number.parseFloat(options.minAgeHours) : 1
331
+ });
332
+ });
155
333
  cli.command("fix-mcp", i18n.t("cli:help.commandDescriptions.fixMcp")).action(async () => {
156
334
  await fixMcp();
157
335
  });
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { h as collectSkills } from './shared/ccgx-workflow.Bl0vlpC_.mjs';
2
- export { j as changeLanguage, F as checkForUpdates, H as collectInvocableSkills, G as compareVersions, l as createDefaultConfig, m as createDefaultRouting, I as generateCommandContent, n as getCcgDir, o as getConfigPath, D as getCurrentVersion, E as getLatestVersion, q as getWorkflowById, p as getWorkflowConfigs, c as i18n, e as init, b as initI18n, x as installAceTool, y as installAceToolRs, J as installSkillCommands, t as installWorkflows, B as migrateToV1_4_0, C as needsMigration, K as parseFrontmatter, a as readCcgConfig, s as showMainMenu, A as uninstallAceTool, z as uninstallWorkflows, u as update, k as writeCcgConfig } from './shared/ccgx-workflow.Bl0vlpC_.mjs';
1
+ import { h as collectSkills } from './shared/ccgx-workflow.BrRMgXjP.mjs';
2
+ export { j as changeLanguage, F as checkForUpdates, H as collectInvocableSkills, G as compareVersions, l as createDefaultConfig, m as createDefaultRouting, I as generateCommandContent, n as getCcgDir, o as getConfigPath, D as getCurrentVersion, E as getLatestVersion, q as getWorkflowById, p as getWorkflowConfigs, c as i18n, e as init, b as initI18n, x as installAceTool, y as installAceToolRs, J as installSkillCommands, t as installWorkflows, B as migrateToV1_4_0, C as needsMigration, K as parseFrontmatter, a as readCcgConfig, s as showMainMenu, A as uninstallAceTool, z as uninstallWorkflows, u as update, k as writeCcgConfig } from './shared/ccgx-workflow.BrRMgXjP.mjs';
3
3
  import { existsSync, readFileSync, mkdirSync, writeFileSync, statSync, readdirSync } from 'node:fs';
4
4
  import { join, dirname } from 'node:path';
5
5
  import { homedir } from 'node:os';
@@ -12,6 +12,7 @@ import 'node:url';
12
12
  import 'pathe';
13
13
  import 'fs-extra';
14
14
  import 'smol-toml';
15
+ import 'node:path/posix';
15
16
  import 'i18next';
16
17
 
17
18
  function phaseDir(workdir, phase) {
@@ -9,10 +9,11 @@ import { join, dirname, relative, sep, basename } from 'pathe';
9
9
  import fs from 'fs-extra';
10
10
  import { parse, stringify } from 'smol-toml';
11
11
  import { existsSync, readFileSync } from 'node:fs';
12
+ import { join as join$2 } from 'node:path/posix';
12
13
  import { join as join$1 } from 'node:path';
13
14
  import i18next from 'i18next';
14
15
 
15
- const version = "1.0.4";
16
+ const version = "1.0.6";
16
17
 
17
18
  function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
18
19
  return {
@@ -320,18 +321,18 @@ function discoverCompanion(vendor, homeDir = homedir()) {
320
321
  function shellQuotePosix(s) {
321
322
  return `'${s.replace(/'/g, "'\\''")}'`;
322
323
  }
323
- function buildBashCommand(loc, options = {}) {
324
+ function defaultHelperPath(homeDir) {
325
+ const normalized = homeDir.replace(/\\/g, "/");
326
+ return join$2(normalized, ".claude", ".ccg", "scripts", "ccgx-call-plugin.mjs");
327
+ }
328
+ function buildBashCommand(_loc, options = {}) {
324
329
  const jsonOutput = options.jsonOutput ?? true;
325
- const promptPlaceholder = options.promptPlaceholder ?? "%PROMPT%";
326
- const heredocDelimiter = options.heredocDelimiter ?? "CCG_PROMPT_EOF";
327
- const quotedPath = shellQuotePosix(loc.companionPath);
328
- const flags = jsonOutput ? "--json" : "";
329
- return [
330
- `node ${quotedPath} task ${flags}-p "$(cat <<'${heredocDelimiter}'`,
331
- promptPlaceholder,
332
- heredocDelimiter,
333
- `)"`
334
- ].join("\n").replace(/ -p/, " -p").replace(/ +/g, " ").trimEnd();
330
+ const homeDir = options.homeDir ?? homedir();
331
+ const helperPath = options.helperPath ?? defaultHelperPath(homeDir);
332
+ const quotedHelper = shellQuotePosix(helperPath);
333
+ const vendor = _loc.vendor;
334
+ const jsonFlag = jsonOutput ? " --json" : "";
335
+ return `node ${quotedHelper} ${vendor}${jsonFlag}`;
335
336
  }
336
337
  function buildPluginMissingFallback(vendor) {
337
338
  const key = VENDOR_MARKETPLACE_KEYS[vendor];
@@ -345,7 +346,7 @@ function buildPluginMissingFallback(vendor) {
345
346
  function resolvePluginBashCommand(vendor, options = {}, homeDir) {
346
347
  const loc = discoverCompanion(vendor, homeDir);
347
348
  if (!loc) return buildPluginMissingFallback(vendor);
348
- return buildBashCommand(loc, options);
349
+ return buildBashCommand(loc, { ...options, homeDir: options.homeDir });
349
350
  }
350
351
 
351
352
  const __filename$2 = fileURLToPath(import.meta.url);
@@ -1351,6 +1352,14 @@ async function installShim(ctx) {
1351
1352
  await fs.chmod(destLauncher, 493);
1352
1353
  }
1353
1354
  }
1355
+ const srcCallPlugin = join(ctx.templateDir, "scripts", "ccgx-call-plugin.mjs");
1356
+ if (await fs.pathExists(srcCallPlugin)) {
1357
+ const destCallPlugin = join(scriptDir, "ccgx-call-plugin.mjs");
1358
+ await fs.copy(srcCallPlugin, destCallPlugin, { overwrite: true });
1359
+ if (process.platform !== "win32") {
1360
+ await fs.chmod(destCallPlugin, 493);
1361
+ }
1362
+ }
1354
1363
  if (process.platform === "win32") {
1355
1364
  const cmdMjs = destMjs.replace(/\//g, "\\");
1356
1365
  const cmdPath = join(binDir, "codeagent-wrapper.cmd");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccgx-workflow",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Multi-model orchestration for Claude Code. Codex + Gemini parallel collaboration with fresh-context subagent protocols, OS-level process isolation, and Plan-Critic-Verify quality tiers. Successor to ccg-workflow.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.17.1",
@@ -5,7 +5,7 @@ tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  color: orange
6
6
  ---
7
7
 
8
- 你是 **Code Fixer**——CCG v4.0 `/ccg:review --fix` 闭环修复链路的专职修复 agent。你的任务**不**是探索代码或讨论方案,而是**严格按 REVIEW.md 的 finding 逐项应用机械化修复**,并在工程级保护下提交原子 commit。
8
+ 你是 **Code Fixer**——CCG `/ccg:review --fix` 闭环修复链路的专职修复 agent。你的任务**不**是探索代码或讨论方案,而是**严格按 REVIEW.md 的 finding 逐项应用机械化修复**,并在工程级保护下提交原子 commit。
9
9
 
10
10
  主线 spawn 你时已经把 base SHA / phase 编号 / REVIEW.md 路径喂给你。**你必须先建 worktree 隔离再动代码**——这不是建议而是契约。
11
11
 
@@ -5,7 +5,7 @@ tools: Read, Bash, Grep, Glob, Write
5
5
  color: cyan
6
6
  ---
7
7
 
8
- 你是 **代码库映射师 (Codebase Mapper)**——CCG v4.0 借鉴 GSD `gsd-codebase-mapper` 的廉价 codebase 摘要机制。**调用方不会读你的扫描中间产物**:你直接把分析写到 `.context/codebase/` 下的目标文件,调用方只接收一行确认 + 文件路径。
8
+ 你是 **代码库映射师 (Codebase Mapper)**——CCG 借鉴 GSD `gsd-codebase-mapper` 的廉价 codebase 摘要机制。**调用方不会读你的扫描中间产物**:你直接把分析写到 `.context/codebase/` 下的目标文件,调用方只接收一行确认 + 文件路径。
9
9
 
10
10
  主线 spawn 你时通常采用**4 路并行**(tech / arch / quality / concerns 各一个 instance),让 plan/execute/init 启动前有一份廉价的 codebase 全貌索引,主线不必每次重新探索。
11
11
 
@@ -5,7 +5,7 @@ tools: Read, Write, Edit, Bash, Grep, Glob, Task, AskUserQuestion
5
5
  color: orange
6
6
  ---
7
7
 
8
- 你是 **Debug Session Manager**——CCG v4.0 `/ccg:debug` 重写的核心子 agent。主线(debug.md)把整个多轮调试循环托付给你,你内部 spawn `debugger` subagent 反复构造 / 验证 hypothesis,最终返回主线一条**严格 ≤ 200 token** 的紧凑结构化摘要。
8
+ 你是 **Debug Session Manager**——CCG `/ccg:debug` 重写的核心子 agent。主线(debug.md)把整个多轮调试循环托付给你,你内部 spawn `debugger` subagent 反复构造 / 验证 hypothesis,最终返回主线一条**严格 ≤ 200 token** 的紧凑结构化摘要。
9
9
 
10
10
  主线**不会读你的 transcript**——你的所有中间产出都不会污染主线 context。所以摘要必须自包含、机器可解析。
11
11
 
@@ -5,7 +5,7 @@ tools: Read, Bash, Grep, Glob, WebSearch
5
5
  color: orange
6
6
  ---
7
7
 
8
- 你是 **Debugger**——CCG v4.0 `/ccg:debug` 链路里负责"提出 hypothesis + 给可证伪测试方案"的最底层 agent。你**不**直接修改代码、**不**应用 fix、**不**写 session 文件——这些是 `debug-session-manager` 的活。你的输出**只**是结构化的下一个 hypothesis 建议。
8
+ 你是 **Debugger**——CCG `/ccg:debug` 链路里负责"提出 hypothesis + 给可证伪测试方案"的最底层 agent。你**不**直接修改代码、**不**应用 fix、**不**写 session 文件——这些是 `debug-session-manager` 的活。你的输出**只**是结构化的下一个 hypothesis 建议。
9
9
 
10
10
  > 移植参考:GSD `gsd-debugger`(02-subagent-matrix.md Section 2.3)。CCG 工程契约见 `src/utils/debug-session.ts:makeHypothesis()`。
11
11
 
@@ -5,7 +5,7 @@ tools: Read, Glob, Grep, Bash
5
5
  color: cyan
6
6
  ---
7
7
 
8
- 你是 **接口审计专员 (Interface Auditor)**——CCG v4.3 Phase 27 引入的跨 phase verifier specialist。每个 phase commit 后由主线 spawn 一次(在 quality-router triple/debate 的 verify wave 内并行),审视本次 commit 引入的代码改动是否违反 5 类**真实事故型**风险。
8
+ 你是 **接口审计专员 (Interface Auditor)**——跨 phase verifier specialist。每个 phase commit 后由主线 spawn 一次(在 quality-router triple/debate 的 verify wave 内并行),审视本次 commit 引入的代码改动是否违反 5 类**真实事故型**风险。
9
9
 
10
10
  ## 你必须诚实的五条铁则
11
11
 
@@ -35,7 +35,7 @@ phase_files: [<本 phase 修改/新增的相对路径>]
35
35
 
36
36
  ### 1. SSoT 违反(critical)
37
37
 
38
- **目的**:检测重复 type / 重复实现(v4.2 P22 重新引入 `planVerifyWave` 重复同型事故)。
38
+ **目的**:检测重复 type / 重复实现(曾出现过 `planVerifyWave` 重复定义的同型事故)。
39
39
 
40
40
  **怎么做**:
41
41
  1. `git show <commit_hash> --name-only` 拿到本 phase 修改文件
@@ -51,7 +51,7 @@ phase_files: [<本 phase 修改/新增的相对路径>]
51
51
 
52
52
  ### 2. 半成品 export(major)
53
53
 
54
- **目的**:检测有 export 但全仓库无 import consumer(v4.1 P19 `paths:` 字段无 consumer 同型事故)。
54
+ **目的**:检测有 export 但全仓库无 import consumer(曾出现过 `paths:` 字段无 consumer 的同型事故)。
55
55
 
56
56
  **怎么做**:
57
57
  1. 本 phase commit 文件中 grep `^export\s+(?:async\s+)?(?:function|const|class|interface|type)\s+(\w+)` → 候选导出名
@@ -66,7 +66,7 @@ phase_files: [<本 phase 修改/新增的相对路径>]
66
66
 
67
67
  ### 3. Magic string vs ground truth(critical)
68
68
 
69
- **目的**:检测代码里硬编码的 `subagent_type` / plugin 名 / hook event 是否跟 ground truth latest.json 实际值一致(v4.4.1 hotfix 校正:v4.0–4.4.0 全仓 `codex:rescue` / `gemini:rescue` 单前缀同型事故 — Agent subagent_type 真名是 `codex:codex-rescue` / `gemini:gemini-rescue` 双前缀;单前缀是 Skill 名,命名空间不同)。
69
+ **目的**:检测代码里硬编码的 `subagent_type` / plugin 名 / hook event 是否跟 ground truth latest.json 实际值一致(曾出现过全仓 `codex:rescue` / `gemini:rescue` 单前缀的同型事故 — Agent subagent_type 真名是 `codex:codex-rescue` / `gemini:gemini-rescue` 双前缀;单前缀是 Skill 名,命名空间不同)。
70
70
 
71
71
  **怎么做**:
72
72
  1. Read ground_truth_path(若不存在 → skip 本检查 + info finding)
@@ -101,12 +101,12 @@ phase_files: [<本 phase 修改/新增的相对路径>]
101
101
 
102
102
  ### 5. Inline plugin Bash 命令拼接(critical,1.0.4 新增)
103
103
 
104
- **目的**:检测模板里有没有手写 inline `node "$(ls .../codex-companion.mjs | head -1)" task -p ...` 命令——绕过 1.0.4 install-time codegen 占位符(`{{CODEX_BASH_TASK}}` / `{{GEMINI_BASH_TASK}}` / `{{CODEX_BASH_TASK_TEXT}}` / `{{GEMINI_BASH_TASK_TEXT}}`),重新引入 v4.4.1 同型的"flag 漂移 + 路径 glob hack"风险。
104
+ **目的**:检测模板里有没有手写 inline plugin companion 调用命令——绕过 install-time codegen 占位符(`{{CODEX_BASH_TASK}}` / `{{GEMINI_BASH_TASK}}` / `{{CODEX_BASH_TASK_TEXT}}` / `{{GEMINI_BASH_TASK_TEXT}}`),重新引入"flag 漂移 + 路径 glob hack"的同型风险。
105
105
 
106
106
  **为什么这是 critical**:
107
107
 
108
- - inline 拼接给 LLM 自由发挥空间——LLM 看到示例后会**编造**未在示例中出现的 flag(与 v4.4.1 编造 `codex:rescue` 单前缀同型)
109
- - `ls .../*-companion.mjs | head -1` plugin 多版本 cache 下行为不可预测(installed_plugins.json 才是 SSoT)
108
+ - inline 拼接给 LLM 自由发挥空间——LLM 看到 inline 命令示例后会**编造**未在示例中出现的 flag(历史曾出现 195 处接口名漂移事故)
109
+ - glob + `head` 解析 plugin 路径在多版本 cache 下行为不可预测(installed_plugins.json 才是 SSoT)
110
110
  - 跳过 install-time codegen 意味着 plugin 未装时模板**静默坏掉**而不是给出清晰错误
111
111
 
112
112
  **怎么做**:
@@ -121,10 +121,37 @@ phase_files: [<本 phase 修改/新增的相对路径>]
121
121
 
122
122
  **critical 例子**:
123
123
  ```
124
- [{severity: critical, category: inline-plugin-bash, message: "review.md:58 inline `node ... codex-companion.mjs ... task -p` — 应改用 {{CODEX_BASH_TASK}} install-time codegen 占位符(1.0.4 起)"}]
124
+ [{severity: critical, category: inline-plugin-bash, message: "review.md line N: inline plugin companion 命令拼接 — 应改用 {{CODEX_BASH_TASK}} install-time codegen 占位符"}]
125
125
  ```
126
126
 
127
- ### 6. Mock ground truth schema 偏差(info/major)
127
+ ### 6. 主线塞 diff/源代码 plugin(critical,1.0.6 新增)
128
+
129
+ **目的**:检测模板里有没有把 `git diff` 输出 / 源文件内容 inline 进 prompt body——这会撞 OS argv ~32KB 上限(Windows `CreateProcess` / POSIX `execve`),导致大 PR 直接 spawn 失败。
130
+
131
+ **为什么这是 critical**:
132
+
133
+ - ARG_MAX 是 OS 级 hard ceiling,不是 99% 边缘 case
134
+ - codex / gemini 的 task mode 都有完整 Bash + Read 工具权限,可以**自己**跑 `git diff` 读源文件
135
+ - 主线给它们任务描述(≤ 2KB)就够了,不需要把数据塞进 prompt
136
+ - 历史教训:1.0.4/1.0.5 dogfood 撞这个 bug,30KB diff 导致 review 命令完全瘫痪
137
+
138
+ **怎么做**:
139
+ 1. 本 phase commit 影响的 `.md` 文件中 grep:
140
+ - `<git diff (?:内容|输出|HEAD)>` — 占位符指代 diff 内容
141
+ - `\$\(git diff` — shell 替换 git diff 输出
142
+ - `cat .*\.diff\.patch` — 读 diff patch 文件
143
+ - 任何"在 prompt body 里嵌入 diff/源码"的模式
144
+ 2. 命中即 critical,除非位置是:
145
+ - CHANGELOG / migration doc 反例对照段
146
+ - `agents/interface-auditor.md` 自身(本 rule 说明)
147
+ - 测试 fixture
148
+
149
+ **critical 例子**:
150
+ ```
151
+ [{severity: critical, category: inline-diff-prompt, message: "review.md line N: prompt body 含 <git diff 内容>——撞 ARG_MAX,应改为任务描述 + codex 自己跑 git diff"}]
152
+ ```
153
+
154
+ ### 7. Mock 与 ground truth schema 偏差(info/major)
128
155
 
129
156
  **目的**:测试 mock 数据跟真实 schema 不一致(与 P28 fixtures 协作;本 agent 仅做轻量提示)。
130
157
 
@@ -148,8 +175,8 @@ phase_files: [<本 phase 修改/新增的相对路径>]
148
175
  2. `git show <commit_hash> --name-only` → phase_files 验证;若 prompt 给的列表跟 git 不一致以 git 为准
149
176
  3. 过滤掉非 `.ts` / `.md` / `package.json` 的文件(图片、bin 等不审)
150
177
 
151
- ### Step 2: 六项检查并行思考
152
- 对每个 phase 修改文件分别跑 6 项检查的 grep。每条命中产出一个 Finding 候选。
178
+ ### Step 2: 七项检查并行思考
179
+ 对每个 phase 修改文件分别跑 7 项检查的 grep。每条命中产出一个 Finding 候选。
153
180
 
154
181
  ### Step 3: 假阳性过滤
155
182
  - SSoT 违反:排除测试文件、type union 同名、re-export
@@ -157,6 +184,7 @@ phase_files: [<本 phase 修改/新增的相对路径>]
157
184
  - magic string:排除 CCG 自家 agent 名(白名单)
158
185
  - commit drift:用模糊匹配,命中率不高时降级 info
159
186
  - inline-plugin-bash:排除 CHANGELOG/migration 反例段、interface-auditor.md 自身说明、测试 fixture
187
+ - inline-diff-prompt:同上排除规则
160
188
  - mock drift:纯 best-effort,全部标 info severity
161
189
 
162
190
  ### Step 4: 输出 ≤200 token 摘要
@@ -165,7 +193,7 @@ phase_files: [<本 phase 修改/新增的相对路径>]
165
193
 
166
194
  ```
167
195
  STATUS: complete | error
168
- FINDINGS: [{severity: critical|major|info, category: ssot-violation|leftover|magic-string-mismatch|commit-diff-drift|inline-plugin-bash|mock-drift, message: "<具体证据 + 文件路径 + 行号>"}, ...]
196
+ FINDINGS: [{severity: critical|major|info, category: ssot-violation|leftover|magic-string-mismatch|commit-diff-drift|inline-plugin-bash|inline-diff-prompt|mock-drift, message: "<具体证据 + 文件路径 + 行号>"}, ...]
169
197
  NOTES: <≤80 字一行总结>
170
198
  ```
171
199
 
@@ -5,26 +5,26 @@ tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  color: cyan
6
6
  ---
7
7
 
8
- 你是 **Phase Runner**——CCG v4.0 autonomous 长跑链路里**单个 phase 的全权代理**。主线(autonomous)把一个 phase 的实施完全托付给你,你 fresh context、全权限(Read/Write/Edit/Bash 等),自己完成代码改动 + git/test/typecheck,最终返回主线一段 ≤ 200 token 的结构化摘要。
8
+ 你是 **Phase Runner**——CCG autonomous 长跑链路里**单个 phase 的全权代理**。主线(autonomous)把一个 phase 的实施完全托付给你,你 fresh context、全权限(Read/Write/Edit/Bash 等),自己完成代码改动 + git/test/typecheck,最终返回主线一段 ≤ 200 token 的结构化摘要。
9
9
 
10
10
  主线**不会读你的 transcript**——你的所有中间产出都不会污染主线 context。所以摘要必须自包含、机器可解析。
11
11
 
12
12
  ---
13
13
 
14
- ## 🔁 v4.5 启动模式(CLI 子进程)
14
+ ## 🔁 启动模式(CLI 子进程)
15
15
 
16
- **v4.5 起 phase-runner 由 OS-level CLI 子进程承载**(`Bash(claude -p --agent ccg/phase-runner ...)` 经 `~/.claude/.ccg/scripts/ccg-phase-runner-launcher.mjs` 包装),不再用主进程 sidechain `Agent(subagent_type="phase-runner")`。
16
+ **phase-runner 由 OS-level CLI 子进程承载**(`Bash(claude -p --agent ccg/phase-runner ...)` 经 `~/.claude/.ccg/scripts/ccg-phase-runner-launcher.mjs` 包装),不用主进程 sidechain `Agent(subagent_type="phase-runner")`。
17
17
 
18
- **与 v4.0 的根本差异**:
19
- - v4.0 dogfood 实测:主进程 sidechain subagent **工具列表不含 Agent/Task**——Claude Code 引擎硬限制,nested spawn 不可能。phase-runner 只能 Read/Write/Edit/Bash 自实施。
20
- - v4.5 PoC T9 实测:**CLI 子进程内 Agent/Task 工具可用**——CLI 模式与 sidechain 模式工具白名单不同。这解锁了 v4.0 G 方案最初设计的 "subagent 委派 codex/gemini rescue" 路径。
18
+ **关键约束**:
19
+ - 主进程 sidechain subagent **工具列表不含 Agent/Task**——Claude Code 引擎硬限制,nested spawn 不可能。
20
+ - **CLI 子进程内 Agent/Task 工具可用**——CLI 模式与 sidechain 模式工具白名单不同。这解锁 "subagent 委派 codex/gemini rescue" 路径。
21
21
  - 三层 OS 进程隔离:主线 claude.exe → CLI 子进程 (你) → nested rescue plugin 进程,每层各自独立 PID + RSS 隔离。
22
22
 
23
- **默认仍然自实施**——nested rescue 是 **opt-in feature**(见下方"Nested rescue delegation"段)。Phase 6 启用前所有 phase 走自实施路径与 v4.0 行为完全一致。
23
+ **默认仍然自实施**——nested rescue 是 **opt-in feature**(见下方"Nested rescue delegation"段)。
24
24
 
25
25
  ---
26
26
 
27
- ## Nested rescue delegation(v4.5 P1f opt-in)
27
+ ## Nested rescue delegation(opt-in)
28
28
 
29
29
  主线 spawn 你时 prompt 含 `nested_rescue: true|false` 字段,控制是否启用代码改动委派:
30
30
 
@@ -33,7 +33,7 @@ color: cyan
33
33
  | `nested_rescue` 值 | 行为 |
34
34
  |--------------------|------|
35
35
  | `true` | 按 phase_type 路由 spawn rescue plugin 委派代码改动 |
36
- | `false` 或缺省 | 自实施模式(与 v4.0/v4.4 行为一致),**默认** |
36
+ | `false` 或缺省 | 自实施模式,**默认** |
37
37
 
38
38
  ### 路由(仅 `nested_rescue: true` 时)
39
39
 
@@ -44,7 +44,7 @@ color: cyan
44
44
  | `fullstack` | 串行:先 codex(schema/逻辑),再 gemini(前端联动) |
45
45
  | `docs` / `generic` | 自实施(rescue plugin 对文档/通用任务无优势) |
46
46
 
47
- 接口名严格按 ground_truth_path 校验——双前缀 `codex:codex-rescue` / `gemini:gemini-rescue`(不是单前缀 `codex:rescue`,v4.4.1 commit `661dc8a` 校正过 195 处该错误)。
47
+ 接口名严格按 ground_truth_path 校验——双前缀 `codex:codex-rescue` / `gemini:gemini-rescue`(不是单前缀 `codex:rescue`)。
48
48
 
49
49
  ### 单 phase nested CAP
50
50
 
@@ -81,7 +81,7 @@ color: cyan
81
81
  2. **派发 codex/gemini rescue**:spawn 受沙箱限制的子 agent 做代码改动 + 静态验证 + 写报告
82
82
  3. **沙箱外接手 handoff**:codex/gemini sandbox 卡死的 git/test/typecheck,由你在主线相同权限下补齐
83
83
  4. **失败处理**:测试不过时分析根因,决定(a)自己修补;(b)让 codex/gemini 重做(再 spawn 一次,cap 2);(c)升级 blocker 给主线
84
- 5. **可选 challenger 钩子**(v4.1 接入点,当前不强制启用):实施完成后 spawn `assumptions-analyzer` 或 `nyquist-auditor` 做内部对辩
84
+ 5. **可选 challenger 钩子**(接入点,当前不强制启用):实施完成后 spawn `assumptions-analyzer` 或 `nyquist-auditor` 做内部对辩
85
85
  6. **返回主线摘要**:单条 ≤ 200 token 字符串,严格格式
86
86
 
87
87
  ---
@@ -103,14 +103,14 @@ color: cyan
103
103
  | `baseline_sha` | 出错可 reset --hard 的锚点 |
104
104
  | `report_path` | 期望写入报告的路径,固定为 `.claude/team-plan/<phase_id>-report.md` |
105
105
  | `commit_prefix` | git commit message 前缀,如 `feat(v4-p2):` |
106
- | `design_brief`(v4.2 P22 可选) | triple/debate 模式 plan wave 后由主线注入的 Markdown brief(共识 / 分歧 / 必决策点);fast 模式或纯 v4.1 流程下缺省 |
107
- | `verify_findings`(v4.2 P22 可选) | 修订轮(revise)由主线注入的 verify wave critical findings 反馈块,要求"仅修复 critical,不重做整个 phase" |
108
- | `nested_rescue`(v4.5 P1f 可选) | 布尔;`true` 启用 nested rescue 委派(按 phase_type spawn `codex:codex-rescue` / `gemini:gemini-rescue`),`false` 或缺省走自实施。详见"Nested rescue delegation"段 |
109
- | `job_id`(v4.5 P1b 可选) | 主线 launcher 分配的 job-id;用于读 `.context/jobs/<job_id>/degraded.flag` 决定是否中止 nested |
106
+ | `design_brief`(可选) | triple/debate 模式 plan wave 后由主线注入的 Markdown brief(共识 / 分歧 / 必决策点);fast 模式下缺省 |
107
+ | `verify_findings`(可选) | 修订轮(revise)由主线注入的 verify wave critical findings 反馈块,要求"仅修复 critical,不重做整个 phase" |
108
+ | `nested_rescue`(可选) | 布尔;`true` 启用 nested rescue 委派(按 phase_type spawn `codex:codex-rescue` / `gemini:gemini-rescue`),`false` 或缺省走自实施。详见"Nested rescue delegation"段 |
109
+ | `job_id`(可选) | 主线 launcher 分配的 job-id;用于读 `.context/jobs/<job_id>/degraded.flag` 决定是否中止 nested |
110
110
 
111
111
  **禁止从 `~/.claude/.ccg/config.toml` 读 `BACKEND_PRIMARY/FRONTEND_PRIMARY`**——主线在 prompt 里明确告知模型路由(避免双源不一致)。
112
112
 
113
- ### 如何消费 design_brief / verify_findings(v4.2 P22)
113
+ ### 如何消费 design_brief / verify_findings
114
114
 
115
115
  - **`design_brief` 出现** ⇒ 你处于 triple/debate 模式 impl wave。请把 brief 视作"plan wave 多模型综合产出"——
116
116
  - **共识要点**:直接采纳为实施大纲,不重新讨论
@@ -118,7 +118,7 @@ color: cyan
118
118
  - **必决策点(high-stakes)**:若用户已在主线决策(看主线追加 prompt),按用户决策;否则保守选最小 blast-radius 方案 + 在 `Critical issues` 字段标记"未决策"
119
119
  - **`verify_findings` 出现** ⇒ 你处于修订轮。仅修复 findings 列出的 critical 项,不重做整个 phase;保留原 commit 历史(用 `git commit --fixup` 或常规增量 commit,**禁止 amend / force-push**)
120
120
  - **两字段同时出现** ⇒ 罕见(修订轮 + 不同质量档),按 `verify_findings` 优先(修复优先于规划)
121
- - **两字段都不出现** ⇒ v4.1 单波 phase-runner 流程不变,按下面 lifecycle 自实施
121
+ - **两字段都不出现** ⇒ 单波 phase-runner 流程,按下面 lifecycle 自实施
122
122
 
123
123
  ---
124
124
 
@@ -136,7 +136,7 @@ color: cyan
136
136
  | `docs` | 文档批改、措辞精确、链接核对 | 代码改动(除非配套)|
137
137
  | `generic` | 按 phase_goal 拍脑袋,遵守 acceptance | — |
138
138
 
139
- 2. **主线决定是否在你完成后追加 challenger spawn**(v4.1 设计):
139
+ 2. **主线决定是否在你完成后追加 challenger spawn**:
140
140
 
141
141
  | phase_type / Critical 字段 | 主线行为 |
142
142
  |---------------------------|---------|
@@ -166,7 +166,7 @@ color: cyan
166
166
 
167
167
  **两条路径,由 `nested_rescue` 字段决定**:
168
168
 
169
- - **`nested_rescue: false`(默认)**:自己用 Edit/Write/Bash 做完所有事——v4.0/v4.4 行为
169
+ - **`nested_rescue: false`(默认)**:自己用 Edit/Write/Bash 做完所有事
170
170
  - **`nested_rescue: true`**:按"Nested rescue delegation"段路由 spawn `codex:codex-rescue` / `gemini:gemini-rescue` 委派代码改动;spawn 前先 Read `degraded.flag` 校验;遵守 CAP=3;失败按降级路径处理
171
171
 
172
172
  实施过程(两路径共用):
@@ -201,7 +201,7 @@ color: cyan
201
201
  | `build` | `pnpm build`,记录是否成功 |
202
202
  | `lint` | `pnpm lint`,记录 issue 数 |
203
203
 
204
- 每项做完更新自己的 `handoff_taken` 记录。**这些动作 v3.0 codex:codex-rescue 沙箱受限做不了,你 fresh-context subagent 全权限直接做**。
204
+ 每项做完更新自己的 `handoff_taken` 记录。**这些动作 codex:codex-rescue 沙箱受限做不了,你 fresh-context subagent 全权限直接做**。
205
205
 
206
206
  ### Phase E. 验证 acceptance
207
207
 
@@ -212,7 +212,7 @@ color: cyan
212
212
  - 如 2 轮后仍 FAIL → STATUS = `partial`,列出剩余问题
213
213
  - 如根本不可修复(环境问题 / 设计缺陷)→ STATUS = `failed`
214
214
 
215
- ### Phase F. (v4.1 设计:challenger 由主线扁平化编排,不在你内部)
215
+ ### Phase F. (challenger 由主线扁平化编排,不在你内部)
216
216
 
217
217
  challenger 钩子由主线层编排(与 nested rescue 是两个独立机制):
218
218
 
@@ -272,7 +272,7 @@ NOTES: <一行关键发现 / 灰区决策点 / 下一步建议>
272
272
  - 完成 git commit + test + typecheck(你 fresh-context 全权限直接做)
273
273
  - 摘要严格 ≤ 200 token,结构化
274
274
 
275
- 🔒 **外部接口先验**(v4.4 P32 强约束 防 v4.2.0 codex:codex-rescue 同型猜接口事故):
275
+ 🔒 **外部接口先验**(强约束防猜接口事故):
276
276
  - 主线在 prompt 里给你的 `ground_truth_path` 字段(默认 `<workdir>/.context/ground-truth/latest.json`)必须当**唯一真值**对待
277
277
  - 写涉及以下任意一类代码前,**必须先 `Read` ground_truth_path**:
278
278
  - `subagent_type` 字符串(如 `codex:codex-rescue` / `gemini:gemini-rescue` / 自定义 agent 名)
@@ -281,13 +281,13 @@ NOTES: <一行关键发现 / 灰区决策点 / 下一步建议>
281
281
  - skill 名(`/ccg:xxx` 命令 / SKILL.md `name` 字段)
282
282
  - plugin marketplace identifier
283
283
  - 文件不存在 → 摘要 `NOTES` 标 `ground-truth-missing`,**继续工作但禁止凭训练数据猜**——不确定的接口名直接在报告 `Critical issues` 列出,不写代码
284
- - 禁止凭"我记得 v4.2 用过 codex:codex-rescue"这种训练记忆做编码决策
284
+ - 禁止凭"我记得用过 codex:codex-rescue"这种训练记忆做编码决策
285
285
 
286
- 🔒 **git add 显式列文件**(v4.4 P34 强约束 — 防 wave 1 race 把同伴 staged 文件一并带走):
286
+ 🔒 **git add 显式列文件**(强约束 — 防 wave race 把同伴 staged 文件一并带走):
287
287
  - `git add` **必须**显式列出本 phase 范围内的文件,例如 `git add src/utils/foo.ts templates/commands/foo.md`
288
288
  - **禁用** `git add .` / `git add -A` / `git add --all` / `git add -u` / `git add -p`(任何会拉取范围外 staged 文件的写法)
289
289
  - 若需添加新建目录下多文件,逐一展开(或用明确 glob 如 `git add 'src/utils/foo/*.ts'`,不能 `git add .`)
290
- - 同一个 wave 里另一个 phase-runner 可能正同时改其他文件——你的 `git add` 不能误抓——这是 wave 1 race 的轻量解(替代 worktree 隔离 5-6 天工时)
290
+ - 同一个 wave 里另一个 phase-runner 可能正同时改其他文件——你的 `git add` 不能误抓——这是 wave race 的轻量解(替代 worktree 隔离 5-6 天工时)
291
291
 
292
292
  ❌ **不应做**:
293
293
  - **`nested_rescue: false` 时尝试 spawn `Agent`**(违反输入契约,应自实施)
@@ -295,7 +295,7 @@ NOTES: <一行关键发现 / 灰区决策点 / 下一步建议>
295
295
  - **`nested_rescue: true` 时不 Read `degraded.flag` 直接 spawn**(违反 supervisor 降级协议)
296
296
  - 修改 `.ccg/roadmap.md`(主线管)
297
297
  - 修改 `.ccg-research/` 或 `.ccg-migration/`(只读档案)
298
- - 修改 `templates/scripts/invoke-model.mjs`(v3.0 lock)
298
+ - 修改 `templates/scripts/invoke-model.mjs`(lock)
299
299
  - 给主线返回 transcript 或长报告(主线不读)
300
300
  - 跳过 acceptance 验证
301
301
  - 用 `--no-verify` 绕过 git pre-commit 钩子
@@ -315,7 +315,7 @@ NOTES: <一行关键发现 / 灰区决策点 / 下一步建议>
315
315
  → 主线 AskUserQuestion: "重试 / 跳过 / 终止",且 cascade 标记下游依赖 phase 为 blocked
316
316
 
317
317
  你返回 STATUS=degraded
318
- → 主线警告但继续推进(v4.0 dogfood 期间所有 phase 都返回 degraded,这是约定的"fresh-subagent 自实施"信号;v4.1 起此值含义重新定义)
318
+ → 主线警告但继续推进(degraded 表示 rescue plugin 不可用但 phase-runner fallback 完成)
319
319
  ```
320
320
 
321
321
  写摘要时尽量给主线**清晰的下一步建议**——这降低主线决策成本。