ccg-ros2-workflow 2.2.1 → 3.0.0

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 (186) hide show
  1. package/README.md +211 -96
  2. package/README.zh-CN.md +256 -0
  3. package/dist/cli.mjs +15 -15
  4. package/dist/index.d.mts +61 -34
  5. package/dist/index.d.ts +61 -34
  6. package/dist/index.mjs +4 -4
  7. package/dist/shared/ccg-ros2-workflow.Bhm8c7P1.mjs +5154 -0
  8. package/package.json +31 -12
  9. package/templates/codex/AGENTS.md +348 -0
  10. package/templates/codex/agents/ccg-implement.toml +73 -0
  11. package/templates/codex/agents/ccg-research.toml +73 -0
  12. package/templates/codex/agents/ccg-review.toml +82 -0
  13. package/templates/codex/config.toml +21 -0
  14. package/templates/codex/hooks/ccg-workflow.py +253 -0
  15. package/templates/codex/hooks.json +15 -0
  16. package/templates/commands/agents/planner.md +97 -122
  17. package/templates/commands/agents/system-integrator.md +2 -2
  18. package/templates/commands/agents/team-architect.md +97 -0
  19. package/templates/commands/agents/team-qa.md +121 -0
  20. package/templates/commands/agents/team-reviewer.md +112 -0
  21. package/templates/commands/commit.md +30 -1
  22. package/templates/commands/context.md +332 -0
  23. package/templates/commands/go.md +206 -0
  24. package/templates/commands/init.md +1 -1
  25. package/templates/commands/spec-impl.md +41 -21
  26. package/templates/commands/spec-init.md +21 -27
  27. package/templates/commands/spec-plan.md +54 -21
  28. package/templates/commands/spec-research.md +78 -26
  29. package/templates/commands/spec-review.md +20 -16
  30. package/templates/{commands → commands-legacy}/analyze.md +1 -1
  31. package/templates/commands-legacy/backend.md +224 -0
  32. package/templates/commands-legacy/codex-exec.md +411 -0
  33. package/templates/{commands → commands-legacy}/debug.md +1 -1
  34. package/templates/commands-legacy/enhance.md +55 -0
  35. package/templates/{commands → commands-legacy}/feat.md +2 -2
  36. package/templates/commands-legacy/frontend.md +213 -0
  37. package/templates/{commands → commands-legacy}/optimize.md +1 -1
  38. package/templates/{commands → commands-legacy}/plan.md +1 -15
  39. package/templates/{commands → commands-legacy}/team-plan.md +1 -1
  40. package/templates/commands-legacy/team.md +475 -0
  41. package/templates/{commands → commands-legacy}/test.md +1 -1
  42. package/templates/commands-legacy/workflow.md +283 -0
  43. package/templates/engine/model-router.md +123 -0
  44. package/templates/engine/phase-guide.md +207 -0
  45. package/templates/engine/strategies/debug-investigate.md +169 -0
  46. package/templates/engine/strategies/deep-research.md +141 -0
  47. package/templates/engine/strategies/direct-fix.md +108 -0
  48. package/templates/engine/strategies/full-collaborate.md +389 -0
  49. package/templates/engine/strategies/git-action.md +43 -0
  50. package/templates/engine/strategies/guided-develop.md +282 -0
  51. package/templates/engine/strategies/optimize-measure.md +103 -0
  52. package/templates/engine/strategies/quick-implement.md +96 -0
  53. package/templates/engine/strategies/refactor-safely.md +180 -0
  54. package/templates/engine/strategies/review-audit.md +123 -0
  55. package/templates/hooks/session-start.js +100 -0
  56. package/templates/hooks/skill-router.js +144 -0
  57. package/templates/hooks/subagent-context.js +161 -0
  58. package/templates/hooks/task-utils.js +190 -0
  59. package/templates/hooks/workflow-state.js +55 -0
  60. package/templates/output-styles/abyss-command.md +56 -0
  61. package/templates/output-styles/abyss-concise.md +89 -0
  62. package/templates/output-styles/abyss-ritual.md +70 -0
  63. package/templates/output-styles/engineer-professional.md +20 -3
  64. package/templates/output-styles/laowang-engineer.md +2 -2
  65. package/templates/prompts/antigravity/analyzer.md +59 -0
  66. package/templates/prompts/antigravity/architect.md +55 -0
  67. package/templates/prompts/antigravity/builder.md +52 -0
  68. package/templates/prompts/antigravity/debugger.md +48 -0
  69. package/templates/prompts/antigravity/frontend.md +50 -0
  70. package/templates/prompts/antigravity/optimizer.md +40 -0
  71. package/templates/prompts/antigravity/reviewer.md +67 -0
  72. package/templates/prompts/antigravity/tester.md +39 -0
  73. package/templates/prompts/claude/debugger.md +1 -1
  74. package/templates/prompts/claude/reviewer.md +1 -1
  75. package/templates/prompts/codex/analyzer.md +8 -0
  76. package/templates/prompts/codex/architect.md +9 -1
  77. package/templates/prompts/codex/builder.md +61 -0
  78. package/templates/prompts/codex/debugger.md +9 -1
  79. package/templates/prompts/codex/optimizer.md +7 -0
  80. package/templates/prompts/codex/reviewer.md +7 -0
  81. package/templates/prompts/codex/tester.md +8 -1
  82. package/templates/prompts/gemini/analyzer.md +11 -3
  83. package/templates/prompts/gemini/architect.md +10 -2
  84. package/templates/prompts/gemini/debugger.md +8 -0
  85. package/templates/prompts/gemini/frontend.md +10 -2
  86. package/templates/prompts/gemini/optimizer.md +9 -2
  87. package/templates/prompts/gemini/reviewer.md +7 -0
  88. package/templates/prompts/gemini/tester.md +8 -1
  89. package/templates/rules/ccg-skill-routing.md +91 -0
  90. package/templates/rules/ccg-skills.md +65 -0
  91. package/templates/skills/SKILL.md +92 -0
  92. package/templates/skills/domains/ai/SKILL.md +34 -0
  93. package/templates/skills/domains/ai/agent-dev.md +242 -0
  94. package/templates/skills/domains/ai/llm-security.md +288 -0
  95. package/templates/skills/domains/ai/prompt-and-eval.md +279 -0
  96. package/templates/skills/domains/ai/rag-system.md +542 -0
  97. package/templates/skills/domains/architecture/SKILL.md +42 -0
  98. package/templates/skills/domains/architecture/api-design.md +225 -0
  99. package/templates/skills/domains/architecture/caching.md +299 -0
  100. package/templates/skills/domains/architecture/cloud-native.md +285 -0
  101. package/templates/skills/domains/architecture/message-queue.md +329 -0
  102. package/templates/skills/domains/architecture/security-arch.md +297 -0
  103. package/templates/skills/domains/data-engineering/SKILL.md +207 -0
  104. package/templates/skills/domains/development/SKILL.md +46 -0
  105. package/templates/skills/domains/development/cpp.md +369 -0
  106. package/templates/skills/domains/development/go.md +323 -0
  107. package/templates/skills/domains/development/java.md +277 -0
  108. package/templates/skills/domains/development/python.md +487 -0
  109. package/templates/skills/domains/development/rust.md +313 -0
  110. package/templates/skills/domains/development/shell.md +313 -0
  111. package/templates/skills/domains/development/typescript.md +277 -0
  112. package/templates/skills/domains/devops/SKILL.md +39 -0
  113. package/templates/skills/domains/devops/cost-optimization.md +272 -0
  114. package/templates/skills/domains/devops/database.md +217 -0
  115. package/templates/skills/domains/devops/devsecops.md +198 -0
  116. package/templates/skills/domains/devops/git-workflow.md +181 -0
  117. package/templates/skills/domains/devops/observability.md +280 -0
  118. package/templates/skills/domains/devops/performance.md +336 -0
  119. package/templates/skills/domains/devops/testing.md +283 -0
  120. package/templates/skills/domains/infrastructure/SKILL.md +200 -0
  121. package/templates/skills/domains/mobile/SKILL.md +224 -0
  122. package/templates/skills/domains/orchestration/SKILL.md +29 -0
  123. package/templates/skills/domains/orchestration/multi-agent.md +263 -0
  124. package/templates/skills/domains/ros2-control/SKILL.md +206 -0
  125. package/templates/skills/domains/ros2-hardware/SKILL.md +277 -0
  126. package/templates/skills/domains/ros2-manipulation/SKILL.md +237 -0
  127. package/templates/skills/domains/ros2-navigation/SKILL.md +196 -0
  128. package/templates/skills/domains/ros2-perception/SKILL.md +166 -0
  129. package/templates/skills/domains/ros2-upper-app/SKILL.md +50 -0
  130. package/templates/skills/domains/ros2-upper-app/launch-files.md +224 -0
  131. package/templates/skills/domains/ros2-upper-app/parameters.md +192 -0
  132. package/templates/skills/domains/ros2-upper-app/python-nodes.md +249 -0
  133. package/templates/skills/domains/ros2-upper-app/rviz-config.md +158 -0
  134. package/templates/skills/domains/ros2-upper-app/simulation.md +225 -0
  135. package/templates/skills/domains/security/SKILL.md +72 -0
  136. package/templates/skills/domains/security/blue-team.md +436 -0
  137. package/templates/skills/domains/security/code-audit.md +265 -0
  138. package/templates/skills/domains/security/pentest.md +226 -0
  139. package/templates/skills/domains/security/red-team.md +374 -0
  140. package/templates/skills/domains/security/threat-intel.md +372 -0
  141. package/templates/skills/domains/security/vuln-research.md +369 -0
  142. package/templates/skills/orchestration/multi-agent/SKILL.md +533 -0
  143. package/templates/skills/run_skill.js +129 -0
  144. package/templates/skills/scrapling/SKILL.md +98 -0
  145. package/templates/skills/scrapling/references/api-quick-ref.md +127 -0
  146. package/templates/skills/scrapling/references/cookie-vault.md +56 -0
  147. package/templates/skills/scrapling/references/maintenance.md +79 -0
  148. package/templates/skills/scrapling/references/site-patterns.md +86 -0
  149. package/templates/skills/scrapling/references/troubleshooting.md +95 -0
  150. package/templates/skills/scrapling/templates/basic_fetch.py +19 -0
  151. package/templates/skills/scrapling/templates/parse_only.py +15 -0
  152. package/templates/skills/scrapling/templates/session_login.py +19 -0
  153. package/templates/skills/scrapling/templates/stealth_cloudflare.py +28 -0
  154. package/templates/skills/tools/gen-docs/SKILL.md +116 -0
  155. package/templates/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
  156. package/templates/skills/tools/lib/shared.js +98 -0
  157. package/templates/skills/tools/override-refusal/SKILL.md +53 -0
  158. package/templates/skills/tools/override-refusal/agents/openai.yaml +4 -0
  159. package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -0
  160. package/templates/skills/tools/verify-change/SKILL.md +140 -0
  161. package/templates/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
  162. package/templates/skills/tools/verify-module/SKILL.md +127 -0
  163. package/templates/skills/tools/verify-module/scripts/module_scanner.js +171 -0
  164. package/templates/skills/tools/verify-quality/SKILL.md +160 -0
  165. package/templates/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
  166. package/templates/skills/tools/verify-security/SKILL.md +143 -0
  167. package/templates/skills/tools/verify-security/scripts/security_scanner.js +283 -0
  168. package/templates/spec/guides/index.md +30 -0
  169. package/templates/spec/low-control/index.md +31 -0
  170. package/templates/spec/upper-app/index.md +31 -0
  171. package/bin/codeagent-wrapper-darwin-amd64 +0 -0
  172. package/bin/codeagent-wrapper-darwin-arm64 +0 -0
  173. package/bin/codeagent-wrapper-linux-amd64 +0 -0
  174. package/bin/codeagent-wrapper-linux-arm64 +0 -0
  175. package/bin/codeagent-wrapper-windows-amd64.exe +0 -0
  176. package/bin/codeagent-wrapper-windows-arm64.exe +0 -0
  177. package/dist/shared/ccg-ros2-workflow.DRytDWqb.mjs +0 -2274
  178. package/templates/commands/backend.md +0 -162
  179. package/templates/commands/enhance.md +0 -36
  180. package/templates/commands/frontend.md +0 -162
  181. package/templates/commands/workflow.md +0 -202
  182. /package/templates/{commands → commands-legacy}/execute.md +0 -0
  183. /package/templates/{commands → commands-legacy}/review.md +0 -0
  184. /package/templates/{commands → commands-legacy}/team-exec.md +0 -0
  185. /package/templates/{commands → commands-legacy}/team-research.md +0 -0
  186. /package/templates/{commands → commands-legacy}/team-review.md +0 -0
@@ -0,0 +1,123 @@
1
+ # Strategy: Review Audit — 代码审查
2
+
3
+ > 适用于代码审查需求,双模型交叉验证,结果分级输出。
4
+
5
+ ## 适用条件
6
+ - 用户请求代码审查
7
+ - 任何复杂度级别
8
+ - 自动检测 git diff 作为审查范围
9
+
10
+ ## 前置加载
11
+
12
+ ```
13
+ Read("~/.claude/.ccg/engine/model-router.md")
14
+ ```
15
+
16
+ ---
17
+
18
+ ## 工作流状态机
19
+
20
+ [phase-state:1-scope]
21
+ 当前阶段:确定审查范围
22
+ 📍 Next: 范围确定后启动双模型审查
23
+ [/phase-state:1-scope]
24
+
25
+ [phase-state:2-review]
26
+ 当前阶段:双模型审查
27
+ Gate: 审查范围已确定 ✓
28
+ 📍 Next: 双模型审查返回后综合报告
29
+ [/phase-state:2-review]
30
+
31
+ [phase-state:3-report]
32
+ 当前阶段:综合报告
33
+ Gate: 双模型审查已返回 ✓
34
+ 📍 Next: 报告输出后等待用户决定
35
+ [/phase-state:3-report]
36
+
37
+ ---
38
+
39
+ ## 阶段详情
40
+
41
+ ### Phase 1: 确定审查范围 [required]
42
+
43
+ 1. 如果用户指定了文件/范围 → 使用指定范围
44
+ 2. 如果未指定 → 自动获取:
45
+ - `git diff HEAD` — 未提交的变更
46
+ - 如果无 diff → `git diff HEAD~1` — 最近一次提交
47
+ - 如果仍无 diff → 询问用户要审查什么
48
+ 3. 读取变更涉及的完整文件(不只是 diff,需要上下文)
49
+
50
+ 输出审查范围:
51
+ ```
52
+ 📋 审查范围
53
+ 变更: [N] 文件,[+M/-K] 行
54
+ 文件: [文件列表]
55
+ ```
56
+
57
+ ### Phase 2: 双模型审查 [required]
58
+
59
+ **Gate check**: 审查范围已确定
60
+
61
+ **并行调用**(`run_in_background: true`):
62
+ - **backend 模型**:reviewer 角色
63
+ ```
64
+ <TASK>
65
+ 需求:审查以下代码变更
66
+ 上下文:[git diff + 完整文件上下文]
67
+ </TASK>
68
+ OUTPUT: 审查发现(按严重度分级:Critical/Warning/Info,每条含:位置、问题、建议)
69
+ ```
70
+ - **frontend 模型**:reviewer 角色(相同格式)
71
+
72
+ 等待双模型返回。
73
+
74
+ ### Phase 3: 综合报告 + 质量关卡
75
+
76
+ **Gate check**: 双模型审查已返回
77
+
78
+ #### 3a. 质量关卡
79
+
80
+ **⛔ 必须逐个调用 Skill,不可跳过:**
81
+ - 调用 Skill `verify-security` — 等待报告
82
+ - 调用 Skill `verify-quality` — 等待报告
83
+
84
+ #### 3b. 综合报告
85
+
86
+ 合并双模型发现 + 质量关卡结果,去重,按严重度分级:
87
+
88
+ ```
89
+ 📋 代码审查报告
90
+
91
+ ## Critical(必须修复)
92
+ 1. [file:line] — [问题描述]
93
+ 建议: [具体修复建议]
94
+ 来源: [backend/frontend/质量关卡]
95
+
96
+ ## Warning(建议修复)
97
+ 1. [file:line] — [问题描述]
98
+ 建议: [具体修复建议]
99
+
100
+ ## Info(供参考)
101
+ 1. [file:line] — [观察/建议]
102
+
103
+ ---
104
+ 总计: [N] Critical, [M] Warning, [K] Info
105
+ ```
106
+
107
+ 如果有 Critical 发现,询问用户是否立即修复(可切换到 `direct-fix` 策略)。
108
+
109
+ #### Spec Evolution(审查完成后执行)
110
+
111
+ 参考 `phase-guide.md § 8 Spec Evolution Protocol` 执行:
112
+ 1. 从审查发现中提炼可复用的编码规范(特别是 Critical/Warning 级反复出现的模式)
113
+ 2. 如有值得记录的经验 → 草拟 Spec 条目,展示给用户确认后追加到 `.ccg/spec/{domain}/index.md`
114
+ 3. 无值得提炼的经验 → 跳过
115
+
116
+ ---
117
+
118
+ ## 铁律
119
+
120
+ - **审查结果必须分级** — 不可笼统说"代码看起来没问题"
121
+ - **双模型必须独立审查** — 交叉验证的价值在于独立性
122
+ - **Critical 必须明确标出** — 不可淡化严重问题
123
+ - **如无发现,明确说明** — "经双模型审查,未发现问题" 优于沉默
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ // CCG Session Start Hook — SessionStart
3
+ // Injects full project context when session starts, clears, or compacts.
4
+
5
+ 'use strict';
6
+
7
+ try {
8
+ const path = require('path');
9
+ const fs = require('fs');
10
+ const {
11
+ findProjectRoot, getActiveTask, readFileSafe,
12
+ detectTechStack, getGitInfo, outputHook
13
+ } = require('./task-utils.js');
14
+
15
+ const cwd = process.env.CLAUDE_PROJECT_DIR || process.cwd();
16
+ const root = findProjectRoot(cwd);
17
+
18
+ if (!root) process.exit(0);
19
+
20
+ const sections = [];
21
+
22
+ // Project info
23
+ const techStack = detectTechStack(root);
24
+ const git = getGitInfo(root);
25
+ sections.push(`<project>
26
+ Tech: ${techStack}
27
+ Branch: ${git.branch}
28
+ Dirty files: ${git.dirtyCount}
29
+ Root: ${root}
30
+ </project>`);
31
+
32
+ // Model routing config
33
+ const configPath = path.join(root, '.ccg', 'config.toml');
34
+ if (fs.existsSync(configPath)) {
35
+ const configRaw = readFileSafe(configPath);
36
+ if (configRaw) {
37
+ const frontendMatch = configRaw.match(/primary\s*=\s*"(\w+)"/);
38
+ const models = frontendMatch ? `Configured (see .ccg/config.toml)` : 'Default (frontend=gemini, backend=codex)';
39
+ sections.push(`<models>${models}</models>`);
40
+ }
41
+ } else {
42
+ sections.push('<models>Default (frontend=gemini, backend=codex)</models>');
43
+ }
44
+
45
+ // Active task
46
+ const task = getActiveTask(root);
47
+ if (task) {
48
+ const taskLines = [
49
+ `<active-task>`,
50
+ `Task: ${task.title || task.id} (${task.status})`,
51
+ `Strategy: ${task.strategy}`,
52
+ `Phase: ${task.currentPhase}`,
53
+ ];
54
+
55
+ if (task.gate) taskLines.push(`⛔ GATE: ${task.gate}`);
56
+ taskLines.push(`Next: ${task.nextAction || 'Continue'}`);
57
+ taskLines.push(`Dir: ${task.dir}`);
58
+
59
+ // Check for plan/prd
60
+ const planPath = path.join(task.dir, 'plan.md');
61
+ const prdPath = path.join(task.dir, 'requirements.md');
62
+ if (fs.existsSync(planPath)) taskLines.push(`Plan: ${planPath}`);
63
+ if (fs.existsSync(prdPath)) taskLines.push(`PRD: ${prdPath}`);
64
+
65
+ taskLines.push('</active-task>');
66
+ sections.push(taskLines.join('\n'));
67
+ } else {
68
+ sections.push('<active-task>No active task. Use /ccg:go to start.</active-task>');
69
+ }
70
+
71
+ // Spec availability
72
+ const specDir = path.join(root, '.ccg', 'spec');
73
+ if (fs.existsSync(specDir)) {
74
+ try {
75
+ const specPaths = [];
76
+ const walk = (dir, prefix) => {
77
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
78
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
79
+ if (entry.isDirectory()) walk(path.join(dir, entry.name), rel);
80
+ else if (entry.name.endsWith('.md')) specPaths.push(rel);
81
+ }
82
+ };
83
+ walk(specDir, '');
84
+ if (specPaths.length > 0) {
85
+ sections.push(`<specs>\nAvailable specs in .ccg/spec/:\n${specPaths.map(p => ` - ${p}`).join('\n')}\n</specs>`);
86
+ }
87
+ } catch { /* silent */ }
88
+ }
89
+
90
+ // Available commands hint
91
+ sections.push(`<commands>
92
+ Key commands: /ccg:go (smart entry), /ccg:commit, /ccg:review
93
+ All /ccg:* commands available. Use /ccg:go for intelligent routing.
94
+ </commands>`);
95
+
96
+ const context = `<ccg-session>\n${sections.join('\n\n')}\n</ccg-session>`;
97
+ outputHook('SessionStart', context);
98
+ } catch {
99
+ process.exit(0);
100
+ }
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ // CCG Skill Router Hook — UserPromptSubmit
3
+ // Detects domain keywords in user message and injects relevant skill content.
4
+ // Fires alongside workflow-state.js on every user prompt.
5
+
6
+ 'use strict';
7
+
8
+ try {
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const { findProjectRoot, outputHook } = require('./task-utils.js');
12
+
13
+ // Read hook input (contains user's message)
14
+ let inputData = '';
15
+ if (!process.stdin.isTTY) {
16
+ inputData = fs.readFileSync(0, 'utf-8');
17
+ }
18
+
19
+ // Extract user message from hook input
20
+ let userMessage = '';
21
+ try {
22
+ const parsed = JSON.parse(inputData);
23
+ userMessage = parsed.message || parsed.content || parsed.prompt || '';
24
+ if (typeof userMessage === 'object') userMessage = JSON.stringify(userMessage);
25
+ } catch {
26
+ userMessage = inputData;
27
+ }
28
+
29
+ if (!userMessage || userMessage.length < 5) process.exit(0);
30
+
31
+ const msgLower = userMessage.toLowerCase();
32
+
33
+ // Keyword → skill file routing table
34
+ const ROUTES = [
35
+ { keywords: ['渗透', '红队', 'pentest', 'exploit', 'c2', '横向', '提权', 'bypass', 'red team'], skill: 'domains/security/red-team.md', name: '红队渗透' },
36
+ { keywords: ['蓝队', '告警', 'ioc', '应急', '取证', 'siem', 'edr', 'blue team', 'incident'], skill: 'domains/security/blue-team.md', name: '蓝队防御' },
37
+ { keywords: ['sqli', 'xss', 'ssrf', 'rce', 'injection', 'owasp', 'web渗透', 'api安全'], skill: 'domains/security/pentest.md', name: 'Web渗透' },
38
+ { keywords: ['代码审计', '污点分析', 'sink', 'source', '危险函数', 'code audit'], skill: 'domains/security/code-audit.md', name: '代码审计' },
39
+ { keywords: ['逆向', 'pwn', 'fuzzing', '栈溢出', '堆溢出', 'rop', 'binary', 'reversing'], skill: 'domains/security/vuln-research.md', name: '漏洞研究' },
40
+ { keywords: ['osint', '威胁情报', '威胁建模', 'att&ck', 'threat', 'threat hunting'], skill: 'domains/security/threat-intel.md', name: '威胁情报' },
41
+ { keywords: ['api设计', 'rest', 'graphql', 'grpc', 'endpoint', 'versioning', 'api design'], skill: 'domains/architecture/api-design.md', name: 'API设计' },
42
+ { keywords: ['缓存', 'redis', 'memcached', 'cache', 'cdn', 'invalidation'], skill: 'domains/architecture/caching.md', name: '缓存架构' },
43
+ { keywords: ['kubernetes', 'docker', 'k8s', '微服务', 'service mesh', 'cloud native'], skill: 'domains/architecture/cloud-native.md', name: '云原生' },
44
+ { keywords: ['kafka', 'rabbitmq', '消息队列', 'event driven', 'pub/sub', 'message queue'], skill: 'domains/architecture/message-queue.md', name: '消息队列' },
45
+ { keywords: ['rag', 'retrieval', '向量', 'embedding', 'chunking', 'vector'], skill: 'domains/ai/rag-system.md', name: 'RAG系统' },
46
+ { keywords: ['ai agent', 'tool use', 'function calling', 'agent框架', 'orchestration'], skill: 'domains/ai/agent-dev.md', name: 'Agent开发' },
47
+ { keywords: ['prompt injection', 'jailbreak', 'guardrail', 'llm安全'], skill: 'domains/ai/llm-security.md', name: 'LLM安全' },
48
+ ];
49
+
50
+ // Find matching skills
51
+ const matched = ROUTES.filter(route =>
52
+ route.keywords.some(kw => msgLower.includes(kw))
53
+ );
54
+
55
+ // ── Model action triggers ──
56
+ // Detect when user wants to use a specific model for a task
57
+ const MODEL_ACTIONS = [
58
+ { keywords: ['codex审查', 'codex 审查', 'codex review', '用codex看', '让codex检查', 'codex检查'], model: 'codex', role: 'reviewer', action: '审查当前代码变更(git diff)' },
59
+ { keywords: ['codex分析', 'codex 分析', 'codex analyze', '用codex分析'], model: 'codex', role: 'analyzer', action: '分析当前项目/代码' },
60
+ { keywords: ['codex调试', 'codex 调试', 'codex debug', '用codex调试'], model: 'codex', role: 'debugger', action: '诊断问题' },
61
+ { keywords: ['codex测试', 'codex 测试', 'codex test', '用codex写测试'], model: 'codex', role: 'tester', action: '生成测试用例' },
62
+ { keywords: ['gemini审查', 'gemini 审查', 'gemini review', '用gemini看', '让gemini检查'], model: 'gemini', role: 'reviewer', action: '审查当前代码变更(git diff)' },
63
+ { keywords: ['gemini分析', 'gemini 分析', 'gemini analyze', '用gemini分析'], model: 'gemini', role: 'analyzer', action: '分析当前项目/代码' },
64
+ { keywords: ['gemini上层应用', 'gemini 上层应用', '用gemini做上层应用'], model: 'gemini', role: 'frontend', action: '上层应用开发分析' },
65
+ { keywords: ['双模型审查', '双模型 审查', '两个模型审查', 'dual review'], model: 'both', role: 'reviewer', action: '双模型交叉审查代码变更' },
66
+ { keywords: ['双模型分析', '双模型 分析', '两个模型分析', 'dual analyze'], model: 'both', role: 'analyzer', action: '双模型并行分析' },
67
+ ];
68
+
69
+ const modelAction = MODEL_ACTIONS.find(a => a.keywords.some(kw => msgLower.includes(kw)));
70
+ if (modelAction) {
71
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
72
+ const wrapperPath = path.join(homeDir, '.claude', 'bin', 'codeagent-wrapper');
73
+
74
+ let actionInstructions;
75
+ if (modelAction.model === 'both') {
76
+ actionInstructions = `<ccg-model-action>
77
+ 用户请求双模型${modelAction.role === 'reviewer' ? '审查' : '分析'}。请立即执行:
78
+
79
+ 1. 获取工作目录: WORKDIR=$(pwd)
80
+ 2. 并行调用两个模型 (run_in_background: true):
81
+
82
+ Low-level Control (codex):
83
+ ${wrapperPath} --progress --backend codex - "$WORKDIR" <<'EOF'
84
+ ROLE_FILE: ${path.join(homeDir, '.claude', '.ccg', 'prompts', 'codex', modelAction.role + '.md')}
85
+ <TASK>${modelAction.action}</TASK>
86
+ EOF
87
+
88
+ Upper-layer Application (gemini):
89
+ ${wrapperPath} --progress --backend gemini - "$WORKDIR" <<'EOF'
90
+ ROLE_FILE: ${path.join(homeDir, '.claude', '.ccg', 'prompts', 'gemini', modelAction.role + '.md')}
91
+ <TASK>${modelAction.action}</TASK>
92
+ EOF
93
+
94
+ 3. 等待结果,综合输出
95
+ </ccg-model-action>`;
96
+ } else {
97
+ actionInstructions = `<ccg-model-action>
98
+ 用户请求使用 ${modelAction.model} 执行${modelAction.action}。请立即执行:
99
+
100
+ 1. 获取工作目录: WORKDIR=$(pwd)
101
+ 2. 调用模型:
102
+
103
+ ${wrapperPath} --progress --backend ${modelAction.model} - "$WORKDIR" <<'EOF'
104
+ ROLE_FILE: ${path.join(homeDir, '.claude', '.ccg', 'prompts', modelAction.model, modelAction.role + '.md')}
105
+ <TASK>${modelAction.action}</TASK>
106
+ EOF
107
+
108
+ 3. 等待结果并输出
109
+ </ccg-model-action>`;
110
+ }
111
+
112
+ outputHook('UserPromptSubmit', actionInstructions);
113
+ process.exit(0);
114
+ }
115
+
116
+ // ── Domain knowledge injection ──
117
+ if (matched.length === 0) process.exit(0);
118
+
119
+ const cwd = process.env.CLAUDE_PROJECT_DIR || process.cwd();
120
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
121
+ const skillsBase = path.join(homeDir, '.claude', 'skills', 'ccg');
122
+
123
+ if (!fs.existsSync(skillsBase)) process.exit(0);
124
+
125
+ const injections = [];
126
+ for (const match of matched.slice(0, 2)) {
127
+ const skillPath = path.join(skillsBase, match.skill);
128
+ if (!fs.existsSync(skillPath)) continue;
129
+
130
+ try {
131
+ const content = fs.readFileSync(skillPath, 'utf-8');
132
+ const lines = content.split('\n');
133
+ const excerpt = lines.slice(0, 120).join('\n');
134
+ injections.push(`## ${match.name} (auto-injected)\n${excerpt}${lines.length > 120 ? '\n...(truncated, full: ' + match.skill + ')' : ''}`);
135
+ } catch { /* silent */ }
136
+ }
137
+
138
+ if (injections.length === 0) process.exit(0);
139
+
140
+ const context = `<ccg-domain-knowledge>\n${injections.join('\n\n---\n\n')}\n</ccg-domain-knowledge>`;
141
+ outputHook('UserPromptSubmit', context);
142
+ } catch {
143
+ process.exit(0);
144
+ }
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ // CCG SubAgent Context Hook — PreToolUse (Bash|Agent matcher)
3
+ // Injects spec + task context when:
4
+ // 1. codeagent-wrapper is about to be called (Bash)
5
+ // 2. Agent Team member is about to be spawned (Agent)
6
+ // Supports role-based filtering: context.jsonl entries with "roles" field
7
+ // are only injected when the agent's detected role matches.
8
+
9
+ 'use strict';
10
+
11
+ try {
12
+ const path = require('path');
13
+ const fs = require('fs');
14
+ const {
15
+ findProjectRoot, getActiveTask, readFileSafe,
16
+ readContextJsonl, outputHook
17
+ } = require('./task-utils.js');
18
+
19
+ let inputData = '';
20
+ if (!process.stdin.isTTY) {
21
+ inputData = fs.readFileSync(0, 'utf-8');
22
+ }
23
+
24
+ let toolInput = {};
25
+ try {
26
+ const parsed = JSON.parse(inputData);
27
+ toolInput = parsed.tool_input || parsed.input || parsed;
28
+ } catch { /* not JSON */ }
29
+
30
+ // Determine trigger type
31
+ const command = toolInput.command || '';
32
+ const teamName = toolInput.team_name || '';
33
+ const agentName = toolInput.name || '';
34
+
35
+ const isCodeagentCall = command.includes('codeagent-wrapper');
36
+ const isTeamSpawn = !!teamName;
37
+
38
+ if (!isCodeagentCall && !isTeamSpawn) {
39
+ process.exit(0);
40
+ }
41
+
42
+ const cwd = process.env.CLAUDE_PROJECT_DIR || process.cwd();
43
+ const root = findProjectRoot(cwd);
44
+ if (!root) process.exit(0);
45
+
46
+ const task = getActiveTask(root);
47
+ if (!task) process.exit(0);
48
+
49
+ // --- Role detection ---
50
+ const ROLE_FILE_MAP = {
51
+ 'reviewer': 'review',
52
+ 'analyzer': 'research',
53
+ 'debugger': 'debug',
54
+ 'tester': 'review',
55
+ 'architect': 'implement',
56
+ 'optimizer': 'implement',
57
+ 'frontend': 'implement'
58
+ };
59
+ const AGENT_NAME_PATTERNS = [
60
+ { pattern: /dev|builder|fix|impl/i, role: 'implement' },
61
+ { pattern: /review|check|audit/i, role: 'review' },
62
+ { pattern: /research|scout|explore|analy/i, role: 'research' },
63
+ { pattern: /debug|diagnos/i, role: 'debug' }
64
+ ];
65
+
66
+ let detectedRole = 'implement'; // default
67
+
68
+ if (isCodeagentCall) {
69
+ const roleMatch = command.match(/ROLE_FILE:.*\/(\w+)\.md/);
70
+ if (roleMatch) {
71
+ detectedRole = ROLE_FILE_MAP[roleMatch[1]] || 'implement';
72
+ }
73
+ } else if (isTeamSpawn && agentName) {
74
+ for (const { pattern, role } of AGENT_NAME_PATTERNS) {
75
+ if (pattern.test(agentName)) {
76
+ detectedRole = role;
77
+ break;
78
+ }
79
+ }
80
+ }
81
+
82
+ const contextParts = [];
83
+
84
+ if (isTeamSpawn) {
85
+ contextParts.push(`<ccg-active-task>
86
+ Active task: ${task.dir}
87
+ Task: ${task.title || task.id} (${task.status})
88
+ Strategy: ${task.strategy}
89
+ Phase: ${task.currentPhase}
90
+ Agent role: ${detectedRole}
91
+ </ccg-active-task>`);
92
+ }
93
+
94
+ // Read context.jsonl with role-based filtering
95
+ const allEntries = readContextJsonl(task.dir);
96
+ const entries = allEntries.filter(entry => {
97
+ if (!entry.roles || !Array.isArray(entry.roles) || entry.roles.length === 0) {
98
+ return true; // no roles field = inject to all
99
+ }
100
+ return entry.roles.includes(detectedRole) || entry.roles.includes('all');
101
+ });
102
+
103
+ if (entries.length > 0) {
104
+ const specContents = [];
105
+ for (const entry of entries) {
106
+ const filePath = path.isAbsolute(entry.file)
107
+ ? entry.file
108
+ : path.join(root, entry.file);
109
+ const content = readFileSafe(filePath);
110
+ if (content) {
111
+ specContents.push(`--- ${entry.file} (${entry.reason || 'context'}) ---\n${content}`);
112
+ }
113
+ }
114
+ if (specContents.length > 0) {
115
+ contextParts.push(`<ccg-specs>\n${specContents.join('\n\n')}\n</ccg-specs>`);
116
+ }
117
+ }
118
+
119
+ // Read PRD and plan (always inject, role-independent)
120
+ const prd = readFileSafe(path.join(task.dir, 'requirements.md'));
121
+ const plan = readFileSafe(path.join(task.dir, 'plan.md'));
122
+
123
+ if (prd || plan) {
124
+ const taskContext = ['<ccg-task-context>'];
125
+ if (prd) {
126
+ const prdSummary = prd.length > 2000 ? prd.substring(0, 2000) + '\n...(truncated)' : prd;
127
+ taskContext.push(`## Requirements\n${prdSummary}`);
128
+ }
129
+ if (plan) {
130
+ const planSummary = plan.length > 3000 ? plan.substring(0, 3000) + '\n...(truncated)' : plan;
131
+ taskContext.push(`## Plan\n${planSummary}`);
132
+ }
133
+ taskContext.push('</ccg-task-context>');
134
+ contextParts.push(taskContext.join('\n'));
135
+ }
136
+
137
+ // Read research files (only for research + implement roles)
138
+ if (detectedRole === 'research' || detectedRole === 'implement') {
139
+ const researchDir = path.join(task.dir, 'research');
140
+ if (fs.existsSync(researchDir)) {
141
+ try {
142
+ const researchFiles = fs.readdirSync(researchDir).filter(f => f.endsWith('.md'));
143
+ if (researchFiles.length > 0) {
144
+ const researchContents = researchFiles.map(f => {
145
+ const content = readFileSafe(path.join(researchDir, f));
146
+ return content ? `--- research/${f} ---\n${content.substring(0, 1500)}` : null;
147
+ }).filter(Boolean);
148
+ if (researchContents.length > 0) {
149
+ contextParts.push(`<ccg-research>\n${researchContents.join('\n\n')}\n</ccg-research>`);
150
+ }
151
+ }
152
+ } catch { /* silent */ }
153
+ }
154
+ }
155
+
156
+ if (contextParts.length === 0) process.exit(0);
157
+
158
+ outputHook('PreToolUse', contextParts.join('\n\n'));
159
+ } catch {
160
+ process.exit(0);
161
+ }