ccgx-workflow 1.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 (212) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +469 -0
  3. package/README.zh-CN.md +466 -0
  4. package/bin/ccg.mjs +2 -0
  5. package/dist/cli.d.mts +1 -0
  6. package/dist/cli.d.ts +1 -0
  7. package/dist/cli.mjs +173 -0
  8. package/dist/index.d.mts +1774 -0
  9. package/dist/index.d.ts +1774 -0
  10. package/dist/index.mjs +2029 -0
  11. package/dist/shared/ccgx-workflow.WgUzkiC3.mjs +5248 -0
  12. package/package.json +129 -0
  13. package/templates/commands/agents/assumptions-analyzer.md +129 -0
  14. package/templates/commands/agents/code-fixer.md +292 -0
  15. package/templates/commands/agents/codebase-mapper.md +152 -0
  16. package/templates/commands/agents/debug-session-manager.md +247 -0
  17. package/templates/commands/agents/debugger.md +111 -0
  18. package/templates/commands/agents/eval-auditor.md +171 -0
  19. package/templates/commands/agents/framework-selector.md +152 -0
  20. package/templates/commands/agents/get-current-datetime.md +29 -0
  21. package/templates/commands/agents/init-architect.md +114 -0
  22. package/templates/commands/agents/integration-checker.md +163 -0
  23. package/templates/commands/agents/interface-auditor.md +170 -0
  24. package/templates/commands/agents/nyquist-auditor.md +131 -0
  25. package/templates/commands/agents/pattern-mapper.md +111 -0
  26. package/templates/commands/agents/phase-runner.md +321 -0
  27. package/templates/commands/agents/plan-checker.md +255 -0
  28. package/templates/commands/agents/planner.md +320 -0
  29. package/templates/commands/agents/team-architect.md +186 -0
  30. package/templates/commands/agents/team-qa.md +121 -0
  31. package/templates/commands/agents/team-reviewer.md +157 -0
  32. package/templates/commands/agents/ui-ux-designer.md +573 -0
  33. package/templates/commands/agents/verifier.md +274 -0
  34. package/templates/commands/analyze.md +210 -0
  35. package/templates/commands/autonomous.md +792 -0
  36. package/templates/commands/cancel.md +132 -0
  37. package/templates/commands/clean-branches.md +117 -0
  38. package/templates/commands/codex-exec.md +404 -0
  39. package/templates/commands/commit.md +151 -0
  40. package/templates/commands/context.md +332 -0
  41. package/templates/commands/debate.md +165 -0
  42. package/templates/commands/debug.md +226 -0
  43. package/templates/commands/enhance.md +64 -0
  44. package/templates/commands/execute.md +380 -0
  45. package/templates/commands/init.md +123 -0
  46. package/templates/commands/optimize.md +217 -0
  47. package/templates/commands/plan.md +373 -0
  48. package/templates/commands/result.md +106 -0
  49. package/templates/commands/review.md +338 -0
  50. package/templates/commands/rollback.md +116 -0
  51. package/templates/commands/spec-impl.md +139 -0
  52. package/templates/commands/spec-init.md +101 -0
  53. package/templates/commands/spec-plan.md +210 -0
  54. package/templates/commands/spec-research.md +152 -0
  55. package/templates/commands/spec-review.md +120 -0
  56. package/templates/commands/status.md +206 -0
  57. package/templates/commands/team-exec.md +265 -0
  58. package/templates/commands/test.md +236 -0
  59. package/templates/commands/verify-work.md +338 -0
  60. package/templates/commands/verify.md +66 -0
  61. package/templates/commands/workflow.md +190 -0
  62. package/templates/commands/worktree.md +128 -0
  63. package/templates/hooks/ccg-context-monitor.js +159 -0
  64. package/templates/hooks/ccg-session-state.cjs +510 -0
  65. package/templates/hooks/ccg-statusline.js +142 -0
  66. package/templates/output-styles/abyss-command.md +56 -0
  67. package/templates/output-styles/abyss-concise.md +89 -0
  68. package/templates/output-styles/abyss-cultivator.md +302 -0
  69. package/templates/output-styles/abyss-ritual.md +70 -0
  70. package/templates/output-styles/engineer-professional.md +89 -0
  71. package/templates/output-styles/laowang-engineer.md +127 -0
  72. package/templates/output-styles/nekomata-engineer.md +120 -0
  73. package/templates/output-styles/ojousama-engineer.md +121 -0
  74. package/templates/prompts/claude/analyzer.md +59 -0
  75. package/templates/prompts/claude/architect.md +54 -0
  76. package/templates/prompts/claude/debugger.md +71 -0
  77. package/templates/prompts/claude/optimizer.md +73 -0
  78. package/templates/prompts/claude/reviewer.md +63 -0
  79. package/templates/prompts/claude/tester.md +69 -0
  80. package/templates/prompts/codex/analyzer.md +58 -0
  81. package/templates/prompts/codex/architect.md +54 -0
  82. package/templates/prompts/codex/debugger.md +74 -0
  83. package/templates/prompts/codex/optimizer.md +81 -0
  84. package/templates/prompts/codex/reviewer.md +73 -0
  85. package/templates/prompts/codex/tester.md +62 -0
  86. package/templates/prompts/gemini/analyzer.md +61 -0
  87. package/templates/prompts/gemini/architect.md +55 -0
  88. package/templates/prompts/gemini/debugger.md +78 -0
  89. package/templates/prompts/gemini/frontend.md +64 -0
  90. package/templates/prompts/gemini/optimizer.md +84 -0
  91. package/templates/prompts/gemini/reviewer.md +80 -0
  92. package/templates/prompts/gemini/tester.md +68 -0
  93. package/templates/rules/ccg-skill-routing.md +83 -0
  94. package/templates/rules/ccg-skills.md +71 -0
  95. package/templates/scripts/ccg-phase-runner-launcher.mjs +467 -0
  96. package/templates/scripts/invoke-model.mjs +949 -0
  97. package/templates/scripts/repatch-gemini-plugin.mjs +194 -0
  98. package/templates/skills/SKILL.md +92 -0
  99. package/templates/skills/domains/ai/SKILL.md +35 -0
  100. package/templates/skills/domains/ai/agent-dev.md +242 -0
  101. package/templates/skills/domains/ai/llm-security.md +288 -0
  102. package/templates/skills/domains/ai/prompt-and-eval.md +279 -0
  103. package/templates/skills/domains/ai/rag-system.md +542 -0
  104. package/templates/skills/domains/architecture/SKILL.md +43 -0
  105. package/templates/skills/domains/architecture/api-design.md +225 -0
  106. package/templates/skills/domains/architecture/caching.md +299 -0
  107. package/templates/skills/domains/architecture/cloud-native.md +285 -0
  108. package/templates/skills/domains/architecture/message-queue.md +329 -0
  109. package/templates/skills/domains/architecture/security-arch.md +297 -0
  110. package/templates/skills/domains/data-engineering/SKILL.md +208 -0
  111. package/templates/skills/domains/development/SKILL.md +47 -0
  112. package/templates/skills/domains/development/cpp.md +246 -0
  113. package/templates/skills/domains/development/go.md +323 -0
  114. package/templates/skills/domains/development/java.md +277 -0
  115. package/templates/skills/domains/development/python.md +288 -0
  116. package/templates/skills/domains/development/rust.md +313 -0
  117. package/templates/skills/domains/development/shell.md +313 -0
  118. package/templates/skills/domains/development/typescript.md +277 -0
  119. package/templates/skills/domains/devops/SKILL.md +40 -0
  120. package/templates/skills/domains/devops/cost-optimization.md +272 -0
  121. package/templates/skills/domains/devops/database.md +217 -0
  122. package/templates/skills/domains/devops/devsecops.md +198 -0
  123. package/templates/skills/domains/devops/git-workflow.md +181 -0
  124. package/templates/skills/domains/devops/observability.md +280 -0
  125. package/templates/skills/domains/devops/performance.md +336 -0
  126. package/templates/skills/domains/devops/testing.md +283 -0
  127. package/templates/skills/domains/frontend-design/SKILL.md +244 -0
  128. package/templates/skills/domains/frontend-design/agents/openai.yaml +4 -0
  129. package/templates/skills/domains/frontend-design/claymorphism/SKILL.md +121 -0
  130. package/templates/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
  131. package/templates/skills/domains/frontend-design/component-patterns.md +202 -0
  132. package/templates/skills/domains/frontend-design/engineering.md +287 -0
  133. package/templates/skills/domains/frontend-design/glassmorphism/SKILL.md +142 -0
  134. package/templates/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
  135. package/templates/skills/domains/frontend-design/liquid-glass/SKILL.md +139 -0
  136. package/templates/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
  137. package/templates/skills/domains/frontend-design/neubrutalism/SKILL.md +145 -0
  138. package/templates/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
  139. package/templates/skills/domains/frontend-design/reference/color-and-contrast.md +132 -0
  140. package/templates/skills/domains/frontend-design/reference/interaction-design.md +195 -0
  141. package/templates/skills/domains/frontend-design/reference/motion-design.md +99 -0
  142. package/templates/skills/domains/frontend-design/reference/responsive-design.md +114 -0
  143. package/templates/skills/domains/frontend-design/reference/spatial-design.md +100 -0
  144. package/templates/skills/domains/frontend-design/reference/typography.md +133 -0
  145. package/templates/skills/domains/frontend-design/reference/ux-writing.md +107 -0
  146. package/templates/skills/domains/frontend-design/state-management.md +680 -0
  147. package/templates/skills/domains/frontend-design/ui-aesthetics.md +110 -0
  148. package/templates/skills/domains/frontend-design/ux-principles.md +156 -0
  149. package/templates/skills/domains/infrastructure/SKILL.md +201 -0
  150. package/templates/skills/domains/mobile/SKILL.md +225 -0
  151. package/templates/skills/domains/orchestration/SKILL.md +30 -0
  152. package/templates/skills/domains/orchestration/multi-agent.md +263 -0
  153. package/templates/skills/domains/security/SKILL.md +73 -0
  154. package/templates/skills/domains/security/blue-team.md +436 -0
  155. package/templates/skills/domains/security/code-audit.md +265 -0
  156. package/templates/skills/domains/security/pentest.md +226 -0
  157. package/templates/skills/domains/security/red-team.md +374 -0
  158. package/templates/skills/domains/security/threat-intel.md +372 -0
  159. package/templates/skills/domains/security/vuln-research.md +369 -0
  160. package/templates/skills/impeccable/adapt/SKILL.md +201 -0
  161. package/templates/skills/impeccable/animate/SKILL.md +176 -0
  162. package/templates/skills/impeccable/arrange/SKILL.md +126 -0
  163. package/templates/skills/impeccable/audit/SKILL.md +149 -0
  164. package/templates/skills/impeccable/bolder/SKILL.md +118 -0
  165. package/templates/skills/impeccable/clarify/SKILL.md +185 -0
  166. package/templates/skills/impeccable/colorize/SKILL.md +144 -0
  167. package/templates/skills/impeccable/critique/SKILL.md +203 -0
  168. package/templates/skills/impeccable/critique/reference/cognitive-load.md +106 -0
  169. package/templates/skills/impeccable/critique/reference/heuristics-scoring.md +234 -0
  170. package/templates/skills/impeccable/critique/reference/personas.md +178 -0
  171. package/templates/skills/impeccable/delight/SKILL.md +305 -0
  172. package/templates/skills/impeccable/distill/SKILL.md +123 -0
  173. package/templates/skills/impeccable/extract/SKILL.md +94 -0
  174. package/templates/skills/impeccable/harden/SKILL.md +357 -0
  175. package/templates/skills/impeccable/normalize/SKILL.md +72 -0
  176. package/templates/skills/impeccable/onboard/SKILL.md +248 -0
  177. package/templates/skills/impeccable/optimize/SKILL.md +268 -0
  178. package/templates/skills/impeccable/overdrive/SKILL.md +143 -0
  179. package/templates/skills/impeccable/polish/SKILL.md +205 -0
  180. package/templates/skills/impeccable/quieter/SKILL.md +104 -0
  181. package/templates/skills/impeccable/teach-impeccable/SKILL.md +72 -0
  182. package/templates/skills/impeccable/typeset/SKILL.md +117 -0
  183. package/templates/skills/orchestration/multi-agent/SKILL.md +533 -0
  184. package/templates/skills/run_skill.js +129 -0
  185. package/templates/skills/scrapling/SKILL.md +98 -0
  186. package/templates/skills/scrapling/references/api-quick-ref.md +127 -0
  187. package/templates/skills/scrapling/references/cookie-vault.md +56 -0
  188. package/templates/skills/scrapling/references/maintenance.md +79 -0
  189. package/templates/skills/scrapling/references/site-patterns.md +86 -0
  190. package/templates/skills/scrapling/references/troubleshooting.md +95 -0
  191. package/templates/skills/scrapling/templates/basic_fetch.py +19 -0
  192. package/templates/skills/scrapling/templates/parse_only.py +15 -0
  193. package/templates/skills/scrapling/templates/session_login.py +19 -0
  194. package/templates/skills/scrapling/templates/stealth_cloudflare.py +28 -0
  195. package/templates/skills/tools/extract-learnings/SKILL.md +77 -0
  196. package/templates/skills/tools/forensics/SKILL.md +89 -0
  197. package/templates/skills/tools/gen-docs/SKILL.md +116 -0
  198. package/templates/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
  199. package/templates/skills/tools/health/SKILL.md +121 -0
  200. package/templates/skills/tools/lib/shared.js +98 -0
  201. package/templates/skills/tools/map-codebase/SKILL.md +118 -0
  202. package/templates/skills/tools/override-refusal/SKILL.md +53 -0
  203. package/templates/skills/tools/override-refusal/agents/openai.yaml +4 -0
  204. package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -0
  205. package/templates/skills/tools/verify-change/SKILL.md +143 -0
  206. package/templates/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
  207. package/templates/skills/tools/verify-module/SKILL.md +130 -0
  208. package/templates/skills/tools/verify-module/scripts/module_scanner.js +171 -0
  209. package/templates/skills/tools/verify-quality/SKILL.md +163 -0
  210. package/templates/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
  211. package/templates/skills/tools/verify-security/SKILL.md +146 -0
  212. package/templates/skills/tools/verify-security/scripts/security_scanner.js +283 -0
@@ -0,0 +1,435 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 文档生成器
4
+ * 自动生成/更新 README.md 和 DESIGN.md 骨架
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ // --- Utilities ---
11
+
12
+ function parseGitignore(modPath) {
13
+ const patterns = [];
14
+ const hardcoded = ['node_modules', '.git', '__pycache__', '.vscode', '.idea', 'dist', 'build', '.DS_Store'];
15
+
16
+ // 硬编码常见排除
17
+ hardcoded.forEach(p => patterns.push({ pattern: p, negate: false }));
18
+
19
+ // 解析 .gitignore
20
+ try {
21
+ const gitignorePath = path.join(modPath, '.gitignore');
22
+ const content = fs.readFileSync(gitignorePath, 'utf8');
23
+ content.split('\n').forEach(line => {
24
+ line = line.trim();
25
+ if (line && !line.startsWith('#')) {
26
+ const negate = line.startsWith('!');
27
+ if (negate) line = line.slice(1);
28
+ patterns.push({ pattern: line, negate });
29
+ }
30
+ });
31
+ } catch {}
32
+
33
+ return patterns;
34
+ }
35
+
36
+ function shouldIgnore(filePath, basePath, patterns) {
37
+ const relPath = path.relative(basePath, filePath);
38
+ const parts = relPath.split(path.sep);
39
+ const name = path.basename(filePath);
40
+
41
+ let ignored = false;
42
+ for (const {pattern, negate} of patterns) {
43
+ let match = false;
44
+ const cleanPattern = pattern.replace(/\/$/, '');
45
+
46
+ if (cleanPattern.includes('*')) {
47
+ // 通配符 → 正则:先转义特殊字符,再将 \* 还原为 [^/]*
48
+ const escaped = cleanPattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^/]*');
49
+ const regex = new RegExp('^' + escaped + '$');
50
+ match = regex.test(name) || parts.some(p => regex.test(p));
51
+ } else if (cleanPattern.includes('/')) {
52
+ // 路径匹配:必须从头匹配或完整段匹配
53
+ match = relPath === cleanPattern || relPath.startsWith(cleanPattern + '/');
54
+ } else {
55
+ // 目录/文件名精确匹配
56
+ match = name === cleanPattern || parts.includes(cleanPattern);
57
+ }
58
+
59
+ if (match) ignored = !negate;
60
+ }
61
+ return ignored;
62
+ }
63
+
64
+ function rglob(dir, filter, basePath = dir) {
65
+ const patterns = parseGitignore(basePath);
66
+ const results = [];
67
+
68
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
69
+ const full = path.join(dir, entry.name);
70
+
71
+ if (shouldIgnore(full, basePath, patterns)) continue;
72
+
73
+ if (entry.isDirectory()) {
74
+ results.push(...rglob(full, filter, basePath));
75
+ } else if (!filter || filter(entry.name, full)) {
76
+ results.push(full);
77
+ }
78
+ }
79
+ return results;
80
+ }
81
+
82
+ // --- Language Detection ---
83
+
84
+ const LANG_MAP = {
85
+ '.py': 'Python', '.go': 'Go', '.rs': 'Rust', '.ts': 'TypeScript',
86
+ '.js': 'JavaScript', '.java': 'Java', '.c': 'C', '.cpp': 'C++',
87
+ };
88
+
89
+ function detectLanguage(modPath) {
90
+ const exts = {};
91
+ try {
92
+ for (const f of rglob(modPath)) {
93
+ const ext = path.extname(f).toLowerCase();
94
+ if (ext) exts[ext] = (exts[ext] || 0) + 1;
95
+ }
96
+ } catch { return 'Unknown'; }
97
+ const codeExts = Object.entries(exts).filter(([k]) => k in LANG_MAP);
98
+ if (codeExts.length) {
99
+ const best = codeExts.reduce((a, b) => b[1] > a[1] ? b : a);
100
+ return LANG_MAP[best[0]] || 'Unknown';
101
+ }
102
+ return 'Unknown';
103
+ }
104
+
105
+ // --- Python AST-lite extraction via regex ---
106
+
107
+ function analyzePythonModule(modPath) {
108
+ const info = makeInfo(modPath, 'Python');
109
+ const pyFiles = rglob(modPath, (name) => name.endsWith('.py'));
110
+ info.files = pyFiles.map(f => path.relative(modPath, f));
111
+
112
+ for (const pyFile of pyFiles) {
113
+ const basename = path.basename(pyFile);
114
+ if (basename.startsWith('test_') || basename.includes('_test')) continue;
115
+ let content;
116
+ try { content = fs.readFileSync(pyFile, 'utf-8'); } catch { continue; }
117
+
118
+ // Module docstring (triple-quoted at top)
119
+ if (!info.description) {
120
+ const docM = content.match(/^(?:#[^\n]*\n)*\s*(?:"""([\s\S]*?)"""|'''([\s\S]*?)''')/);
121
+ if (docM) info.description = (docM[1] || docM[2]).split('\n')[0].trim();
122
+ }
123
+
124
+ const rel = path.relative(modPath, pyFile);
125
+
126
+ // Functions
127
+ for (const m of content.matchAll(/^def\s+([A-Za-z]\w*)\s*\(/gm)) {
128
+ info.functions.push({ name: m[1], file: rel, doc: '' });
129
+ }
130
+ // Classes
131
+ for (const m of content.matchAll(/^class\s+([A-Za-z]\w*)\s*[:(]/gm)) {
132
+ info.classes.push({ name: m[1], file: rel, doc: '' });
133
+ }
134
+
135
+ // Entry points
136
+ if (['main.py', '__main__.py', 'cli.py', 'app.py'].includes(basename)) {
137
+ info.entry_points.push(rel);
138
+ }
139
+ }
140
+
141
+ // Dependencies
142
+ const reqPath = path.join(modPath, 'requirements.txt');
143
+ try {
144
+ const content = fs.readFileSync(reqPath, 'utf-8');
145
+ for (const line of content.split('\n')) {
146
+ const trimmed = line.trim();
147
+ if (trimmed && !trimmed.startsWith('#')) {
148
+ info.dependencies.push(trimmed.split(/[=><]/)[0]);
149
+ }
150
+ }
151
+ } catch {}
152
+
153
+ return info;
154
+ }
155
+
156
+ // --- Generic analysis (regex fallback) ---
157
+
158
+ const LANG_PATTERNS = {
159
+ 'Go': [/^\s*func\s+(\w+)/, /^\s*type\s+(\w+)\s+struct\b/],
160
+ 'Rust': [/^\s*(?:pub\s+)?fn\s+(\w+)/, /^\s*(?:pub\s+)?struct\s+(\w+)/],
161
+ 'TypeScript': [/^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)/, /^\s*(?:export\s+)?class\s+(\w+)/],
162
+ 'JavaScript': [/^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)/, /^\s*(?:export\s+)?class\s+(\w+)/],
163
+ 'Java': [/^\s*(?:public|private|protected)?\s*(?:static\s+)?\w+\s+(\w+)\s*\(/,
164
+ /^\s*(?:public\s+)?class\s+(\w+)/],
165
+ 'C++': [/^\s*(?:\w+\s+)+(\w+)\s*\([^;]*$/, /^\s*class\s+(\w+)/],
166
+ 'C': [/^\s*(?:\w+\s+)+(\w+)\s*\([^;]*$/, null],
167
+ };
168
+
169
+ const CODE_EXTS = new Set(['.py', '.go', '.rs', '.ts', '.js', '.java', '.c', '.cpp']);
170
+
171
+ function analyzeModule(modPath) {
172
+ const language = detectLanguage(modPath);
173
+ if (language === 'Python') return analyzePythonModule(modPath);
174
+
175
+ const info = makeInfo(modPath, language);
176
+ const [funcPat, clsPat] = LANG_PATTERNS[language] || [null, null];
177
+
178
+ try {
179
+ for (const f of rglob(modPath)) {
180
+ if (!CODE_EXTS.has(path.extname(f).toLowerCase())) continue;
181
+ const rel = path.relative(modPath, f);
182
+ info.files.push(rel);
183
+
184
+ if (!funcPat && !clsPat) continue;
185
+ let content;
186
+ try { content = fs.readFileSync(f, 'utf-8'); } catch { continue; }
187
+ for (const line of content.split('\n')) {
188
+ if (funcPat) {
189
+ const m = line.match(funcPat);
190
+ if (m && !m[1].startsWith('_')) info.functions.push({ name: m[1], file: rel, doc: '' });
191
+ }
192
+ if (clsPat) {
193
+ const m = line.match(clsPat);
194
+ if (m && !m[1].startsWith('_')) info.classes.push({ name: m[1], file: rel, doc: '' });
195
+ }
196
+ }
197
+ }
198
+ } catch {}
199
+
200
+ return info;
201
+ }
202
+
203
+ function makeInfo(modPath, language) {
204
+ return {
205
+ name: path.basename(modPath), path: modPath, description: '', language,
206
+ files: [], functions: [], classes: [], dependencies: [], entry_points: [],
207
+ };
208
+ }
209
+
210
+ // --- README Generation ---
211
+
212
+ function generateReadme(info) {
213
+ const L = [];
214
+ L.push(`# ${info.name}`, '');
215
+ if (info.description) {
216
+ L.push(info.description);
217
+ } else {
218
+ L.push('> 请在此描述模块的核心功能、解决的问题和主要用途。');
219
+ L.push('> 例如:本模块提供 X 功能,用于解决 Y 问题。');
220
+ }
221
+ L.push('', '## 概述', '', '<!-- 描述这个模块是什么,解决什么问题 -->', '');
222
+ L.push('## 特性', '', '<!-- 列出模块的主要特性,每项应包含简短描述 -->', '');
223
+ L.push('- **特性1**: 请描述第一个主要特性');
224
+ L.push('- **特性2**: 请描述第二个主要特性');
225
+ L.push('- **特性3**: 请描述第三个主要特性', '');
226
+
227
+ if (info.dependencies.length) {
228
+ L.push('## 依赖', '', '```');
229
+ info.dependencies.slice(0, 10).forEach(d => L.push(d));
230
+ if (info.dependencies.length > 10) L.push(`# ... 及其他 ${info.dependencies.length - 10} 个依赖`);
231
+ L.push('```', '');
232
+ }
233
+
234
+ L.push('## 使用方法', '');
235
+ if (info.entry_points.length) {
236
+ L.push('### 运行', '', '```bash');
237
+ const cmds = {
238
+ Python: `python -m ${info.name}`, Go: 'go run ./cmd/main.go',
239
+ Rust: 'cargo run', TypeScript: 'npm start', JavaScript: 'npm start'
240
+ };
241
+ L.push(cmds[info.language] || `# 请根据 ${info.language} 项目结构添加运行命令`);
242
+ L.push('```', '');
243
+ }
244
+
245
+ L.push('### 示例', '');
246
+ const EXAMPLES = {
247
+ Python: `from ${info.name.toLowerCase()} import main\n\n` +
248
+ `# 初始化\nobj = main()\n\n# 执行操作\nresult = obj.process()\nprint(result)`,
249
+ Go: `package main\n\nimport "${info.name.toLowerCase()}"\n\nfunc main() {\n` +
250
+ ` // 初始化\n obj := ${info.name.toLowerCase()}.New()\n` +
251
+ `\n // 执行操作\n result := obj.Process()\n println(result)\n}`,
252
+ Rust: `use ${info.name.toLowerCase()}::*;\n\nfn main() {\n` +
253
+ ` // 初始化\n let obj = Object::new();\n\n` +
254
+ ` // 执行操作\n let result = obj.process();\n` +
255
+ ` println!("{}", result);\n}`,
256
+ TypeScript: `import { main } from "./${info.name.toLowerCase()}";\n\n` +
257
+ `// 初始化\nconst obj = new main();\n\n` +
258
+ `// 执行操作\nconst result = obj.process();\nconsole.log(result);`,
259
+ JavaScript: `const { main } = require("./${info.name.toLowerCase()}");\n\n` +
260
+ `// 初始化\nconst obj = new main();\n\n` +
261
+ `// 执行操作\nconst result = obj.process();\nconsole.log(result);`,
262
+ };
263
+ if (EXAMPLES[info.language]) {
264
+ L.push('```' + info.language.toLowerCase(), EXAMPLES[info.language], '```');
265
+ } else {
266
+ L.push('```' + info.language.toLowerCase());
267
+ L.push(`<!-- 请根据 ${info.language} 语言特性提供使用示例 -->`);
268
+ L.push(`<!-- 示例应包含:初始化、基本操作、结果处理 -->`);
269
+ L.push('```');
270
+ }
271
+ L.push('');
272
+
273
+ if (info.classes.length || info.functions.length) {
274
+ L.push('## API 概览', '');
275
+ if (info.classes.length) {
276
+ L.push('### 类', '', '| 类名 | 描述 |', '|------|------|');
277
+ info.classes.slice(0, 10).forEach(c => L.push(`| \`${c.name}\` | ${c.doc || '请补充此类的功能描述'} |`));
278
+ L.push('');
279
+ }
280
+ if (info.functions.length) {
281
+ L.push('### 函数', '', '| 函数 | 描述 |', '|------|------|');
282
+ info.functions.slice(0, 10).forEach(f => L.push(`| \`${f.name}()\` | ${f.doc || '请补充此函数的功能描述'} |`));
283
+ L.push('');
284
+ }
285
+ }
286
+
287
+ L.push('## 目录结构', '', '```', `${info.name}/`);
288
+ info.files.sort().slice(0, 15).forEach(f => L.push(`├── ${f}`));
289
+ if (info.files.length > 15) L.push(`└── ... (${info.files.length - 15} more files)`);
290
+ L.push('```', '');
291
+ L.push('## 相关文档', '', '- [设计文档](DESIGN.md)', '');
292
+ return L.join('\n');
293
+ }
294
+
295
+ // --- DESIGN Generation ---
296
+
297
+ function generateDesign(info) {
298
+ const today = new Date().toISOString().slice(0, 10);
299
+ const L = [];
300
+ L.push(`# ${info.name} 设计文档`, '');
301
+ L.push('## 设计概述', '', '### 目标', '', '<!-- 这个模块要解决什么问题? -->', '');
302
+ L.push('### 非目标', '', '<!-- 这个模块明确不做什么? -->', '');
303
+ L.push('## 架构设计', '', '### 整体架构', '', '```');
304
+ L.push('┌─────────────────────────────────────┐');
305
+ L.push('│ 请在此绘制模块的整体架构图 │');
306
+ L.push('│ 包括主要组件、数据流、依赖关系 │');
307
+ L.push('│ 可使用 ASCII 图或 Mermaid 图表 │');
308
+ L.push('└─────────────────────────────────────┘');
309
+ L.push('```', '');
310
+ L.push('### 核心组件', '');
311
+ if (info.classes.length) {
312
+ info.classes.slice(0, 5).forEach(c => L.push(`- **${c.name}**: ${c.doc || '请描述此组件的职责和功能'}`));
313
+ } else {
314
+ L.push('<!-- 列出模块的核心组件及其职责 -->');
315
+ L.push('- **组件1**: 请描述第一个核心组件的职责');
316
+ L.push('- **组件2**: 请描述第二个核心组件的职责');
317
+ L.push('- **组件3**: 请描述第三个核心组件的职责');
318
+ }
319
+ L.push('');
320
+ L.push('## 设计决策', '', '### 决策记录', '');
321
+ L.push('| 日期 | 决策 | 理由 | 影响 |', '|------|------|------|------|');
322
+ L.push(`| ${today} | 初始设计 | - | - |`, '');
323
+ L.push('### 技术选型', '', `- **语言**: ${info.language}`);
324
+ if (info.dependencies.length) L.push(`- **主要依赖**: ${info.dependencies.slice(0, 5).join(', ')}`);
325
+ L.push('- **理由**: <!-- 请说明为什么选择这些技术栈,包括性能、可维护性、生态等考量 -->', '');
326
+ L.push('## 权衡取舍', '', '### 已知限制', '');
327
+ L.push('<!-- 列出模块的已知限制和约束条件 -->');
328
+ L.push('- **限制1**: 请描述第一个已知限制及其原因');
329
+ L.push('- **限制2**: 请描述第二个已知限制及其原因', '');
330
+ L.push('### 技术债务', '');
331
+ L.push('<!-- 记录有意引入的技术债务、临时方案及其原因 -->');
332
+ L.push('- **债务1**: 描述 | 原因:性能优先 | 计划偿还时间:v2.0', '');
333
+ L.push('## 安全考量', '', '### 威胁模型', '');
334
+ L.push('<!-- 识别潜在的安全威胁,如认证、授权、数据泄露等 -->');
335
+ L.push('- **威胁1**: 请描述潜在威胁及其影响');
336
+ L.push('- **威胁2**: 请描述潜在威胁及其影响', '');
337
+ L.push('### 安全措施', '');
338
+ L.push('<!-- 列出已实施的安全措施,如输入验证、加密、访问控制等 -->');
339
+ L.push('- **措施1**: 请描述已实施的安全措施');
340
+ L.push('- **措施2**: 请描述已实施的安全措施', '');
341
+ L.push('## 变更历史', '', `### ${today} - 初始版本`, '');
342
+ L.push('**变更内容**: 创建模块', '', '**变更理由**: 初始开发', '');
343
+ return L.join('\n');
344
+ }
345
+
346
+ // --- Core: generate_docs ---
347
+
348
+ function generateDocs(targetPath, force) {
349
+ const modPath = path.resolve(targetPath);
350
+ const result = { readme: null, design: null, status: 'success', messages: [] };
351
+
352
+ if (!fs.existsSync(modPath)) {
353
+ result.status = 'error';
354
+ result.messages.push(`路径不存在: ${modPath}`);
355
+ return result;
356
+ }
357
+
358
+ const info = analyzeModule(modPath);
359
+
360
+ const readmePath = path.join(modPath, 'README.md');
361
+ if (fs.existsSync(readmePath) && !force) {
362
+ result.messages.push('README.md 已存在,跳过(使用 --force 覆盖)');
363
+ } else {
364
+ fs.writeFileSync(readmePath, generateReadme(info));
365
+ result.readme = readmePath;
366
+ result.messages.push('已生成 README.md');
367
+ }
368
+
369
+ const designPath = path.join(modPath, 'DESIGN.md');
370
+ if (fs.existsSync(designPath) && !force) {
371
+ result.messages.push('DESIGN.md 已存在,跳过(使用 --force 覆盖)');
372
+ } else {
373
+ fs.writeFileSync(designPath, generateDesign(info));
374
+ result.design = designPath;
375
+ result.messages.push('已生成 DESIGN.md');
376
+ }
377
+
378
+ return result;
379
+ }
380
+
381
+ // --- CLI ---
382
+
383
+ function parseArgs(argv) {
384
+ const args = { path: '.', force: false, json: false, readmeOnly: false, designOnly: false };
385
+ const rest = argv.slice(2);
386
+ const positional = [];
387
+ for (const a of rest) {
388
+ if (a === '-f' || a === '--force') args.force = true;
389
+ else if (a === '--json') args.json = true;
390
+ else if (a === '--readme-only') args.readmeOnly = true;
391
+ else if (a === '--design-only') args.designOnly = true;
392
+ else if (a === '-h' || a === '--help') {
393
+ console.log('Usage: doc_generator.js [path] [-f|--force] [--json] [--readme-only] [--design-only]');
394
+ process.exit(0);
395
+ } else positional.push(a);
396
+ }
397
+ if (positional.length) args.path = positional[0];
398
+ return args;
399
+ }
400
+
401
+ function main() {
402
+ const args = parseArgs(process.argv);
403
+ const result = generateDocs(args.path, args.force);
404
+
405
+ if (args.json) {
406
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
407
+ } else {
408
+ console.log('='.repeat(50));
409
+ console.log('文档生成报告');
410
+ console.log('='.repeat(50));
411
+ for (const msg of result.messages) {
412
+ console.log(` \u2022 ${msg}`);
413
+ }
414
+ console.log('='.repeat(50));
415
+ }
416
+
417
+ process.exitCode = result.status === 'success' ? 0 : 1;
418
+ }
419
+
420
+ if (require.main === module) {
421
+ main();
422
+ }
423
+
424
+ module.exports = {
425
+ parseGitignore,
426
+ shouldIgnore,
427
+ rglob,
428
+ detectLanguage,
429
+ analyzeModule,
430
+ generateReadme,
431
+ generateDesign,
432
+ generateDocs,
433
+ parseArgs,
434
+ main,
435
+ };
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: health
3
+ description: 项目健康度报告。一次性盘点项目工程层面卫生指标:依赖陈旧度 / 已知漏洞 / 文档与代码同步度 / 堆积的 TODO / CLAUDE.md 是否反映现状 / 测试覆盖率。当用户提到 health / 健康度 / 体检 / 项目卫生 / 依赖陈旧 / 漏洞扫描 / 文档同步时使用。
4
+ license: MIT
5
+ user-invocable: true
6
+ disable-model-invocation: false
7
+ allowed-tools: Bash, Read, Grep, Glob, Write
8
+ argument-hint: "[--repair]"
9
+ ---
10
+
11
+ # 🏥 健康度关卡 · 项目体检
12
+
13
+ > v4.1-p18:从 `/ccg:health` 命令迁移为 skill。`/ccg:health` 自动生成路由保留。
14
+
15
+ 一次性盘点项目"是不是在烂掉"。不深入业务正确性,只看**工程层面的卫生指标**:依赖陈旧度、已知漏洞、文档与代码同步度、堆积的 TODO、CLAUDE.md 是否还反映现状、测试覆盖率(如可拿到)。输出 markdown 报告,每项打分 + 给出可执行修复建议。
16
+
17
+ `--repair` 模式:对**安全且确定**的问题(如自动生成的过期文档骨架)询问后修复,绝不擅自动核心代码或依赖。
18
+
19
+ ## 使用方法
20
+
21
+ ```bash
22
+ /ccg:health # 体检 + 报告
23
+ /ccg:health --repair # 体检 + 交互式修复(仅低风险项)
24
+ ```
25
+
26
+ ## 工作流程
27
+
28
+ ### Step 1:识别项目类型
29
+
30
+ 并行检测:
31
+
32
+ ```bash
33
+ ls package.json Cargo.toml go.mod pyproject.toml setup.py Gemfile pom.xml build.gradle 2>/dev/null
34
+ ```
35
+
36
+ 记录所有命中的清单文件,决定后续要跑哪些工具链查询。
37
+
38
+ ### Step 2:六大维度体检
39
+
40
+ #### 维度 A:依赖更新状态
41
+
42
+ 按项目类型选命令:
43
+
44
+ | 项目 | 命令 | 关注 |
45
+ |------|------|------|
46
+ | Node | `pnpm outdated` 或 `npm outdated` | major 落后数 |
47
+ | Rust | `cargo outdated`(如已装) | 同上 |
48
+ | Go | `go list -u -m all` | 同上 |
49
+ | Python | `pip list --outdated` | 同上 |
50
+
51
+ 每条发现 5+ 个 major 落后视为"严重老化"。
52
+
53
+ #### 维度 B:已知漏洞
54
+
55
+ | 项目 | 命令 |
56
+ |------|------|
57
+ | Node | `pnpm audit --audit-level=moderate` |
58
+ | Rust | `cargo audit`(需安装) |
59
+ | Python | `pip-audit`(如可用) |
60
+
61
+ 记录 high/critical 数量。
62
+
63
+ #### 维度 C:文档同步度
64
+
65
+ `git log --since='30.days.ago' -- src/ \| wc -l` vs `git log --since='30.days.ago' -- '*.md' \| wc -l` 比值。代码改动 >> 文档改动 → 文档可能过期。
66
+
67
+ #### 维度 D:堆积 TODO/FIXME
68
+
69
+ ```bash
70
+ grep -rn -E "TODO|FIXME|XXX|HACK" --include="*.{ts,js,py,rs,go,java}" \| wc -l
71
+ ```
72
+
73
+ 按目录聚合 top 5。
74
+
75
+ #### 维度 E:CLAUDE.md 现状
76
+
77
+ 读 `CLAUDE.md` 末尾 `Last Updated`,超 90 天 → 黄牌;超 180 天 → 红牌。检查列出的命令/Agent 数与现在 `npx ccg-workflow` 暴露的是否一致。
78
+
79
+ #### 维度 F:测试覆盖率(可选,如已配 coverage 工具)
80
+
81
+ 读 `coverage/lcov-report/index.html` 或 `coverage/coverage-summary.json` 总行覆盖率。
82
+
83
+ ### Step 3:生成报告
84
+
85
+ 写入 `.context/health-report.md`:
86
+
87
+ ```markdown
88
+ # Project Health Report — <项目名>
89
+
90
+ **生成时间**: <ISO 时间>
91
+ **总评**: A / B / C / D / F
92
+
93
+ ## 维度汇总
94
+ | 维度 | 状态 | 严重项 |
95
+ |------|------|-------|
96
+ | 依赖陈旧 | A | 0 |
97
+ | 已知漏洞 | C | 2 high |
98
+ | 文档同步 | B | - |
99
+ | TODO 堆积 | C | 47 |
100
+ | CLAUDE.md | A | - |
101
+ | 测试覆盖 | B | 78% |
102
+
103
+ ## Top 5 修复优先级
104
+ 1. `pnpm audit fix` — 解决 2 个 high vuln
105
+ 2. ...
106
+ ```
107
+
108
+ ### Step 4(可选):--repair 模式
109
+
110
+ 仅对以下场景询问后执行:
111
+
112
+ - CLAUDE.md `Last Updated` 字段更新
113
+ - 重新 spawn `init-architect` 子代理刷新 CLAUDE.md(用户确认后)
114
+ - 自动跑 `pnpm dedupe` 等纯清理命令
115
+
116
+ **绝不**自动跑 `pnpm update` / `cargo update` / `pip install -U`,这类需要人工 review changelog。
117
+
118
+ ## 输出契约
119
+
120
+ - 主输出:`.context/health-report.md`
121
+ - 终端打印:1 行总评 + 每维度 1 行状态 + 修复优先级
@@ -0,0 +1,98 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * 验证工具共享库
5
+ * 消灭 verify-* 脚本间的重复代码
6
+ */
7
+
8
+ // --- CLI 参数解析 ---
9
+
10
+ function parseCliArgs(argv, extraFlags) {
11
+ const args = argv.slice(2);
12
+ const result = { target: '.', verbose: false, json: false };
13
+ if (extraFlags) Object.assign(result, extraFlags);
14
+
15
+ for (let i = 0; i < args.length; i++) {
16
+ if (args[i] === '-v' || args[i] === '--verbose') result.verbose = true;
17
+ else if (args[i] === '--json') result.json = true;
18
+ else if (args[i] === '-h' || args[i] === '--help') { result.help = true; }
19
+ else if (args[i] === '--mode' && args[i + 1]) { result.mode = args[++i]; }
20
+ else if (args[i] === '--exclude') {
21
+ result.exclude = result.exclude || [];
22
+ while (i + 1 < args.length && !args[i + 1].startsWith('-')) result.exclude.push(args[++i]);
23
+ }
24
+ else if (!args[i].startsWith('-')) result.target = args[i];
25
+ }
26
+ return result;
27
+ }
28
+
29
+ // --- 报告格式化 ---
30
+
31
+ const SEP = '='.repeat(60);
32
+ const DASH = '-'.repeat(40);
33
+ const ICONS = {
34
+ error: '\u2717', warning: '\u26A0', info: '\u2139',
35
+ critical: '\u{1F534}', high: '\u{1F7E0}', medium: '\u{1F7E1}', low: '\u{1F535}'
36
+ };
37
+
38
+ function reportHeader(title, fields) {
39
+ const lines = [SEP, title, SEP];
40
+ for (const [k, v] of Object.entries(fields)) {
41
+ lines.push(`\n${k}: ${v}`);
42
+ }
43
+ return lines;
44
+ }
45
+
46
+ function reportIssues(issues, verbose, groupBy) {
47
+ if (!issues.length) return [];
48
+ const lines = ['\n' + DASH, '问题列表:', DASH];
49
+
50
+ if (groupBy) {
51
+ const groups = {};
52
+ for (const i of issues) (groups[i[groupBy]] || (groups[i[groupBy]] = [])).push(i);
53
+ for (const cat of Object.keys(groups).sort()) {
54
+ const items = groups[cat];
55
+ lines.push(`\n【${cat}】(${items.length} 个)`);
56
+ for (const i of items.slice(0, 10)) {
57
+ lines.push(` ${ICONS[i.severity] || '\u2139'} ` +
58
+ `${i.file_path || ''}${i.line_number ? ':' + i.line_number : ''}`);
59
+ lines.push(` ${i.message}`);
60
+ if (verbose && i.suggestion) lines.push(` \u{1F4A1} ${i.suggestion}`);
61
+ if (verbose && i.recommendation) lines.push(` \u{1F4A1} ${i.recommendation}`);
62
+ }
63
+ if (items.length > 10) lines.push(` ... 及其他 ${items.length - 10} 个问题`);
64
+ }
65
+ } else {
66
+ for (const i of issues) {
67
+ const icon = ICONS[i.severity] || '\u2139';
68
+ lines.push(` ${icon} [${i.severity.toUpperCase()}] ${i.message}`);
69
+ if (i.path && verbose) lines.push(` 路径: ${i.path}`);
70
+ }
71
+ }
72
+ return lines;
73
+ }
74
+
75
+ function reportFooter() { return ['\n' + SEP]; }
76
+
77
+ function buildReport(title, fields, issues, verbose, groupBy) {
78
+ return [...reportHeader(title, fields), ...reportIssues(issues, verbose, groupBy), ...reportFooter()].join('\n');
79
+ }
80
+
81
+ // --- 通用计数 ---
82
+
83
+ function countBySeverity(issues, field) {
84
+ field = field || 'severity';
85
+ const counts = {};
86
+ for (const i of issues) counts[i[field]] = (counts[i[field]] || 0) + 1;
87
+ return counts;
88
+ }
89
+
90
+ function hasFatal(issues, fatalLevels) {
91
+ fatalLevels = fatalLevels || ['error'];
92
+ return issues.some(i => fatalLevels.includes(i.severity));
93
+ }
94
+
95
+ module.exports = {
96
+ parseCliArgs, buildReport, reportHeader, reportIssues,
97
+ reportFooter, countBySeverity, hasFatal, SEP, DASH, ICONS
98
+ };