ccg-workflow 3.1.2 → 3.1.4

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
@@ -144,7 +144,7 @@ CCG installs 4 hooks into `~/.claude/settings.json`:
144
144
  |------|-------|---------|
145
145
  | workflow-state.js | UserPromptSubmit | Injects task state breadcrumb every turn |
146
146
  | session-start.js | SessionStart | Injects full project context on session start/clear/compact |
147
- | subagent-context.js | PreToolUse (Bash/Agent) | Injects spec + task context into codeagent-wrapper calls and Team member spawns |
147
+ | subagent-context.js | PreToolUse (Bash/Agent) | Injects spec + task context: directly into Team member prompt via `updatedInput`, into lead context for codeagent-wrapper calls |
148
148
  | skill-router.js | UserPromptSubmit | Auto-injects domain knowledge when keywords detected |
149
149
 
150
150
  Hooks are JavaScript, zero dependencies, silent on failure.
@@ -253,4 +253,4 @@ MIT
253
253
 
254
254
  ---
255
255
 
256
- v3.1.2 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
256
+ v3.1.4 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
package/README.zh-CN.md CHANGED
@@ -145,7 +145,7 @@ CCG 在 `~/.claude/settings.json` 注册 4 个 Hook:
145
145
  |------|------|------|
146
146
  | workflow-state.js | UserPromptSubmit | 每轮注入任务状态面包屑 |
147
147
  | session-start.js | SessionStart | 会话开始/压缩时注入完整项目上下文 |
148
- | subagent-context.js | PreToolUse | codeagent-wrapper/Team spawn 时注入 spec + 任务上下文 |
148
+ | subagent-context.js | PreToolUse | Team spawn 时通过 `updatedInput` 直接注入子 agent prompt;codeagent-wrapper 时注入主控上下文 |
149
149
  | skill-router.js | UserPromptSubmit | 检测域关键词,自动注入知识文件 |
150
150
 
151
151
  纯 JavaScript,零依赖,失败时静默退出。
@@ -248,4 +248,4 @@ MIT
248
248
 
249
249
  ---
250
250
 
251
- v3.0.4 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
251
+ v3.1.4 | [Issues](https://github.com/fengshao1227/ccg-workflow/issues) | [Contributing](./CONTRIBUTING.md)
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { B as diagnoseMcpConfig, C as isWindows, D as readClaudeCodeConfig, E as fixWindowsMcpConfig, F as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, G as configMcp, H as version } from './shared/ccg-workflow.CTnUpMWE.mjs';
4
+ import { B as diagnoseMcpConfig, C as isWindows, D as readClaudeCodeConfig, E as fixWindowsMcpConfig, F as writeClaudeCodeConfig, r as readCcgConfig, b as initI18n, a as i18n, s as showMainMenu, i as init, G as configMcp, H as version } from './shared/ccg-workflow.B4UibgqQ.mjs';
5
5
  import 'inquirer';
6
6
  import 'ora';
7
7
  import 'node:child_process';
package/dist/index.d.mts CHANGED
@@ -196,6 +196,7 @@ interface UninstallResult {
196
196
  removedAgents: string[];
197
197
  removedSkills: string[];
198
198
  removedRules: boolean;
199
+ removedHooks: boolean;
199
200
  removedBin: boolean;
200
201
  errors: string[];
201
202
  }
package/dist/index.d.ts CHANGED
@@ -196,6 +196,7 @@ interface UninstallResult {
196
196
  removedAgents: string[];
197
197
  removedSkills: string[];
198
198
  removedRules: boolean;
199
+ removedHooks: boolean;
199
200
  removedBin: boolean;
200
201
  errors: string[];
201
202
  }
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { c as changeLanguage, z as checkForUpdates, A as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, x as getCurrentVersion, y as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, n as installCodexMode, k as installWorkflows, t as migrateToV1_4_0, v as needsMigration, r as readCcgConfig, s as showMainMenu, q as uninstallAceTool, o as uninstallCodexMode, p as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.CTnUpMWE.mjs';
1
+ export { c as changeLanguage, z as checkForUpdates, A as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, x as getCurrentVersion, y as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, m as installAceToolRs, n as installCodexMode, k as installWorkflows, t as migrateToV1_4_0, v as needsMigration, r as readCcgConfig, s as showMainMenu, q as uninstallAceTool, o as uninstallCodexMode, p as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.B4UibgqQ.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.1.2";
13
+ const version = "3.1.4";
14
14
 
15
15
  function cmd(id, order, category, name, nameEn, description, descriptionEn, cmdOverride) {
16
16
  return {
@@ -1541,6 +1541,7 @@ async function uninstallWorkflows(installDir, options) {
1541
1541
  removedAgents: [],
1542
1542
  removedSkills: [],
1543
1543
  removedRules: false,
1544
+ removedHooks: false,
1544
1545
  removedBin: false,
1545
1546
  errors: []
1546
1547
  };
@@ -1605,6 +1606,46 @@ async function uninstallWorkflows(installDir, options) {
1605
1606
  result.errors.push(`Failed to remove .ccg directory: ${error}`);
1606
1607
  }
1607
1608
  }
1609
+ const hooksCcgDir = join(installDir, "hooks", "ccg");
1610
+ if (await fs.pathExists(hooksCcgDir)) {
1611
+ try {
1612
+ await fs.remove(hooksCcgDir);
1613
+ result.removedHooks = true;
1614
+ } catch (error) {
1615
+ result.errors.push(`Failed to remove hooks directory: ${error}`);
1616
+ result.success = false;
1617
+ }
1618
+ }
1619
+ const settingsPath = join(installDir, "settings.json");
1620
+ if (await fs.pathExists(settingsPath)) {
1621
+ try {
1622
+ const settings = JSON.parse(await fs.readFile(settingsPath, "utf-8"));
1623
+ const hooks = settings.hooks;
1624
+ if (hooks && typeof hooks === "object") {
1625
+ const isCcgEntry = (h) => {
1626
+ const hHooks = h?.hooks || [];
1627
+ return hHooks.some((hh) => typeof hh?.command === "string" && /hooks[\\/]ccg[\\/]/.test(hh.command));
1628
+ };
1629
+ let modified = false;
1630
+ for (const event of Object.keys(hooks)) {
1631
+ const arr = Array.isArray(hooks[event]) ? hooks[event] : [];
1632
+ const filtered = arr.filter((h) => !isCcgEntry(h));
1633
+ if (filtered.length !== arr.length) {
1634
+ modified = true;
1635
+ if (filtered.length === 0) delete hooks[event];
1636
+ else hooks[event] = filtered;
1637
+ }
1638
+ }
1639
+ if (modified) {
1640
+ if (Object.keys(hooks).length === 0) delete settings.hooks;
1641
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
1642
+ result.removedHooks = true;
1643
+ }
1644
+ }
1645
+ } catch (error) {
1646
+ result.errors.push(`Failed to deregister hooks from settings.json: ${error}`);
1647
+ }
1648
+ }
1608
1649
  return result;
1609
1650
  }
1610
1651
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccg-workflow",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
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",
@@ -155,7 +155,23 @@ Agent role: ${detectedRole}
155
155
 
156
156
  if (contextParts.length === 0) process.exit(0);
157
157
 
158
- outputHook('PreToolUse', contextParts.join('\n\n'));
158
+ const injected = `<ccg-injected-context>\n${contextParts.join('\n\n')}\n</ccg-injected-context>`;
159
+
160
+ // Agent/Team spawn: rewrite the spawned teammate's OWN prompt via updatedInput.
161
+ // A PreToolUse hook's additionalContext only reaches the CALLING (lead) session,
162
+ // which the not-yet-created subagent can never read. updatedInput replaces the
163
+ // entire tool input, so we spread toolInput to keep subagent_type/name/team_name/
164
+ // model intact and only prepend the spec to `prompt`. The teammate is born with
165
+ // the spec already in its prompt. (Docs: PreToolUse → updatedInput.)
166
+ if (isTeamSpawn && typeof toolInput.prompt === 'string') {
167
+ outputHook('PreToolUse', null, {
168
+ updatedInput: { ...toolInput, prompt: `${injected}\n\n---\n\n${toolInput.prompt}` }
169
+ });
170
+ } else {
171
+ // Bash / codeagent-wrapper: the lead builds the HEREDOC task text itself, so the
172
+ // spec belongs in the lead's context where it can be woven into the command.
173
+ outputHook('PreToolUse', injected);
174
+ }
159
175
  } catch {
160
176
  process.exit(0);
161
177
  }
@@ -95,13 +95,20 @@ function getGitInfo(projectRoot) {
95
95
  } catch { return { branch: 'unknown', dirtyCount: 0 }; }
96
96
  }
97
97
 
98
- function outputHook(eventName, additionalContext) {
99
- console.log(JSON.stringify({
100
- hookSpecificOutput: {
101
- hookEventName: eventName,
102
- additionalContext
103
- }
104
- }));
98
+ // outputHook(event, additionalContext) inject context into the CALLING session
99
+ // outputHook(event, null, { updatedInput, ... }) → rewrite the tool input before it runs
100
+ // `extra` is merged into hookSpecificOutput, so it can carry updatedInput /
101
+ // permissionDecision / permissionDecisionReason. Pass additionalContext = null
102
+ // to omit it. Back-compatible: existing 2-arg calls behave exactly as before.
103
+ function outputHook(eventName, additionalContext, extra) {
104
+ const hookSpecificOutput = { hookEventName: eventName };
105
+ if (additionalContext != null && additionalContext !== '') {
106
+ hookSpecificOutput.additionalContext = additionalContext;
107
+ }
108
+ if (extra && typeof extra === 'object') {
109
+ Object.assign(hookSpecificOutput, extra);
110
+ }
111
+ console.log(JSON.stringify({ hookSpecificOutput }));
105
112
  }
106
113
 
107
114
  function archiveTask(taskDir, projectRoot) {