ccbot-cli 2.0.1 → 2.2.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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/bin/adapters/claude.js +150 -0
  3. package/bin/adapters/codex.js +439 -0
  4. package/bin/install.js +583 -349
  5. package/bin/lib/ccline.js +82 -0
  6. package/bin/lib/utils.js +87 -34
  7. package/bin/uninstall.js +48 -0
  8. package/config/AGENTS.md +630 -0
  9. package/config/CLAUDE.md +229 -20
  10. package/config/ccline/config.toml +161 -0
  11. package/config/codex-config.example.toml +22 -0
  12. package/config/settings.example.json +32 -0
  13. package/output-styles/abyss-cultivator.md +399 -0
  14. package/package.json +14 -5
  15. package/skills/SKILL.md +159 -0
  16. package/skills/domains/ai/SKILL.md +34 -0
  17. package/skills/domains/ai/agent-dev.md +242 -0
  18. package/skills/domains/ai/llm-security.md +288 -0
  19. package/skills/domains/ai/prompt-and-eval.md +279 -0
  20. package/skills/domains/ai/rag-system.md +542 -0
  21. package/skills/domains/architecture/SKILL.md +42 -0
  22. package/skills/domains/architecture/api-design.md +225 -0
  23. package/skills/domains/architecture/caching.md +299 -0
  24. package/skills/domains/architecture/cloud-native.md +285 -0
  25. package/skills/domains/architecture/message-queue.md +329 -0
  26. package/skills/domains/architecture/security-arch.md +297 -0
  27. package/skills/domains/data-engineering/SKILL.md +207 -0
  28. package/skills/domains/development/SKILL.md +46 -0
  29. package/skills/domains/development/cpp.md +246 -0
  30. package/skills/domains/development/go.md +323 -0
  31. package/skills/domains/development/java.md +277 -0
  32. package/skills/domains/development/python.md +288 -0
  33. package/skills/domains/development/rust.md +313 -0
  34. package/skills/domains/development/shell.md +313 -0
  35. package/skills/domains/development/typescript.md +277 -0
  36. package/skills/domains/devops/SKILL.md +39 -0
  37. package/skills/domains/devops/cost-optimization.md +272 -0
  38. package/skills/domains/devops/database.md +217 -0
  39. package/skills/domains/devops/devsecops.md +198 -0
  40. package/skills/domains/devops/git-workflow.md +181 -0
  41. package/skills/domains/devops/observability.md +280 -0
  42. package/skills/domains/devops/performance.md +336 -0
  43. package/skills/domains/devops/testing.md +283 -0
  44. package/skills/domains/frontend-design/SKILL.md +38 -0
  45. package/skills/domains/frontend-design/claymorphism/SKILL.md +119 -0
  46. package/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
  47. package/skills/domains/frontend-design/component-patterns.md +202 -0
  48. package/skills/domains/frontend-design/engineering.md +287 -0
  49. package/skills/domains/frontend-design/glassmorphism/SKILL.md +140 -0
  50. package/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
  51. package/skills/domains/frontend-design/liquid-glass/SKILL.md +137 -0
  52. package/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
  53. package/skills/domains/frontend-design/neubrutalism/SKILL.md +143 -0
  54. package/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
  55. package/skills/domains/frontend-design/state-management.md +680 -0
  56. package/skills/domains/frontend-design/ui-aesthetics.md +110 -0
  57. package/skills/domains/frontend-design/ux-principles.md +156 -0
  58. package/skills/domains/infrastructure/SKILL.md +200 -0
  59. package/skills/domains/mobile/SKILL.md +224 -0
  60. package/skills/domains/orchestration/SKILL.md +29 -0
  61. package/skills/domains/orchestration/multi-agent.md +263 -0
  62. package/skills/domains/security/SKILL.md +54 -0
  63. package/skills/domains/security/blue-team.md +436 -0
  64. package/skills/domains/security/code-audit.md +265 -0
  65. package/skills/domains/security/pentest.md +226 -0
  66. package/skills/domains/security/red-team.md +375 -0
  67. package/skills/domains/security/threat-intel.md +372 -0
  68. package/skills/domains/security/vuln-research.md +369 -0
  69. package/skills/orchestration/multi-agent/SKILL.md +493 -0
  70. package/skills/run_skill.js +129 -0
  71. package/skills/tools/gen-docs/SKILL.md +116 -0
  72. package/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
  73. package/skills/tools/lib/shared.js +98 -0
  74. package/skills/tools/verify-change/SKILL.md +140 -0
  75. package/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
  76. package/skills/tools/verify-module/SKILL.md +127 -0
  77. package/skills/tools/verify-module/scripts/module_scanner.js +171 -0
  78. package/skills/tools/verify-quality/SKILL.md +160 -0
  79. package/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
  80. package/skills/tools/verify-security/SKILL.md +143 -0
  81. package/skills/tools/verify-security/scripts/security_scanner.js +283 -0
  82. package/bin/lib/registry.js +0 -61
  83. package/config/.claudeignore +0 -11
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: verify-change
3
+ description: 变更校验关卡。分析代码变更,检测文档同步状态,评估变更影响范围。当魔尊提到变更检查、文档同步、代码审查、提交前检查、diff分析时使用。在设计级变更、重构完成时自动触发。
4
+ license: MIT
5
+ compatibility: node>=18
6
+ user-invocable: true
7
+ disable-model-invocation: false
8
+ allowed-tools: Bash, Read, Grep
9
+ argument-hint: [--mode working|staged|committed]
10
+ ---
11
+
12
+ # ⚖ 校验关卡 · 变更校验
13
+
14
+
15
+ ## 核心原则
16
+
17
+ ```
18
+ 变更 = 代码改动 + 文档更新 + 理由记录
19
+ 无理由的变更是隐患,无记录的变更是灾难
20
+ 每一次变更都是历史,每一个决策都要留痕
21
+ ```
22
+
23
+ ## 自动分析
24
+
25
+ 运行变更分析脚本(跨平台):
26
+
27
+ ```bash
28
+ # 在 skill 目录下运行
29
+ node scripts/change_analyzer.js # 分析工作区变更(默认)
30
+ node scripts/change_analyzer.js --mode staged # 分析暂存区变更
31
+ node scripts/change_analyzer.js --mode committed # 分析已提交变更
32
+ node scripts/change_analyzer.js -v # 详细模式
33
+ node scripts/change_analyzer.js --json # JSON 输出
34
+ ```
35
+
36
+ ## 检测能力
37
+
38
+ ### 自动检测项
39
+
40
+ | 检测项 | 说明 |
41
+ |--------|------|
42
+ | **文件分类** | 自动识别代码/文档/测试/配置文件 |
43
+ | **模块识别** | 识别受影响的模块 |
44
+ | **文档同步** | 检测代码变更是否同步更新文档 |
45
+ | **测试覆盖** | 检测代码变更是否有对应测试 |
46
+ | **影响评估** | 评估变更规模和影响范围 |
47
+
48
+ ### 触发警告的情况
49
+
50
+ - ⚠️ 代码变更 > 50 行但 DESIGN.md 未更新
51
+ - ⚠️ 代码变更 > 30 行但无测试更新
52
+ - ⚠️ 新增文件但 README.md 未更新
53
+ - ⚠️ 配置文件变更未记录
54
+ - ℹ️ 删除文件需确认引用已清理
55
+
56
+ ## 变更前置检查
57
+
58
+ 在修改任何模块前,必须:
59
+
60
+ 1. **读取 README.md** — 理解模块定位
61
+ 2. **读取 DESIGN.md** — 理解现有决策
62
+ 3. **评估影响范围** — 此变更影响哪些部分
63
+ 4. **确认变更理由** — 为什么要改
64
+
65
+ ## 变更后置检查
66
+
67
+ 代码修改完成后,必须:
68
+
69
+ ### README.md 更新检查
70
+
71
+ - [ ] 模块职责是否变化 → 更新职责描述
72
+ - [ ] 依赖关系是否变化 → 更新依赖说明
73
+ - [ ] 使用方式是否变化 → 更新示例代码
74
+
75
+ ### DESIGN.md 更新检查
76
+
77
+ - [ ] 新增设计决策 → 记录决策及理由
78
+ - [ ] 修改现有设计 → 记录变更及原因
79
+ - [ ] 引入新限制 → 更新已知限制
80
+ - [ ] 添加变更记录 → 更新变更历史
81
+
82
+ ## 变更记录格式
83
+
84
+ 在 DESIGN.md 的变更历史中添加:
85
+
86
+ ```markdown
87
+ ## 变更历史
88
+
89
+ ### [日期] - [变更标题]
90
+
91
+ **变更内容**: 简述改了什么
92
+
93
+ **变更理由**: 为什么要改
94
+
95
+ **影响范围**: 影响哪些功能/模块
96
+
97
+ **决策依据**: 为何选择此方案(如适用)
98
+ ```
99
+
100
+ ## 自动触发时机
101
+
102
+ | 场景 | 触发条件 |
103
+ |------|----------|
104
+ | 设计级变更 | 修改架构、接口、数据结构 |
105
+ | 重构完成 | 重构任务完成时 |
106
+ | 代码变更 > 30 行 | 较大规模代码修改 |
107
+ | 提交前 | 代码提交前检查 |
108
+
109
+ ## 校验流程
110
+
111
+ ```
112
+ 1. 运行 change_analyzer.js 自动分析
113
+ 2. 识别变更文件和受影响模块
114
+ 3. 检查文档同步状态
115
+ 4. 评估变更影响
116
+ 5. 输出变更校验报告
117
+ ```
118
+
119
+ ## 校验报告格式
120
+
121
+ ```
122
+ ## 变更校验报告
123
+
124
+ ### 变更概览
125
+ - 变更文件数: N
126
+ - 代码变更行数: +X / -Y
127
+ - 受影响模块: [模块列表]
128
+
129
+ ### 文档同步状态
130
+ - README.md: ✓ 已同步 / ⚠️ 需更新
131
+ - DESIGN.md: ✓ 已同步 / ⚠️ 需更新
132
+
133
+ ### 测试覆盖
134
+ - 测试文件变更: ✓ 有 / ⚠️ 无
135
+
136
+ ### 结论
137
+ 可提交 / 需补充文档后提交
138
+ ```
139
+
140
+ ---
@@ -0,0 +1,289 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { execFileSync } = require("child_process");
5
+ const path = require("path");
6
+ const fs = require("fs");
7
+ const { parseCliArgs, buildReport, hasFatal, DASH } = require(path.join(__dirname, '..', '..', 'lib', 'shared.js'));
8
+
9
+ const CODE_EXT = new Set([".py",".go",".rs",".ts",".js",".jsx",".tsx",".java",".c",".cpp",".h",".hpp"]);
10
+ const DOC_EXT = new Set([".md",".rst",".txt",".adoc"]);
11
+ const TEST_PATTERNS = ["test_","_test.",".test.","spec_","_spec.","/tests/","/test/","/__tests__/"];
12
+ const CONFIG_FILES = new Set(["package.json","pyproject.toml","go.mod","cargo.toml","pom.xml","makefile","dockerfile"]);
13
+ const CONFIG_EXT = new Set([".yaml",".yml",".json",".toml",".ini"]);
14
+
15
+ function normalizePath(p) {
16
+ let s = p.trim();
17
+ if (s.startsWith('"') && s.endsWith('"') && s.length >= 2) {
18
+ s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
19
+ }
20
+ if (s.startsWith("./")) s = s.slice(2);
21
+ return s;
22
+ }
23
+
24
+ function classifyFile(filePath) {
25
+ const ext = path.extname(filePath).toLowerCase();
26
+ const name = path.basename(filePath).toLowerCase();
27
+ const lower = filePath.toLowerCase();
28
+ return {
29
+ path: filePath, type: "modified", additions: 0, deletions: 0,
30
+ is_code: CODE_EXT.has(ext), is_doc: DOC_EXT.has(ext),
31
+ is_test: TEST_PATTERNS.some(p => lower.includes(p)),
32
+ is_config: CONFIG_FILES.has(name) || CONFIG_EXT.has(ext),
33
+ };
34
+ }
35
+
36
+ function parseNameStatusLine(line) {
37
+ const parts = line.split("\t");
38
+ if (parts.length < 2) return null;
39
+ const status = parts[0][0];
40
+ const p = normalizePath(parts[parts.length - 1]);
41
+ if (!p) return null;
42
+ const c = classifyFile(p);
43
+ const map = { A: "added", M: "modified", D: "deleted", R: "renamed" };
44
+ if (map[status]) c.type = map[status];
45
+ return c;
46
+ }
47
+
48
+ function parsePorcelainLine(line) {
49
+ if (line.length < 3) return null;
50
+ const status = line.slice(0, 2);
51
+ let raw = line.slice(3);
52
+ if (!raw) return null;
53
+ if (raw.includes(" -> ")) raw = raw.split(" -> ")[1];
54
+ const p = normalizePath(raw);
55
+ if (!p) return null;
56
+ const c = classifyFile(p);
57
+ if (status.includes("?") || status.includes("A")) c.type = "added";
58
+ else if (status.includes("R")) c.type = "renamed";
59
+ else if (status.includes("M")) c.type = "modified";
60
+ else if (status.includes("D")) c.type = "deleted";
61
+ return c;
62
+ }
63
+
64
+ function git(...args) {
65
+ try { return execFileSync('git', args, { encoding: "utf8", stdio: ["pipe","pipe","pipe"] }); }
66
+ catch { return ""; }
67
+ }
68
+
69
+ function getGitChanges(base = "HEAD~1", target = "HEAD") {
70
+ const changes = [];
71
+ for (const line of git('diff', '--name-status', base, target).split("\n")) {
72
+ if (!line) continue;
73
+ const c = parseNameStatusLine(line);
74
+ if (c) changes.push(c);
75
+ }
76
+ const statMap = {};
77
+ for (const line of git('diff', '--numstat', base, target).split("\n")) {
78
+ if (!line) continue;
79
+ const parts = line.split("\t");
80
+ if (parts.length >= 3) {
81
+ statMap[normalizePath(parts[2])] = [
82
+ parts[0] === "-" ? 0 : parseInt(parts[0], 10),
83
+ parts[1] === "-" ? 0 : parseInt(parts[1], 10),
84
+ ];
85
+ }
86
+ }
87
+ for (const c of changes) {
88
+ if (statMap[c.path]) { [c.additions, c.deletions] = statMap[c.path]; }
89
+ }
90
+ return changes;
91
+ }
92
+
93
+ function getStagedChanges() {
94
+ const changes = [];
95
+ for (const line of git('diff', '--cached', '--name-status').split("\n")) {
96
+ if (!line) continue;
97
+ const c = parseNameStatusLine(line);
98
+ if (c) changes.push(c);
99
+ }
100
+ return changes;
101
+ }
102
+
103
+ function getWorkingChanges() {
104
+ const changes = [];
105
+ for (const line of git('status', '--porcelain').split("\n")) {
106
+ if (!line) continue;
107
+ const c = parsePorcelainLine(line);
108
+ if (c) changes.push(c);
109
+ }
110
+ return changes;
111
+ }
112
+
113
+ function isPathInModule(filePath, mod) {
114
+ const np = normalizePath(filePath);
115
+ if (mod === ".") return !np.includes("/");
116
+ return np === mod || np.startsWith(mod + "/");
117
+ }
118
+
119
+ function identifyModules(changes) {
120
+ const modules = new Set();
121
+ for (const c of changes) {
122
+ const np = normalizePath(c.path);
123
+ const parts = np.split("/").filter(Boolean);
124
+ if (parts.length === 1) { modules.add("."); continue; }
125
+ let found = false;
126
+ for (let i = 0; i < parts.length; i++) {
127
+ const mp = parts.slice(0, i + 1).join("/");
128
+ if (fs.existsSync(path.join(mp, "README.md")) || fs.existsSync(path.join(mp, "DESIGN.md"))) {
129
+ modules.add(mp); found = true; break;
130
+ }
131
+ }
132
+ if (!found && parts.length > 1) modules.add(parts[0]);
133
+ }
134
+ return modules;
135
+ }
136
+
137
+ function checkDocSync(changes, modules) {
138
+ const docStatus = {};
139
+ const issues = [];
140
+ const codeChanges = changes.filter(c => c.is_code && c.type !== "deleted");
141
+ const docPaths = new Set(changes.filter(c => c.is_doc).map(c => normalizePath(c.path)));
142
+
143
+ for (const mod of modules) {
144
+ const readme = normalizePath(mod === "." ? "README.md" : `${mod}/README.md`);
145
+ const design = normalizePath(mod === "." ? "DESIGN.md" : `${mod}/DESIGN.md`);
146
+ const modCode = codeChanges.filter(c => isPathInModule(c.path, mod));
147
+ if (!modCode.length) continue;
148
+ const total = modCode.reduce((s, c) => s + c.additions + c.deletions, 0);
149
+ if (total > 50 && !docPaths.has(design)) {
150
+ issues.push({
151
+ severity: "warning",
152
+ message: `模块 ${mod} 有较大代码变更 (${total} 行),但 DESIGN.md 未更新`,
153
+ related_files: modCode.map(c => c.path)
154
+ });
155
+ docStatus[`${mod}/DESIGN.md`] = false;
156
+ } else {
157
+ docStatus[`${mod}/DESIGN.md`] = true;
158
+ }
159
+ const newFiles = modCode.filter(c => c.type === "added");
160
+ if (newFiles.length && !docPaths.has(readme)) {
161
+ issues.push({
162
+ severity: "info",
163
+ message: `模块 ${mod} 新增了文件,建议更新 README.md`,
164
+ related_files: newFiles.map(c => c.path)
165
+ });
166
+ }
167
+ }
168
+ return { docStatus, issues };
169
+ }
170
+
171
+ function analyzeImpact(changes) {
172
+ const issues = [];
173
+ const code = changes.filter(c => c.is_code && !c.is_test);
174
+ const tests = changes.filter(c => c.is_test);
175
+ if (code.length && !tests.length) {
176
+ const total = code.reduce((s, c) => s + c.additions + c.deletions, 0);
177
+ if (total > 30) {
178
+ issues.push({
179
+ severity: "warning",
180
+ message: `代码变更 ${total} 行,但没有对应的测试更新`,
181
+ related_files: code.map(c => c.path)
182
+ });
183
+ }
184
+ }
185
+ const configs = changes.filter(c => c.is_config);
186
+ if (configs.length) {
187
+ issues.push({
188
+ severity: "info",
189
+ message: "配置文件有变更,请确认是否需要更新文档",
190
+ related_files: configs.map(c => c.path)
191
+ });
192
+ }
193
+ const deleted = changes.filter(c => c.type === "deleted");
194
+ if (deleted.length) {
195
+ issues.push({
196
+ severity: "info",
197
+ message: `删除了 ${deleted.length} 个文件,请确认相关引用已清理`,
198
+ related_files: deleted.map(c => c.path)
199
+ });
200
+ }
201
+ return issues;
202
+ }
203
+
204
+ function analyzeChanges(mode = "working") {
205
+ let changes;
206
+ if (mode === "staged") changes = getStagedChanges();
207
+ else if (mode === "committed") changes = getGitChanges();
208
+ else changes = getWorkingChanges();
209
+
210
+ const issues = [];
211
+ let modules = new Set(), docStatus = {};
212
+ if (changes.length) {
213
+ modules = identifyModules(changes);
214
+ const ds = checkDocSync(changes, modules);
215
+ docStatus = ds.docStatus;
216
+ issues.push(...ds.issues, ...analyzeImpact(changes));
217
+ }
218
+ const passed = !issues.some(i => i.severity === "error");
219
+ const totalAdd = changes.reduce((s, c) => s + c.additions, 0);
220
+ const totalDel = changes.reduce((s, c) => s + c.deletions, 0);
221
+ return { changes, issues, modules, docStatus, passed, totalAdd, totalDel };
222
+ }
223
+
224
+ function formatReport(r, verbose) {
225
+ const fields = {
226
+ '变更文件': r.changes.length,
227
+ '新增行数': `+${r.totalAdd}`,
228
+ '删除行数': `-${r.totalDel}`,
229
+ '受影响模块': [...r.modules].join(", ") || "无",
230
+ '分析结果': r.passed ? "✓ 通过" : "✗ 需要关注",
231
+ };
232
+ let report = buildReport('变更分析报告', fields, r.issues, verbose);
233
+
234
+ if (r.changes.length && verbose) {
235
+ const lines = ["\n" + DASH, "变更文件列表:", DASH];
236
+ const icons = { added: "➕", modified: "📝", deleted: "➖", renamed: "📋" };
237
+ for (const c of r.changes) {
238
+ const tags = [];
239
+ if (c.is_code) tags.push("代码");
240
+ if (c.is_doc) tags.push("文档");
241
+ if (c.is_test) tags.push("测试");
242
+ if (c.is_config) tags.push("配置");
243
+ const t = tags.length ? ` [${tags.join(", ")}]` : "";
244
+ lines.push(` ${icons[c.type] || "📝"} ${c.path}${t} (+${c.additions}/-${c.deletions})`);
245
+ }
246
+ report += '\n' + lines.join('\n');
247
+ }
248
+
249
+ if (Object.keys(r.docStatus).length) {
250
+ const lines = ["\n" + DASH, "文档同步状态:", DASH];
251
+ for (const [doc, synced] of Object.entries(r.docStatus)) {
252
+ lines.push(` ${synced ? "✓" : "✗"} ${doc}`);
253
+ }
254
+ report += '\n' + lines.join('\n');
255
+ }
256
+
257
+ return report;
258
+ }
259
+
260
+ // CLI
261
+ if (require.main === module) {
262
+ const opts = parseCliArgs(process.argv);
263
+ const result = analyzeChanges(opts.mode || "working");
264
+
265
+ if (opts.json) {
266
+ console.log(JSON.stringify({
267
+ passed: result.passed,
268
+ total_additions: result.totalAdd,
269
+ total_deletions: result.totalDel,
270
+ affected_modules: [...result.modules],
271
+ changes: result.changes.map(c => ({
272
+ path: c.path, type: c.type, additions: c.additions,
273
+ deletions: c.deletions, is_code: c.is_code,
274
+ is_doc: c.is_doc, is_test: c.is_test
275
+ })),
276
+ issues: result.issues.map(i => ({
277
+ severity: i.severity, message: i.message,
278
+ related_files: i.related_files,
279
+ })),
280
+ doc_sync_status: result.docStatus,
281
+ }, null, 2));
282
+ } else {
283
+ console.log(formatReport(result, opts.verbose));
284
+ }
285
+
286
+ process.exit(result.passed ? 0 : 1);
287
+ }
288
+
289
+ module.exports = { normalizePath, classifyFile, parsePorcelainLine, parseNameStatusLine, identifyModules };
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: verify-module
3
+ description: 模块完整性校验关卡。扫描目录结构、检测缺失文档、验证代码与文档同步。当魔尊提到模块校验、文档检查、结构完整性、README检查、DESIGN检查时使用。在新建模块完成时自动触发。
4
+ license: MIT
5
+ compatibility: node>=18
6
+ user-invocable: true
7
+ disable-model-invocation: false
8
+ allowed-tools: Bash, Read, Glob
9
+ argument-hint: <模块路径>
10
+ ---
11
+
12
+ # ⚖ 校验关卡 · 模块完整性
13
+
14
+
15
+ ## 核心原则
16
+
17
+ ```
18
+ 模块 = 代码 + README.md + DESIGN.md
19
+ 缺一不可,残缺即异端
20
+ ```
21
+
22
+ ## 自动扫描
23
+
24
+ 运行扫描脚本(跨平台):
25
+
26
+ ```bash
27
+ # 在 verify-module 目录下运行(推荐)
28
+ node scripts/module_scanner.js <模块路径>
29
+ node scripts/module_scanner.js <模块路径> -v # 详细模式
30
+ node scripts/module_scanner.js <模块路径> --json # JSON 输出
31
+ ```
32
+
33
+ ## 校验标准
34
+
35
+ 一个完整的模块必须包含:
36
+
37
+ ```
38
+ module/
39
+ ├── README.md # 必须 - 模块是什么、为什么存在
40
+ ├── DESIGN.md # 必须 - 设计决策、权衡取舍
41
+ ├── src/ # 代码实现
42
+ └── tests/ # 测试用例(如适用)
43
+ ```
44
+
45
+ ## 检测项
46
+
47
+ ### 必须存在
48
+
49
+ | 文件 | 说明 | 缺失后果 |
50
+ |------|------|----------|
51
+ | `README.md` | 模块说明文档 | 🔴 阻断交付 |
52
+ | `DESIGN.md` | 设计决策文档 | 🔴 阻断交付 |
53
+
54
+ ### 推荐存在
55
+
56
+ | 文件/目录 | 说明 | 缺失后果 |
57
+ |-----------|------|----------|
58
+ | `tests/` | 测试目录 | 🟠 警告 |
59
+ | `__init__.py` | Python 包标识 | 🟡 提示 |
60
+ | `.gitignore` | Git 忽略配置 | 🔵 信息 |
61
+
62
+ ### README.md 必须包含
63
+
64
+ - [ ] **模块名称与定位** — 一句话说明是什么
65
+ - [ ] **存在理由** — 为什么需要这个模块
66
+ - [ ] **核心职责** — 做什么、不做什么
67
+ - [ ] **依赖关系** — 依赖谁、被谁依赖
68
+ - [ ] **快速使用** — 最简示例
69
+
70
+ ### DESIGN.md 必须包含
71
+
72
+ - [ ] **设计目标** — 要解决什么问题
73
+ - [ ] **方案选择** — 考虑过哪些方案、为何选当前方案
74
+ - [ ] **关键决策** — 重要的技术决策及理由
75
+ - [ ] **已知限制** — 当前方案的局限性
76
+ - [ ] **变更历史** — 重大变更记录
77
+
78
+ ## 自动触发时机
79
+
80
+ | 场景 | 触发条件 |
81
+ |------|----------|
82
+ | 新建模块 | 模块创建完成时 |
83
+ | 模块重构 | 重构完成时 |
84
+ | 提交前 | 代码提交前检查 |
85
+
86
+ ## 校验流程
87
+
88
+ ```
89
+ 1. 运行 module_scanner.js 自动扫描
90
+ 2. 检查文件结构是否完整
91
+ 3. 检查 README.md 各项是否齐全
92
+ 4. 检查 DESIGN.md 各项是否齐全
93
+ 5. 检查代码与文档描述是否一致
94
+ 6. 输出校验报告
95
+ ```
96
+
97
+ ## 校验报告格式
98
+
99
+ ```
100
+ ## 模块校验报告
101
+
102
+ ### 模块: <模块名>
103
+
104
+ ✓ 通过 | ✗ 未通过
105
+
106
+ ### 文件检查
107
+ - README.md: ✓ 存在 / ✗ 缺失
108
+ - DESIGN.md: ✓ 存在 / ✗ 缺失
109
+ - tests/: ✓ 存在 / ⚠️ 缺失
110
+
111
+ ### 内容检查
112
+ - README 完整性: ✓ 完整 / ⚠️ 缺少 [X, Y, Z]
113
+ - DESIGN 完整性: ✓ 完整 / ⚠️ 缺少 [X, Y, Z]
114
+
115
+ ### 结论
116
+ 可交付 / 需补充后交付
117
+ ```
118
+
119
+ ## 快速修复
120
+
121
+ 如果缺少文档,可使用文档生成器:
122
+
123
+ ```bash
124
+ /gen-docs <模块路径>
125
+ ```
126
+
127
+ ---