ccgx-workflow 2.3.0 → 2.3.1

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/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 { 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.BYuVglaM.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.DDYfdCuM.mjs';
5
5
  import { execSync } from 'node:child_process';
6
6
  import 'inquirer';
7
7
  import 'ora';
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { h as collectSkills, j as resolvePluginBashCommand } from './shared/ccgx-workflow.BYuVglaM.mjs';
2
- export { k as changeLanguage, G as checkForUpdates, I as collectInvocableSkills, H as compareVersions, m as createDefaultConfig, n as createDefaultRouting, J as generateCommandContent, o as getCcgDir, p as getConfigPath, E as getCurrentVersion, F as getLatestVersion, t as getWorkflowById, q as getWorkflowConfigs, c as i18n, e as init, b as initI18n, y as installAceTool, z as installAceToolRs, K as installSkillCommands, x as installWorkflows, C as migrateToV1_4_0, D as needsMigration, L as parseFrontmatter, a as readCcgConfig, s as showMainMenu, B as uninstallAceTool, A as uninstallWorkflows, u as update, l as writeCcgConfig } from './shared/ccgx-workflow.BYuVglaM.mjs';
1
+ import { h as collectSkills, j as resolvePluginBashCommand } from './shared/ccgx-workflow.DDYfdCuM.mjs';
2
+ export { k as changeLanguage, G as checkForUpdates, I as collectInvocableSkills, H as compareVersions, m as createDefaultConfig, n as createDefaultRouting, J as generateCommandContent, o as getCcgDir, p as getConfigPath, E as getCurrentVersion, F as getLatestVersion, t as getWorkflowById, q as getWorkflowConfigs, c as i18n, e as init, b as initI18n, y as installAceTool, z as installAceToolRs, K as installSkillCommands, x as installWorkflows, C as migrateToV1_4_0, D as needsMigration, L as parseFrontmatter, a as readCcgConfig, s as showMainMenu, B as uninstallAceTool, A as uninstallWorkflows, u as update, l as writeCcgConfig } from './shared/ccgx-workflow.DDYfdCuM.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';
@@ -13,7 +13,7 @@ import { join as join$2 } from 'node:path/posix';
13
13
  import { join as join$1 } from 'node:path';
14
14
  import i18next from 'i18next';
15
15
 
16
- const version = "2.3.0";
16
+ const version = "2.3.1";
17
17
 
18
18
  function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
19
19
  return {
@@ -1378,6 +1378,14 @@ async function installShim(ctx) {
1378
1378
  await fs.chmod(destCallPlugin, 493);
1379
1379
  }
1380
1380
  }
1381
+ const srcCheckPlugins = join(ctx.templateDir, "scripts", "check-plugins.cjs");
1382
+ if (await fs.pathExists(srcCheckPlugins)) {
1383
+ const destCheckPlugins = join(scriptDir, "check-plugins.cjs");
1384
+ await fs.copy(srcCheckPlugins, destCheckPlugins, { overwrite: true });
1385
+ if (process.platform !== "win32") {
1386
+ await fs.chmod(destCheckPlugins, 493);
1387
+ }
1388
+ }
1381
1389
  if (process.platform === "win32") {
1382
1390
  const cmdMjs = destMjs.replace(/\//g, "\\");
1383
1391
  const cmdPath = join(binDir, "codeagent-wrapper.cmd");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccgx-workflow",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
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",
@@ -42,7 +42,7 @@ CCG 把双模型并行通道从 `Bash(codeagent-wrapper)` **默认切换**为 pl
42
42
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork,含 P-1..P-21 + W1/W2/I1 patch;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
43
43
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback 到 Bash 调用,行为与 plugin 路径等价。
44
44
 
45
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。helper `src/utils/plugin-detection.ts`。
45
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
46
46
 
47
47
  ⚠️ Analyze 命令在主线 context 内,**允许** `Agent(...)`——与 subagent "禁止嵌套 spawn" 约束不冲突。
48
48
 
@@ -51,7 +51,7 @@ $ARGUMENTS
51
51
  1. **优先 plugin spawn**(默认):plugin 已装 → `Agent(subagent_type="codex:codex-rescue")`,session 复用通过 prompt 内 `--resume` flag 表达(subagent 映射为 codex `--resume-last`)。
52
52
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → Bash 调用,保留 `resume <SESSION_ID>` 显式会话管理。
53
53
 
54
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。
54
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` → 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
55
55
 
56
56
  **会话模型差异**:
57
57
  - **通道 A(plugin)**:session 是同一 Claude session 内的最近 codex/gemini thread(`--resume-last`)。同任务多 phase 顺序执行 OK;不支持跨任务跳点 resume by ID。
@@ -47,11 +47,10 @@ argument-hint: "<topic> [--max-rounds N] [--layer backend|frontend|fullstack]"
47
47
 
48
48
  1. 读 `$ARGUMENTS`,第一个非 flag token 即 topic(用引号包裹整段任务描述)
49
49
  2. 解析 `--max-rounds N` / `--layer X`
50
- 3. **检测 plugin 可用性(纯目录探测,禁止运行时探活)**:
51
- - 用 `Bash` 跑 `ls ~/.claude/plugins/ 2>/dev/null` `codex@*` / `gemini@*` 前缀子目录
52
- - 子目录内须含 `SKILL.md` / `plugin.json` / `package.json` / `manifest.json` 任一 marker `installed: true`
50
+ 3. **检测 plugin 可用性(解析 installed_plugins.json,禁止运行时探活)**:
51
+ - 用 `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `~/.claude/plugins/installed_plugins.json` 注册表)
52
+ - 返回 JSON `{"codex":"<ver>"|null,"gemini":"<ver>"|null}` + exit code(`0` = plugin 都在;非 `0` = 至少一个缺)→ 各自标 `installed: true/false`
53
53
  - ⛔ **严禁**调用 `/gemini:status` / `/codex:status` / 任何 broker / runtime / health 探活——broker 是**懒启动**的,启动后才有;当前 `brokerRunning: false` 不代表 plugin 不可用
54
- - 等价 helper:`detectPluginAvailability()`(`src/utils/plugin-detection.ts:156`)
55
54
  - 任一 plugin 真未装 → 该模型走 general-purpose 降级路径
56
55
  4. 调用 helper:`debateStateMachine(topic, { maxRounds, layer, pluginsAvailable })` 得到 `DebateRoundPlan[]`
57
56
 
@@ -27,9 +27,7 @@ CCG 把 6 核心命令的"双模型并行"通道从 `Bash(codeagent-wrapper)` **
27
27
  1. **优先 plugin spawn 路径**(默认):用户已装 `codex@openai-codex` 和 gemini plugin(推荐 `gemini@gemini-ccgx` fork,已含全部 patch;或上游 `gemini@google-gemini` 配 repatch)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行 spawn,主线只接 plugin 自家 ≤200 token 摘要。
28
28
  2. **降级 codeagent-wrapper 路径**(BC fallback):plugin 未装 → fallback 到 `Bash(~/.claude/bin/codeagent-wrapper ...)`,行为与 plugin 路径等价。
29
29
 
30
- **判断方法**:preflight `Bash` 跑 `ls ~/.claude/plugins/ 2>/dev/null | grep -E '^(codex|gemini)@'`;两个 plugin 独立判定。
31
-
32
- **单一真相源**:`src/utils/plugin-detection.ts`(导出 `detectPlugin` / `detectPluginAvailability` / `bothPluginsInstalled`)。
30
+ **判断方法**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。返回 JSON `{"codex":"<ver>"|null,"gemini":"<ver>"|null}`,两个 plugin 独立判定,可 mix-and-match(仅 codex 装了 → backend 走 plugin、frontend 走 codeagent)。exit `0` = 两 plugin 都在;非 `0` = 至少一个缺。
33
31
 
34
32
  ⚠️ Execute 命令在主线 context 内,**允许**调 `Agent(...)`——与 subagent "引擎层禁止嵌套 spawn" 约束不冲突。
35
33
 
@@ -47,7 +47,7 @@ CCG 把双模型并行通道从 `Bash(codeagent-wrapper)` **默认切换**为 pl
47
47
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork,含 P-1..P-21 + W1/W2/I1 patch;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
48
48
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback 到 Bash 调用,行为与 plugin 路径等价。
49
49
 
50
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。helper `src/utils/plugin-detection.ts`。
50
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
51
51
 
52
52
  ⚠️ Optimize 命令在主线 context 内,**允许** `Agent(...)`——与 subagent "禁止嵌套 spawn" 约束不冲突。
53
53
 
@@ -57,9 +57,7 @@ CCG 把 6 核心命令的"双模型并行"通道从 `Bash(codeagent-wrapper)` **
57
57
  1. **优先 plugin spawn 路径**(默认):用户已装 `codex@openai-codex` 和 gemini plugin(推荐 `gemini@gemini-ccgx` fork,已含全部 patch;或上游 `gemini@google-gemini` 配 repatch)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行 spawn,主线只接 plugin 自家 ≤200 token 摘要协议(`STATUS: ... / FINDINGS: ... / NOTES: ...`)。
58
58
  2. **降级 codeagent-wrapper 路径**(BC fallback):plugin 未装 → fallback 到 `Bash(~/.claude/bin/codeagent-wrapper --backend ... resume ... <<'EOF' ... EOF)`,与 plugin 路径行为等价。
59
59
 
60
- **判断方法**:preflight `Bash` 跑 `ls ~/.claude/plugins/ 2>/dev/null | grep -E '^codex@'` `... | grep -E '^gemini@'` 各一次。匹配到对应行 → plugin 已装。两个 plugin 独立判定,可分别 mix-and-match(仅 codex plugin 装了 → backend 走 plugin、frontend 走 codeagent)。
61
-
62
- **单一真相源**:plugin 检测逻辑 helper 见 `src/utils/plugin-detection.ts`(导出 `detectPlugin` / `detectPluginAvailability` / `bothPluginsInstalled`)。命令模板把判定结果渲染到执行计划,`Agent(...)` 调用与 `Bash(...)` 调用的具体语法见下面"多模型调用规范"段。
60
+ **判断方法**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。返回 JSON `{"codex":"<ver>"|null,"gemini":"<ver>"|null}`,两个 plugin 独立判定,可分别 mix-and-match(仅 codex plugin 装了 → backend 走 plugin、frontend 走 codeagent)。exit `0` = 两 plugin 都在;非 `0` = 至少一个缺。`Agent(...)` 调用与 `Bash(...)` 调用的具体语法见下面"多模型调用规范"段。
63
61
 
64
62
  **为什么默认 plugin**:nested-spawn 测试证明 plugin advisor 摘要协议(≤200 token)压制了 codeagent stdout 全文回灌主线的痛点,主线 context 增量从 +5%/调用 降到 +1.5%/调用。详见 `.ccg-research/07-multimodel-collaboration-rethink.md`。
65
63
 
@@ -21,7 +21,7 @@ argument-hint: "[代码或描述] [--adversarial] [--fix [--all] [--auto]] [--ro
21
21
 
22
22
  双模型并行审查,交叉验证综合反馈。无参数时自动审查当前 git 变更。
23
23
 
24
- **双模型并行通道**:默认走 plugin spawn —— 装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork,含 P-1..P-21 + W1/W2/I1 patch;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线只接 ≤200 token 摘要;plugin 未装 → fallback 到 codeagent-wrapper 路径(BC fallback)。preflight `Bash` 跑 `ls ~/.claude/plugins/` 检测,helper `src/utils/plugin-detection.ts`。
24
+ **双模型并行通道**:默认走 plugin spawn —— 装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork,含 P-1..P-21 + W1/W2/I1 patch;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线只接 ≤200 token 摘要;plugin 未装 → fallback 到 codeagent-wrapper 路径(BC fallback)。preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`,exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` = 两 plugin 都在)。
25
25
 
26
26
  `--adversarial` 模式下额外触发第三层"敌对视角"审查,由官方 codex plugin 的 `Agent(codex:codex-rescue)` 在 fresh context 中专门挑前两轮意见的漏洞,适合极重要 PR / 安全敏感变更。需用户已装 `codex@openai-codex` plugin,否则降级为双模型审查。
27
27
 
@@ -124,7 +124,7 @@ The diff will be reviewed before apply; do not assume it's been applied.
124
124
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
125
125
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback Bash 调用,**保留 Step 4 session resume** 以维持会话上下文。
126
126
 
127
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。
127
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` → 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
128
128
 
129
129
  ⚠️ spec-impl 命令在主线 context 内,**允许** `Agent(...)`——与 subagent "禁止嵌套 spawn" 约束不冲突。
130
130
  ⚠️ **plugin 路径无 session resume 能力**:通道 A 不接 Step 4 的 SESSION_ID,review 任务作为独立无状态分析跑(review 是 read-only 审查,无需会话连续性)。
@@ -32,7 +32,7 @@ description: '多模型分析 → 消除歧义 → 零决策可执行计划'
32
32
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
33
33
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback Bash 调用,行为与 plugin 路径等价。
34
34
 
35
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。
35
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` → 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
36
36
 
37
37
  ⚠️ spec-plan 命令在主线 context 内,**允许** `Agent(...)`——与 subagent "禁止嵌套 spawn" 约束不冲突。
38
38
 
@@ -57,7 +57,7 @@ description: '需求 → 约束集(并行探索 + OPSX 提案)'
57
57
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork,含 P-1..P-21 + W1/W2/I1 patch;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
58
58
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback Bash 调用,行为与 plugin 路径等价。
59
59
 
60
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。
60
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` → 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
61
61
 
62
62
  ⚠️ spec-research 命令在主线 context 内,**允许** `Agent(...)`——与 subagent "禁止嵌套 spawn" 约束不冲突。
63
63
 
@@ -33,7 +33,7 @@ description: '双模型交叉审查(独立工具,随时可用)'
33
33
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + gemini plugin(推荐 `gemini@gemini-ccgx` fork;或上游 `gemini@google-gemini` 配 repatch 脚本)→ 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
34
34
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback Bash 调用,行为与 plugin 路径等价。
35
35
 
36
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。
36
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` → 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
37
37
 
38
38
  ⚠️ spec-review 命令在主线 context 内,**允许** `Agent(...)`——与 subagent "禁止嵌套 spawn" 约束不冲突。
39
39
 
@@ -164,7 +164,7 @@ Phase 8: INTEGRATION → Lead 全量验证 + 报告 + 清理
164
164
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + gemini plugin → 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
165
165
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback Bash 调用,行为与 plugin 路径等价。
166
166
 
167
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。
167
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` → 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
168
168
 
169
169
  - **CRITICAL**: 必须在一条消息中同时发起两个并行调用。
170
170
 
@@ -47,7 +47,7 @@ CCG 把双模型并行通道从 `Bash(codeagent-wrapper)` **默认切换**为 pl
47
47
  1. **优先 plugin spawn**(默认):装了 `codex@openai-codex` + `gemini@google-gemini` plugin → 用 `Agent(subagent_type="codex:codex-rescue")` + `Agent(subagent_type="gemini:gemini-rescue")` 并行,主线接 ≤200 token 摘要。
48
48
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → fallback 到 Bash 调用,行为与 plugin 路径等价。
49
49
 
50
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。helper `src/utils/plugin-detection.ts`。
50
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
51
51
 
52
52
  ⚠️ Test 命令在主线 context 内,**允许** `Agent(...)`——与 subagent "禁止嵌套 spawn" 约束不冲突。
53
53
 
@@ -44,7 +44,7 @@ subagent_freshness: required
44
44
  1. **优先 plugin spawn**(默认):plugin 已装 → `Agent(subagent_type="<codex:codex-rescue|gemini:gemini-rescue>")`。session 复用通过 prompt 内 `--resume` flag 表达(subagent 映射为 codex/gemini `--resume-last`,**注意是 last,不是 by-id**)。
45
45
  2. **降级 codeagent-wrapper**(BC fallback):plugin 未装 → Bash 调用,保留 `resume <SESSION_ID>` 显式会话管理。
46
46
 
47
- **判定**:preflight `Bash` 跑 `ls ~/.claude/plugins/` 看有无 `codex@*` / `gemini@*` 子目录。
47
+ **判定**:preflight `Bash` 跑 `node ~/.claude/.ccg/scripts/check-plugins.cjs`(解析 Claude Code 权威 `installed_plugins.json`)。exit `0` + stdout `{"codex":"<ver>","gemini":"<ver>"}` → 通道 A(plugin 默认);非 `0` → 通道 B(wrapper BC fallback)。
48
48
 
49
49
  ---
50
50
 
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ // CCG plugin detection helper (v2.3.1+)
3
+ //
4
+ // Reads Claude Code's authoritative plugin registry at
5
+ // ~/.claude/plugins/installed_plugins.json and reports whether the
6
+ // codex and gemini plugins required by ccgx Channel A (plugin spawn)
7
+ // are registered.
8
+ //
9
+ // Exit codes:
10
+ // 0 = both plugins ok (use Channel A)
11
+ // 1 = at least one missing (use Channel B / wrapper BC fallback)
12
+ // 2 = registry missing or unparsable (use Channel B)
13
+ //
14
+ // stdout (single line JSON):
15
+ // {"codex": "<version>"|null, "gemini": "<version>"|null, "error"?: "<msg>"}
16
+
17
+ const fs = require('fs');
18
+ const os = require('os');
19
+ const path = require('path');
20
+
21
+ const registryPath = path.join(os.homedir(), '.claude', 'plugins', 'installed_plugins.json');
22
+
23
+ function emit(payload, exitCode) {
24
+ process.stdout.write(JSON.stringify(payload) + '\n');
25
+ process.exit(exitCode);
26
+ }
27
+
28
+ try {
29
+ if (!fs.existsSync(registryPath)) {
30
+ emit({ codex: null, gemini: null, error: 'registry-missing' }, 2);
31
+ }
32
+
33
+ const raw = fs.readFileSync(registryPath, 'utf8');
34
+ const data = JSON.parse(raw);
35
+ const plugins = (data && data.plugins) || {};
36
+
37
+ const codexKey = Object.keys(plugins).find((k) => k.startsWith('codex@'));
38
+ const geminiKey = Object.keys(plugins).find((k) => k.startsWith('gemini@'));
39
+
40
+ const codexEntry = codexKey ? plugins[codexKey] : null;
41
+ const geminiEntry = geminiKey ? plugins[geminiKey] : null;
42
+
43
+ const codex = Array.isArray(codexEntry) && codexEntry[0] ? (codexEntry[0].version || 'unknown') : null;
44
+ const gemini = Array.isArray(geminiEntry) && geminiEntry[0] ? (geminiEntry[0].version || 'unknown') : null;
45
+
46
+ emit({ codex, gemini }, codex && gemini ? 0 : 1);
47
+ } catch (e) {
48
+ emit({ codex: null, gemini: null, error: String(e && e.message || e) }, 2);
49
+ }