ccg-workflow 1.7.85 → 1.7.87

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
@@ -354,4 +354,4 @@ MIT
354
354
 
355
355
  ---
356
356
 
357
- v1.7.85 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
357
+ v1.7.86 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
package/README.zh-CN.md CHANGED
@@ -354,4 +354,4 @@ MIT
354
354
 
355
355
  ---
356
356
 
357
- v1.7.82 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [参与贡献](./CONTRIBUTING.md)
357
+ v1.7.86 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [参与贡献](./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.B9Mj76CP.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.CJXxHH9w.mjs';
5
5
  import 'inquirer';
6
6
  import 'node:child_process';
7
7
  import 'node:util';
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.B9Mj76CP.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.CJXxHH9w.mjs';
2
2
  import 'ansis';
3
3
  import 'inquirer';
4
4
  import 'node:child_process';
@@ -10,7 +10,7 @@ import { parse, stringify } from 'smol-toml';
10
10
  import i18next from 'i18next';
11
11
  import ora from 'ora';
12
12
 
13
- const version = "1.7.85";
13
+ const version = "1.7.87";
14
14
 
15
15
  function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
16
16
  return {
@@ -91,12 +91,23 @@ const __filename$2 = fileURLToPath(import.meta.url);
91
91
  const __dirname$2 = dirname(__filename$2);
92
92
  function findPackageRoot$1(startDir) {
93
93
  let dir = startDir;
94
- for (let i = 0; i < 5; i++) {
94
+ for (let i = 0; i < 10; i++) {
95
95
  if (fs.existsSync(join(dir, "package.json"))) {
96
- return dir;
96
+ if (fs.existsSync(join(dir, "templates"))) {
97
+ return dir;
98
+ }
97
99
  }
98
- dir = dirname(dir);
100
+ const parent = dirname(dir);
101
+ if (parent === dir) break;
102
+ dir = parent;
99
103
  }
104
+ console.error(
105
+ `[CCG] \u26A0 PACKAGE_ROOT resolution failed: could not find package.json with templates/ directory.
106
+ Start dir: ${startDir}
107
+ Last checked: ${dir}
108
+ This will cause commands/skills/prompts to not be installed.
109
+ Please report this issue at: https://github.com/fengshao1227/ccg-workflow/issues`
110
+ );
100
111
  return startDir;
101
112
  }
102
113
  const PACKAGE_ROOT$1 = findPackageRoot$1(__dirname$2);
@@ -682,7 +693,10 @@ async function downloadBinaryFromRelease(binaryName, destPath) {
682
693
  }
683
694
  async function copyMdTemplates(ctx, srcDir, destDir, options = {}) {
684
695
  const installed = [];
685
- if (!await fs.pathExists(srcDir)) return installed;
696
+ if (!await fs.pathExists(srcDir)) {
697
+ console.error(`[CCG] Template source directory not found: ${srcDir}`);
698
+ return installed;
699
+ }
686
700
  await fs.ensureDir(destDir);
687
701
  const files = await fs.readdir(srcDir);
688
702
  for (const file of files) {
@@ -755,7 +769,10 @@ async function installAgentFiles(ctx) {
755
769
  async function installPromptFiles(ctx) {
756
770
  const promptsTemplateDir = join(ctx.templateDir, "prompts");
757
771
  const promptsDir = join(ctx.installDir, ".ccg", "prompts");
758
- if (!await fs.pathExists(promptsTemplateDir)) return;
772
+ if (!await fs.pathExists(promptsTemplateDir)) {
773
+ ctx.result.errors.push(`Prompts template directory not found: ${promptsTemplateDir}`);
774
+ return;
775
+ }
759
776
  for (const model of ["codex", "gemini", "claude"]) {
760
777
  try {
761
778
  const installed = await copyMdTemplates(
@@ -783,7 +800,11 @@ async function collectSkillNames(dir, depth = 0) {
783
800
  names.push(basename(dir));
784
801
  }
785
802
  }
786
- } catch {
803
+ } catch (error) {
804
+ const code = error.code;
805
+ if (code !== "ENOENT") {
806
+ console.error(`[CCG] Failed to read skills directory ${dir}: ${code || error}`);
807
+ }
787
808
  }
788
809
  return names;
789
810
  }
@@ -797,7 +818,10 @@ async function removeDirCollectMdNames(dir) {
797
818
  async function installSkillFiles(ctx) {
798
819
  const skillsTemplateDir = join(ctx.templateDir, "skills");
799
820
  const skillsDestDir = join(ctx.installDir, "skills", "ccg");
800
- if (!await fs.pathExists(skillsTemplateDir)) return;
821
+ if (!await fs.pathExists(skillsTemplateDir)) {
822
+ ctx.result.errors.push(`Skills template directory not found: ${skillsTemplateDir}`);
823
+ return;
824
+ }
801
825
  try {
802
826
  const oldSkillsRoot = join(ctx.installDir, "skills");
803
827
  const ccgLegacyItems = ["tools", "orchestration", "SKILL.md", "run_skill.js"];
@@ -808,12 +832,16 @@ async function installSkillFiles(ctx) {
808
832
  const oldPath = join(oldSkillsRoot, item);
809
833
  const newPath = join(skillsDestDir, item);
810
834
  if (await fs.pathExists(oldPath)) {
811
- await fs.move(oldPath, newPath, { overwrite: true });
835
+ try {
836
+ await fs.move(oldPath, newPath, { overwrite: true });
837
+ } catch (moveErr) {
838
+ ctx.result.errors.push(`Skills migration: failed to move ${item}: ${moveErr}`);
839
+ }
812
840
  }
813
841
  }
814
842
  }
815
843
  await fs.copy(skillsTemplateDir, skillsDestDir, {
816
- overwrite: ctx.force,
844
+ overwrite: true,
817
845
  errorOnExist: false
818
846
  });
819
847
  const replacePathsInDir = async (dir) => {
@@ -832,7 +860,13 @@ async function installSkillFiles(ctx) {
832
860
  }
833
861
  };
834
862
  await replacePathsInDir(skillsDestDir);
835
- ctx.result.installedSkills = (await collectSkillNames(skillsDestDir)).length;
863
+ const installedSkills = await collectSkillNames(skillsDestDir);
864
+ ctx.result.installedSkills = installedSkills.length;
865
+ if (installedSkills.length === 0) {
866
+ ctx.result.errors.push(
867
+ `Skills copy completed but no SKILL.md found in ${skillsDestDir}. Possible cause: file locking (antivirus), permission denied, or path too long. Try running as administrator or disabling antivirus real-time scanning temporarily.`
868
+ );
869
+ }
836
870
  } catch (error) {
837
871
  ctx.result.errors.push(`Failed to install skills: ${error}`);
838
872
  ctx.result.success = false;
@@ -893,7 +927,8 @@ function showBinaryDownloadWarning(binDir) {
893
927
  console.log(ansis.gray(` \u2192 \u627E\u5230 ${ansis.white(binaryFileName)} \u5E76\u4E0B\u8F7D`));
894
928
  console.log();
895
929
  console.log(ansis.white(` 2. \u653E\u5230 / Place at:`));
896
- console.log(ansis.cyan(` ${binDir}/${destFileName}`));
930
+ const displayPath = process.platform === "win32" ? `${binDir.replace(/\//g, "\\")}\\${destFileName}` : `${binDir}/${destFileName}`;
931
+ console.log(ansis.cyan(` ${displayPath}`));
897
932
  console.log();
898
933
  if (process.platform !== "win32") {
899
934
  console.log(ansis.white(` 3. \u52A0\u6743\u9650 / Make executable:`));
@@ -965,6 +1000,12 @@ async function installWorkflows(workflowIds, installDir, force = false, config)
965
1000
  configPath: ""
966
1001
  }
967
1002
  };
1003
+ if (!await fs.pathExists(ctx.templateDir)) {
1004
+ const errorMsg = `Template directory not found: ${ctx.templateDir} (PACKAGE_ROOT=${PACKAGE_ROOT$1}). This usually means the npm package is incomplete or the cache is corrupted. Try: npm cache clean --force && npx ccg-workflow@latest`;
1005
+ ctx.result.errors.push(errorMsg);
1006
+ ctx.result.success = false;
1007
+ return ctx.result;
1008
+ }
968
1009
  await fs.ensureDir(join(installDir, "commands", "ccg"));
969
1010
  await fs.ensureDir(join(installDir, ".ccg"));
970
1011
  await fs.ensureDir(join(installDir, ".ccg", "prompts"));
@@ -974,6 +1015,12 @@ async function installWorkflows(workflowIds, installDir, force = false, config)
974
1015
  await installSkillFiles(ctx);
975
1016
  await installRuleFiles(ctx);
976
1017
  await installBinaryFile(ctx);
1018
+ if (ctx.result.installedCommands.length === 0 && ctx.result.errors.length === 0) {
1019
+ ctx.result.errors.push(
1020
+ `No commands were installed (expected ${workflowIds.length}). Template dir: ${ctx.templateDir}. This may indicate a corrupted package or file permission issue.`
1021
+ );
1022
+ ctx.result.success = false;
1023
+ }
977
1024
  ctx.result.configPath = join(installDir, "commands", "ccg");
978
1025
  return ctx.result;
979
1026
  }
@@ -3126,10 +3173,23 @@ async function init(options = {}) {
3126
3173
  }
3127
3174
  if (result.errors.length > 0) {
3128
3175
  console.log();
3129
- console.log(ansis.red(` \u26A0 ${i18n.t("init:installationErrors")}`));
3176
+ if (!result.success) {
3177
+ console.log(ansis.red.bold(` \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557`));
3178
+ console.log(ansis.red.bold(` \u2551 \u26A0 \u5B89\u88C5\u51FA\u73B0\u9519\u8BEF / Installation errors detected \u2551`));
3179
+ console.log(ansis.red.bold(` \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D`));
3180
+ } else {
3181
+ console.log(ansis.yellow(` \u26A0 ${i18n.t("init:installationErrors")}`));
3182
+ }
3130
3183
  result.errors.forEach((error) => {
3131
3184
  console.log(` ${ansis.red("\u2717")} ${error}`);
3132
3185
  });
3186
+ if (!result.success) {
3187
+ console.log();
3188
+ console.log(ansis.yellow(` \u5C1D\u8BD5\u4FEE\u590D / Try to fix:`));
3189
+ console.log(ansis.cyan(` npx ccg-workflow@latest init --force`));
3190
+ console.log(ansis.gray(` \u5982\u4ECD\u5931\u8D25\uFF0C\u8BF7\u63D0\u4EA4 issue \u5E76\u9644\u4E0A\u4EE5\u4E0A\u9519\u8BEF\u4FE1\u606F`));
3191
+ console.log(ansis.gray(` If still failing, report an issue with the errors above`));
3192
+ }
3133
3193
  }
3134
3194
  if (result.binInstalled && result.binPath) {
3135
3195
  console.log();
@@ -3384,7 +3444,6 @@ async function performUpdate(fromVersion, toVersion, isNewVersion) {
3384
3444
  } catch {
3385
3445
  const npxCachePath = join(homedir(), ".npm", "_npx");
3386
3446
  try {
3387
- const fs = await import('fs-extra');
3388
3447
  await fs.remove(npxCachePath);
3389
3448
  } catch {
3390
3449
  }
@@ -3424,22 +3483,43 @@ async function performUpdate(fromVersion, toVersion, isNewVersion) {
3424
3483
  console.log();
3425
3484
  }
3426
3485
  }
3427
- spinner = ora(i18n.t("update:removingOld")).start();
3428
3486
  const installDir = join(homedir(), ".claude");
3487
+ const BACKUP_SUFFIX = ".ccg-update-bak";
3488
+ const backupTargets = [
3489
+ join(installDir, "commands", "ccg"),
3490
+ join(installDir, "agents", "ccg"),
3491
+ join(installDir, "skills", "ccg")
3492
+ ];
3493
+ spinner = ora(i18n.t("update:removingOld")).start();
3494
+ const backedUp = [];
3429
3495
  try {
3430
- const uninstallResult = await uninstallWorkflows(installDir, { preserveBinary: true });
3431
- if (uninstallResult.success) {
3432
- spinner.succeed(i18n.t("update:oldRemoved"));
3433
- } else {
3434
- spinner.warn(i18n.t("update:partialRemoveFailed"));
3435
- for (const error of uninstallResult.errors) {
3436
- console.log(ansis.yellow(` \u2022 ${error}`));
3496
+ for (const dir of backupTargets) {
3497
+ if (await fs.pathExists(dir)) {
3498
+ const backupPath = dir + BACKUP_SUFFIX;
3499
+ if (await fs.pathExists(backupPath)) {
3500
+ await fs.remove(backupPath);
3501
+ }
3502
+ await fs.move(dir, backupPath);
3503
+ backedUp.push(dir);
3437
3504
  }
3438
3505
  }
3506
+ spinner.succeed(i18n.t("update:oldRemoved"));
3439
3507
  } catch (error) {
3440
- spinner.warn(i18n.t("update:removeFailed", { error: String(error) }));
3508
+ spinner.warn(`Backup failed: ${error}`);
3509
+ for (const dir of backedUp) {
3510
+ const backupPath = dir + BACKUP_SUFFIX;
3511
+ try {
3512
+ if (await fs.pathExists(backupPath)) {
3513
+ await fs.move(backupPath, dir);
3514
+ }
3515
+ } catch {
3516
+ }
3517
+ }
3518
+ console.log(ansis.yellow(" \u65E7\u7248\u672C\u6587\u4EF6\u5DF2\u4FDD\u7559 / Old files preserved"));
3519
+ return;
3441
3520
  }
3442
3521
  spinner = ora(i18n.t("update:installingNew")).start();
3522
+ let installSuccess = false;
3443
3523
  try {
3444
3524
  await execAsync$1(`npx --yes ccg-workflow@latest init --force --skip-mcp --skip-prompt`, {
3445
3525
  timeout: 3e5,
@@ -3449,21 +3529,59 @@ async function performUpdate(fromVersion, toVersion, isNewVersion) {
3449
3529
  CCG_UPDATE_MODE: "true"
3450
3530
  }
3451
3531
  });
3452
- spinner.succeed(i18n.t("update:installDone"));
3453
- const config = await readCcgConfig();
3454
- if (config?.workflows?.installed) {
3455
- console.log();
3456
- console.log(ansis.cyan(i18n.t("update:installed", { count: config.workflows.installed.length })));
3457
- for (const cmd of config.workflows.installed) {
3458
- console.log(` ${ansis.gray("\u2022")} /ccg:${cmd}`);
3532
+ const commandsDir = join(installDir, "commands", "ccg");
3533
+ const hasCommands = await fs.pathExists(commandsDir) && (await fs.readdir(commandsDir)).some((f) => f.endsWith(".md"));
3534
+ if (hasCommands) {
3535
+ installSuccess = true;
3536
+ spinner.succeed(i18n.t("update:installDone"));
3537
+ const config = await readCcgConfig();
3538
+ if (config?.workflows?.installed) {
3539
+ console.log();
3540
+ console.log(ansis.cyan(i18n.t("update:installed", { count: config.workflows.installed.length })));
3541
+ for (const cmd of config.workflows.installed) {
3542
+ console.log(` ${ansis.gray("\u2022")} /ccg:${cmd}`);
3543
+ }
3459
3544
  }
3460
- }
3461
- if (!await verifyBinary(installDir)) {
3462
- showBinaryDownloadWarning(join(installDir, "bin"));
3545
+ } else {
3546
+ spinner.fail(i18n.t("update:installFailed"));
3547
+ console.log(ansis.red(" Install subprocess completed but no command files were created"));
3463
3548
  }
3464
3549
  } catch (error) {
3465
3550
  spinner.fail(i18n.t("update:installFailed"));
3466
3551
  console.log(ansis.red(`${i18n.t("common:error")}: ${error}`));
3552
+ }
3553
+ if (installSuccess) {
3554
+ for (const dir of backedUp) {
3555
+ try {
3556
+ await fs.remove(dir + BACKUP_SUFFIX);
3557
+ } catch {
3558
+ }
3559
+ }
3560
+ if (!await verifyBinary(installDir)) {
3561
+ showBinaryDownloadWarning(join(installDir, "bin"));
3562
+ }
3563
+ } else {
3564
+ console.log();
3565
+ console.log(ansis.yellow.bold(" \u26A0 \u6B63\u5728\u6062\u590D\u65E7\u7248\u672C\u6587\u4EF6 / Restoring old version files..."));
3566
+ let restored = 0;
3567
+ for (const dir of backedUp) {
3568
+ const backupPath = dir + BACKUP_SUFFIX;
3569
+ try {
3570
+ if (await fs.pathExists(dir)) {
3571
+ await fs.remove(dir);
3572
+ }
3573
+ if (await fs.pathExists(backupPath)) {
3574
+ await fs.move(backupPath, dir);
3575
+ restored++;
3576
+ }
3577
+ } catch (restoreErr) {
3578
+ console.log(ansis.red(` Failed to restore ${dir}: ${restoreErr}`));
3579
+ }
3580
+ }
3581
+ if (restored > 0) {
3582
+ console.log(ansis.green(` \u2713 \u5DF2\u6062\u590D ${restored} \u4E2A\u76EE\u5F55 / Restored ${restored} directories`));
3583
+ console.log(ansis.gray(" \u65E7\u7248\u547D\u4EE4\u4ECD\u53EF\u6B63\u5E38\u4F7F\u7528 / Old commands still work"));
3584
+ }
3467
3585
  console.log();
3468
3586
  console.log(ansis.yellow(i18n.t("update:manualRetry")));
3469
3587
  console.log(ansis.cyan(" npx ccg-workflow@latest"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccg-workflow",
3
- "version": "1.7.85",
3
+ "version": "1.7.87",
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",
@@ -70,6 +70,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
70
70
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时。
71
71
  如果 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**。
72
72
  - 若因等待时间过长跳过了等待 TaskOutput 结果,则**必须调用 `AskUserQuestion` 工具询问用户选择继续等待还是 Kill Task。禁止直接 Kill Task。**
73
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
74
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
73
75
 
74
76
  ---
75
77
 
@@ -79,6 +79,8 @@ EOF",
79
79
 
80
80
  **会话复用**:每次调用返回 `SESSION_ID: xxx`,后续阶段用 `resume xxx` 复用上下文。阶段 2 保存 `CODEX_SESSION`,阶段 3 和 5 使用 `resume` 复用。
81
81
 
82
+ ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。若调用超时,继续等待,禁止跳过或提前终止。
83
+
82
84
  ---
83
85
 
84
86
  ## 沟通守则
@@ -120,6 +120,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
120
120
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时
121
121
  - 若 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**
122
122
  - 若因等待时间过长跳过了等待,**必须调用 `AskUserQuestion` 询问用户选择继续等待还是 Kill Task**
123
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
124
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
123
125
 
124
126
  ---
125
127
 
@@ -70,6 +70,8 @@ EOF
70
70
  - 必须指定 `timeout: 600000`,否则默认 30 秒会超时
71
71
  - 如果 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**
72
72
  - 若等待时间过长,**必须用 `AskUserQuestion` 询问用户是否继续等待,禁止直接 Kill**
73
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
74
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
73
75
 
74
76
  ---
75
77
 
@@ -107,6 +107,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
107
107
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时
108
108
  - 若 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**
109
109
  - 若因等待时间过长跳过了等待,**必须调用 `AskUserQuestion` 询问用户选择继续等待还是 Kill Task**
110
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
111
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
110
112
 
111
113
  ---
112
114
 
@@ -76,6 +76,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
76
76
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时。
77
77
  如果 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**。
78
78
  - 若因等待时间过长跳过了等待 TaskOutput 结果,则**必须调用 `AskUserQuestion` 工具询问用户选择继续等待还是 Kill Task。禁止直接 Kill Task。**
79
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
80
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
79
81
 
80
82
  ---
81
83
 
@@ -79,6 +79,8 @@ EOF",
79
79
 
80
80
  **会话复用**:每次调用返回 `SESSION_ID: xxx`,后续阶段用 `resume xxx` 复用上下文。阶段 2 保存 `GEMINI_SESSION`,阶段 3 和 5 使用 `resume` 复用。
81
81
 
82
+ ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才报告错误并终止。
83
+
82
84
  ---
83
85
 
84
86
  ## 沟通守则
@@ -75,6 +75,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
75
75
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时。
76
76
  如果 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**。
77
77
  - 若因等待时间过长跳过了等待 TaskOutput 结果,则**必须调用 `AskUserQuestion` 工具询问用户选择继续等待还是 Kill Task。禁止直接 Kill Task。**
78
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
79
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
78
80
 
79
81
  ---
80
82
 
@@ -66,6 +66,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
66
66
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时
67
67
  - 若 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**
68
68
  - 若因等待时间过长跳过了等待,**必须调用 `AskUserQuestion` 询问用户选择继续等待还是 Kill Task**
69
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
70
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
69
71
 
70
72
  ---
71
73
 
@@ -65,6 +65,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
65
65
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时。
66
66
  如果 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**。
67
67
  - 若因等待时间过长跳过了等待 TaskOutput 结果,则**必须调用 `AskUserQuestion` 工具询问用户选择继续等待还是 Kill Task。禁止直接 Kill Task。**
68
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
69
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
68
70
 
69
71
  ---
70
72
 
@@ -106,6 +106,9 @@ description: '按规范执行 + 多模型协作 + 归档'
106
106
  TaskOutput({ task_id: "<gemini_task_id>", block: true, timeout: 600000 })
107
107
  ```
108
108
 
109
+ ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败,最多重试 2 次(间隔 5 秒)。3 次全败才跳过。
110
+ ⛔ **Codex 结果必须等待**:Codex 执行 5-15 分钟属正常,超时后继续轮询,禁止跳过。
111
+
109
112
  Address any critical findings before proceeding.
110
113
 
111
114
  8. **Update Task Status**
@@ -56,6 +56,9 @@ description: '多模型分析 → 消除歧义 → 零决策可执行计划'
56
56
  TaskOutput({ task_id: "<gemini_task_id>", block: true, timeout: 600000 })
57
57
  ```
58
58
 
59
+ ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败,最多重试 2 次(间隔 5 秒)。3 次全败才跳过。
60
+ ⛔ **Codex 结果必须等待**:Codex 执行 5-15 分钟属正常,超时后继续轮询,禁止跳过。
61
+
59
62
  - Synthesize responses and present consolidated options to user.
60
63
 
61
64
  3. **Uncertainty Elimination Audit**
@@ -95,6 +95,9 @@ description: '需求 → 约束集(并行探索 + OPSX 提案)'
95
95
  TaskOutput({ task_id: "<gemini_task_id>", block: true, timeout: 600000 })
96
96
  ```
97
97
 
98
+ ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败,最多重试 2 次(间隔 5 秒)。3 次全败才跳过。
99
+ ⛔ **Codex 结果必须等待**:Codex 执行 5-15 分钟属正常,超时后继续轮询,禁止跳过。
100
+
98
101
  5. **Aggregate and Synthesize**
99
102
  - Collect all subagent outputs.
100
103
  - Merge into unified constraint sets:
@@ -57,6 +57,9 @@ description: '双模型交叉审查(独立工具,随时可用)'
57
57
  TaskOutput({ task_id: "<gemini_task_id>", block: true, timeout: 600000 })
58
58
  ```
59
59
 
60
+ ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败,最多重试 2 次(间隔 5 秒)。3 次全败才跳过。
61
+ ⛔ **Codex 结果必须等待**:Codex 执行 5-15 分钟属正常,超时后继续轮询,禁止跳过。
62
+
60
63
  4. **Synthesize Findings**
61
64
  - Merge findings from both models.
62
65
  - Deduplicate overlapping issues.
@@ -36,9 +36,12 @@ description: 'Agent Teams 并行实施 - 读取计划文件,spawn Builder team
36
36
  确认开始?
37
37
  ```
38
38
 
39
- 3. **创建 Team + spawn Builders**
40
- - 创建 Agent Team。
41
- - Layer 分组 spawn Builder teammates(Sonnet)。
39
+ 3. **使用 TeamCreate 创建 Team,然后 spawn teammates 加入该 Team**
40
+ - ⛔ **禁止使用普通 Agent 子代理。必须通过 TeamCreate 创建 team,再通过 Agent(team_name=...) spawn teammates 加入 team。**
41
+ - 先调用 TeamCreate 创建 team。
42
+ - 为每个子任务调用 TaskCreate 创建 task。
43
+ - 按 Layer 分组,通过 Agent(team_name=..., name="builder-N") spawn Builder teammates(Sonnet)。
44
+ - 通过 TaskUpdate(owner="builder-N") 将 task 分配给对应 Builder。
42
45
  - 每个 Builder 的 spawn prompt 必须包含:
43
46
 
44
47
  ```
@@ -70,10 +73,11 @@ description: 'Agent Teams 并行实施 - 读取计划文件,spawn Builder team
70
73
  - **依赖关系**:Layer 2 的 Builder 任务设为依赖 Layer 1 的对应任务,等 Layer 1 完成后自动解锁。
71
74
  - spawn 完成后,进入 **delegate 模式**,只协调不写码。
72
75
 
73
- 4. **监控进度**
74
- - 等待所有 Builder 完成。
76
+ 4. **通过 TaskList + SendMessage 监控进度**
77
+ - 通过 TaskList 查看各 task 状态,通过 SendMessage 与 Builder 沟通。
78
+ - teammates 完成 task 后会自动发消息通知你,无需轮询。
75
79
  - 如果某个 Builder 遇到问题并发消息求助:
76
- * 分析问题,给出指导建议
80
+ * 通过 SendMessage 回复指导建议
77
81
  * 不要自己写代码替它完成
78
82
  - 如果某个 Builder 失败:
79
83
  * 记录失败原因
@@ -98,7 +102,7 @@ description: 'Agent Teams 并行实施 - 读取计划文件,spawn Builder team
98
102
  3. 提交代码:`git add -A && git commit`
99
103
  ```
100
104
 
101
- - 关闭所有 teammates,清理 team。
105
+ - 通过 SendMessage 发送 shutdown_request 关闭所有 teammates,清理 team。
102
106
 
103
107
  **Exit Criteria**
104
108
  - [ ] 所有 Builder 任务完成(或明确失败并记录原因)
@@ -51,6 +51,8 @@ description: 'Agent Teams 规划 - Lead 调用 Codex/Gemini 并行分析,产
51
51
 
52
52
  - 必须指定 `timeout: 600000`,否则默认 30 秒会提前超时。
53
53
  - 若 10 分钟后仍未完成,继续轮询,**绝对不要 Kill 进程**。
54
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
55
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续轮询,**绝对禁止在 Codex 未返回结果时直接跳过**。
54
56
 
55
57
  3. **综合分析 + 任务拆分**
56
58
  - 后端方案以 Codex 为准,前端方案以 Gemini 为准。
@@ -62,6 +62,9 @@ description: 'Agent Teams 需求研究 - 并行探索代码库,产出约束集
62
62
  TaskOutput({ task_id: "<gemini_task_id>", block: true, timeout: 600000 })
63
63
  ```
64
64
 
65
+ ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败,最多重试 2 次(间隔 5 秒)。3 次全败才跳过。
66
+ ⛔ **Codex 结果必须等待**:Codex 执行 5-15 分钟属正常,超时后继续轮询,禁止跳过。
67
+
65
68
  4. **聚合与综合**
66
69
  - 合并所有探索输出为统一约束集:
67
70
  * **硬约束**:技术限制、不可违反的模式
@@ -48,6 +48,9 @@ description: 'Agent Teams 审查 - 双模型交叉审查并行实施的产出,
48
48
  TaskOutput({ task_id: "<gemini_task_id>", block: true, timeout: 600000 })
49
49
  ```
50
50
 
51
+ ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败,最多重试 2 次(间隔 5 秒)。3 次全败才跳过。
52
+ ⛔ **Codex 结果必须等待**:Codex 执行 5-15 分钟属正常,超时后继续轮询,禁止跳过。
53
+
51
54
  3. **综合发现**
52
55
  - 合并两个模型的发现。
53
56
  - 去重重叠问题。
@@ -87,6 +87,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
87
87
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时。
88
88
  如果 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**。
89
89
  - 若因等待时间过长跳过了等待 TaskOutput 结果,则**必须调用 `AskUserQuestion` 工具询问用户选择继续等待还是 Kill Task。禁止直接 Kill Task。**
90
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
91
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
90
92
 
91
93
  ---
92
94
 
@@ -97,6 +97,8 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
97
97
  - 必须指定 `timeout: 600000`,否则默认只有 30 秒会导致提前超时。
98
98
  如果 10 分钟后仍未完成,继续用 `TaskOutput` 轮询,**绝对不要 Kill 进程**。
99
99
  - 若因等待时间过长跳过了等待 TaskOutput 结果,则**必须调用 `AskUserQuestion` 工具询问用户选择继续等待还是 Kill Task。禁止直接 Kill Task。**
100
+ - ⛔ **Gemini 失败必须重试**:若 Gemini 调用失败(非零退出码或输出包含错误信息),最多重试 2 次(间隔 5 秒)。仅当 3 次全部失败时才跳过 Gemini 结果并使用单模型结果继续。
101
+ - ⛔ **Codex 结果必须等待**:Codex 执行时间较长(5-15 分钟)属于正常。TaskOutput 超时后必须继续用 TaskOutput 轮询,**绝对禁止在 Codex 未返回结果时直接跳过或继续下一阶段**。已启动的 Codex 任务若被跳过 = 浪费 token + 丢失结果。
100
102
 
101
103
  ---
102
104
 
@@ -59,14 +59,14 @@ Refactoring: refactor → /verify-change → /verify-quality → /verify-secu
59
59
 
60
60
  ```bash
61
61
  # Unified runner
62
- node ~/.claude/skills/run_skill.js <skill-name> [args...]
62
+ node ~/.claude/skills/ccg/run_skill.js <skill-name> [args...]
63
63
 
64
64
  # Examples
65
- node ~/.claude/skills/run_skill.js verify-security ./src
66
- node ~/.claude/skills/run_skill.js verify-quality ./src -v
67
- node ~/.claude/skills/run_skill.js verify-change --mode staged
68
- node ~/.claude/skills/run_skill.js verify-module ./my-module
69
- node ~/.claude/skills/run_skill.js gen-docs ./new-module --force
65
+ node ~/.claude/skills/ccg/run_skill.js verify-security ./src
66
+ node ~/.claude/skills/ccg/run_skill.js verify-quality ./src -v
67
+ node ~/.claude/skills/ccg/run_skill.js verify-change --mode staged
68
+ node ~/.claude/skills/ccg/run_skill.js verify-module ./my-module
69
+ node ~/.claude/skills/ccg/run_skill.js gen-docs ./new-module --force
70
70
  ```
71
71
 
72
72
  ---