ccg-workflow 3.0.0 → 3.0.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/README.md +22 -3
- package/README.zh-CN.md +21 -4
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/shared/{ccg-workflow.81OoN8XX.mjs → ccg-workflow.2vO_S-e7.mjs} +1 -1
- package/package.json +1 -1
- package/templates/commands/go.md +8 -2
- package/templates/engine/strategies/debug-investigate.md +7 -1
- package/templates/engine/strategies/full-collaborate.md +15 -1
- package/templates/engine/strategies/guided-develop.md +7 -1
- package/templates/engine/strategies/refactor-safely.md +7 -1
- package/templates/hooks/task-utils.js +59 -5
package/README.md
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
# CCG - Claude + Codex + Gemini Multi-Model Collaboration
|
|
2
2
|
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
<img src="assets/logo/ccg-logo-cropped.png" alt="CCG Workflow" width="400">
|
|
6
|
+
|
|
3
7
|
[](https://github.com/fengshao1227/ccg-workflow)
|
|
4
8
|
[](https://www.npmjs.com/package/ccg-workflow)
|
|
5
9
|
[](https://www.npmjs.com/package/ccg-workflow)
|
|
6
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://claude.ai/code)
|
|
12
|
+
[]()
|
|
13
|
+
[](https://x.com/CCG_Workflow)
|
|
14
|
+

|
|
7
15
|
|
|
8
16
|
[简体中文](./README.zh-CN.md) | English
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
## ♥️ Sponsor
|
|
11
21
|
|
|
12
|
-
[302.AI](https://share.302.ai/oUDqQ6)
|
|
22
|
+
[](https://share.302.ai/oUDqQ6)
|
|
13
23
|
|
|
14
|
-
[
|
|
24
|
+
[302.AI](https://share.302.ai/oUDqQ6) is a pay-as-you-go enterprise AI resource hub that offers the latest and most comprehensive AI models and APIs on the market, along with a variety of ready-to-use online AI applications.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
[**n1n.ai**](https://api.n1n.ai/register?channel=c_ivgzug0w) — Global LLM API Gateway. One API Key to access 500+ top AI models (GPT-5, Claude 4.5, Gemini 3 Pro, and more).
|
|
15
29
|
|
|
16
30
|
---
|
|
17
31
|
|
|
@@ -224,6 +238,11 @@ npx ccg-workflow # Select "Uninstall" from menu
|
|
|
224
238
|
- **Issues**: [GitHub Issues](https://github.com/fengshao1227/ccg-workflow/issues)
|
|
225
239
|
- **Community**: [Linux.do](https://linux.do)
|
|
226
240
|
|
|
241
|
+
|
|
242
|
+
## Star History
|
|
243
|
+
|
|
244
|
+
[](https://www.star-history.com/#fengshao1227/ccg-workflow&type=timeline&legend=top-left)
|
|
245
|
+
|
|
227
246
|
## License
|
|
228
247
|
|
|
229
248
|
MIT
|
package/README.zh-CN.md
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
# CCG - Claude + Codex + Gemini 多模型协作
|
|
2
|
+
# CCG - Claude + Codex + Gemini Multi-Model Collaboration
|
|
2
3
|
|
|
4
|
+
<div align="center">
|
|
5
|
+
|
|
6
|
+
<img src="assets/logo/ccg-logo-cropped.png" alt="CCG Workflow" width="400">
|
|
7
|
+
|
|
8
|
+
[](https://github.com/fengshao1227/ccg-workflow)
|
|
9
|
+
[](https://www.npmjs.com/package/ccg-workflow)
|
|
3
10
|
[](https://www.npmjs.com/package/ccg-workflow)
|
|
4
11
|
[](https://opensource.org/licenses/MIT)
|
|
12
|
+
[](https://claude.ai/code)
|
|
13
|
+
[]()
|
|
14
|
+
[](https://x.com/CCG_Workflow)
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
[简体中文](./README.zh-CN.md) | English
|
|
5
18
|
|
|
6
|
-
|
|
19
|
+
</div>
|
|
7
20
|
|
|
8
|
-
##
|
|
21
|
+
## ♥️ Sponsor
|
|
9
22
|
|
|
10
|
-
[302.AI](https://share.302.ai/oUDqQ6)
|
|
23
|
+
[](https://share.302.ai/oUDqQ6)
|
|
24
|
+
|
|
25
|
+
[302.AI](https://share.302.ai/oUDqQ6) is a pay-as-you-go enterprise AI resource hub that offers the latest and most comprehensive AI models and APIs on the market, along with a variety of ready-to-use online AI applications.
|
|
26
|
+
|
|
27
|
+
---
|
|
11
28
|
|
|
12
|
-
[n1n.ai](https://api.n1n.ai/register?channel=c_ivgzug0w) —
|
|
29
|
+
[**n1n.ai**](https://api.n1n.ai/register?channel=c_ivgzug0w) — Global LLM API Gateway. One API Key to access 500+ top AI models (GPT-5, Claude 4.5, Gemini 3 Pro, and more).
|
|
13
30
|
|
|
14
31
|
---
|
|
15
32
|
|
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.
|
|
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';
|
|
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.
|
|
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';
|
|
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.
|
|
13
|
+
const version = "3.0.1";
|
|
14
14
|
|
|
15
15
|
function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
|
|
16
16
|
return {
|
package/package.json
CHANGED
package/templates/commands/go.md
CHANGED
|
@@ -127,7 +127,9 @@ $ARGUMENTS
|
|
|
127
127
|
mkdir -p .ccg/tasks/{task-name}
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
**Step 3**:
|
|
130
|
+
**Step 3**: 获取当前 git 分支名:`git rev-parse --abbrev-ref HEAD`
|
|
131
|
+
|
|
132
|
+
**Step 4**: 写入 `.ccg/tasks/{task-name}/task.json`:
|
|
131
133
|
|
|
132
134
|
```json
|
|
133
135
|
{
|
|
@@ -138,11 +140,15 @@ mkdir -p .ccg/tasks/{task-name}
|
|
|
138
140
|
"currentPhase": "1",
|
|
139
141
|
"nextAction": "{策略第一阶段的描述}",
|
|
140
142
|
"gate": null,
|
|
143
|
+
"branch": "{当前 git 分支}",
|
|
144
|
+
"scope": "{task-name}",
|
|
141
145
|
"createdAt": "{当前 ISO 日期时间}"
|
|
142
146
|
}
|
|
143
147
|
```
|
|
144
148
|
|
|
145
|
-
**Step
|
|
149
|
+
**Step 5**: 创建 `.ccg/tasks/{task-name}/context.jsonl` 种子文件:
|
|
150
|
+
- 第一行写种子示例:`{"_example": "Fill with {\"file\": \"path\", \"reason\": \"why\"}. Seed rows are skipped."}`
|
|
151
|
+
- 如果 `.ccg/spec/` 存在 → 追加 spec 文件条目
|
|
146
152
|
|
|
147
153
|
**复杂度 S → 跳过任务创建**(保持轻量)。
|
|
148
154
|
|
|
@@ -144,7 +144,13 @@ Gate: 用户已确认修复方向 ✓
|
|
|
144
144
|
📍 Next: /ccg commit 提交修复
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
**Task 更新**:`status → "
|
|
147
|
+
**Task 更新**:`status → "archived"`
|
|
148
|
+
|
|
149
|
+
**归档任务**:
|
|
150
|
+
```bash
|
|
151
|
+
mkdir -p .ccg/tasks/archive/$(date +%Y-%m) && mv .ccg/tasks/{task-name} .ccg/tasks/archive/$(date +%Y-%m)/
|
|
152
|
+
git add .ccg/tasks/ && git commit -m "chore: archive ccg task"
|
|
153
|
+
```
|
|
148
154
|
|
|
149
155
|
---
|
|
150
156
|
|
|
@@ -277,7 +277,21 @@ SendMessage({ to: "reviewer", message: { type: "shutdown_request" } })
|
|
|
277
277
|
📍 Next: /ccg commit 提交,或查看 .ccg/tasks/{task-name}/ 中的完整记录
|
|
278
278
|
```
|
|
279
279
|
|
|
280
|
-
**Task 更新**:`status → "
|
|
280
|
+
**Task 更新**:`status → "archived"`
|
|
281
|
+
|
|
282
|
+
**归档任务**:将 `.ccg/tasks/{task-name}/` 移动到 `.ccg/tasks/archive/YYYY-MM/{task-name}/`
|
|
283
|
+
```bash
|
|
284
|
+
mkdir -p .ccg/tasks/archive/$(date +%Y-%m) && mv .ccg/tasks/{task-name} .ccg/tasks/archive/$(date +%Y-%m)/
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**自动提交归档**:
|
|
288
|
+
```bash
|
|
289
|
+
git add .ccg/tasks/ && git commit -m "chore: archive ccg task {task-name}"
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
📍 Next: /ccg:commit 提交产品代码
|
|
294
|
+
```
|
|
281
295
|
|
|
282
296
|
---
|
|
283
297
|
|
|
@@ -188,7 +188,13 @@ TaskOutput({ task_id: "<id>", block: true, timeout: 600000 })
|
|
|
188
188
|
📍 Next: 可以用 /ccg:commit 提交
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
-
**Task 更新**:`status → "
|
|
191
|
+
**Task 更新**:`status → "archived"`
|
|
192
|
+
|
|
193
|
+
**归档任务**:
|
|
194
|
+
```bash
|
|
195
|
+
mkdir -p .ccg/tasks/archive/$(date +%Y-%m) && mv .ccg/tasks/{task-name} .ccg/tasks/archive/$(date +%Y-%m)/
|
|
196
|
+
git add .ccg/tasks/ && git commit -m "chore: archive ccg task"
|
|
197
|
+
```
|
|
192
198
|
|
|
193
199
|
---
|
|
194
200
|
|
|
@@ -145,7 +145,13 @@ Step [N/M]: [描述] — ✅ 测试通过 / ❌ 测试失败
|
|
|
145
145
|
📍 Next: /ccg:commit 提交
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
**Task 更新**:`status → "
|
|
148
|
+
**Task 更新**:`status → "archived"`
|
|
149
|
+
|
|
150
|
+
**归档任务**:
|
|
151
|
+
```bash
|
|
152
|
+
mkdir -p .ccg/tasks/archive/$(date +%Y-%m) && mv .ccg/tasks/{task-name} .ccg/tasks/archive/$(date +%Y-%m)/
|
|
153
|
+
git add .ccg/tasks/ && git commit -m "chore: archive ccg task"
|
|
154
|
+
```
|
|
149
155
|
|
|
150
156
|
---
|
|
151
157
|
|
|
@@ -25,9 +25,10 @@ function getActiveTask(projectRoot) {
|
|
|
25
25
|
try {
|
|
26
26
|
const dirs = fs.readdirSync(tasksDir)
|
|
27
27
|
.filter(d => {
|
|
28
|
+
if (d === 'archive') return false;
|
|
28
29
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const full = path.join(tasksDir, d);
|
|
31
|
+
return fs.statSync(full).isDirectory() && fs.existsSync(path.join(full, 'task.json'));
|
|
31
32
|
} catch { return false; }
|
|
32
33
|
})
|
|
33
34
|
.sort()
|
|
@@ -35,10 +36,12 @@ function getActiveTask(projectRoot) {
|
|
|
35
36
|
|
|
36
37
|
for (const dir of dirs) {
|
|
37
38
|
try {
|
|
38
|
-
const
|
|
39
|
+
const taskPath = path.join(tasksDir, dir, 'task.json');
|
|
40
|
+
if (!fs.existsSync(taskPath)) continue; // stale pointer detection
|
|
41
|
+
const raw = fs.readFileSync(taskPath, 'utf-8');
|
|
39
42
|
const task = JSON.parse(raw);
|
|
40
43
|
if (task.status !== 'completed' && task.status !== 'archived') {
|
|
41
|
-
return { dir: path.join(tasksDir, dir), ...task };
|
|
44
|
+
return { dir: path.join(tasksDir, dir), ...task, _stale: false };
|
|
42
45
|
}
|
|
43
46
|
} catch { /* skip malformed */ }
|
|
44
47
|
}
|
|
@@ -101,6 +104,54 @@ function outputHook(eventName, additionalContext) {
|
|
|
101
104
|
}));
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
function archiveTask(taskDir, projectRoot) {
|
|
108
|
+
try {
|
|
109
|
+
const now = new Date();
|
|
110
|
+
const month = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
|
|
111
|
+
const archiveDir = path.join(projectRoot, '.ccg', 'tasks', 'archive', month);
|
|
112
|
+
if (!fs.existsSync(archiveDir)) fs.mkdirSync(archiveDir, { recursive: true });
|
|
113
|
+
const name = path.basename(taskDir);
|
|
114
|
+
const dest = path.join(archiveDir, name);
|
|
115
|
+
fs.renameSync(taskDir, dest);
|
|
116
|
+
return dest;
|
|
117
|
+
} catch { return null; }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function autoCommitTask(projectRoot, message) {
|
|
121
|
+
try {
|
|
122
|
+
const { execSync } = require('child_process');
|
|
123
|
+
execSync('git add .ccg/tasks/', { cwd: projectRoot, stdio: 'pipe' });
|
|
124
|
+
const diff = execSync('git diff --cached --quiet', { cwd: projectRoot, stdio: 'pipe' }).toString();
|
|
125
|
+
return false; // nothing to commit
|
|
126
|
+
} catch {
|
|
127
|
+
try {
|
|
128
|
+
const { execSync } = require('child_process');
|
|
129
|
+
execSync(`git commit -m "${message || 'chore: archive ccg task'}"`, { cwd: projectRoot, stdio: 'pipe' });
|
|
130
|
+
return true;
|
|
131
|
+
} catch { return false; }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function seedContextJsonl(taskDir, projectRoot) {
|
|
136
|
+
const jsonlPath = path.join(taskDir, 'context.jsonl');
|
|
137
|
+
if (fs.existsSync(jsonlPath)) return;
|
|
138
|
+
const specDir = path.join(projectRoot, '.ccg', 'spec');
|
|
139
|
+
const lines = ['{"_example": "Fill with {\\\"file\\\": \\\"path\\\", \\\"reason\\\": \\\"why\\\"}. One entry per line. Seed rows (with _example key) are skipped."}'];
|
|
140
|
+
if (fs.existsSync(specDir)) {
|
|
141
|
+
try {
|
|
142
|
+
const walk = (dir, prefix) => {
|
|
143
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
144
|
+
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
145
|
+
if (e.isDirectory()) walk(path.join(dir, e.name), rel);
|
|
146
|
+
else if (e.name.endsWith('.md')) lines.push(JSON.stringify({ file: `.ccg/spec/${rel}`, reason: 'project spec' }));
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
walk(specDir, '');
|
|
150
|
+
} catch { /* silent */ }
|
|
151
|
+
}
|
|
152
|
+
try { fs.writeFileSync(jsonlPath, lines.join('\n') + '\n', 'utf-8'); } catch { /* silent */ }
|
|
153
|
+
}
|
|
154
|
+
|
|
104
155
|
module.exports = {
|
|
105
156
|
findProjectRoot,
|
|
106
157
|
getActiveTask,
|
|
@@ -109,5 +160,8 @@ module.exports = {
|
|
|
109
160
|
readContextJsonl,
|
|
110
161
|
detectTechStack,
|
|
111
162
|
getGitInfo,
|
|
112
|
-
outputHook
|
|
163
|
+
outputHook,
|
|
164
|
+
archiveTask,
|
|
165
|
+
autoCommitTask,
|
|
166
|
+
seedContextJsonl
|
|
113
167
|
};
|