code-abyss 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +197 -0
  3. package/bin/install.js +193 -0
  4. package/bin/uninstall.js +42 -0
  5. package/config/AGENTS.md +247 -0
  6. package/config/CLAUDE.md +207 -0
  7. package/config/settings.example.json +27 -0
  8. package/output-styles/abyss-cultivator.md +399 -0
  9. package/package.json +41 -0
  10. package/skills/SKILL.md +115 -0
  11. package/skills/ai/SKILL.md +29 -0
  12. package/skills/ai/agent-dev.md +242 -0
  13. package/skills/ai/llm-security.md +288 -0
  14. package/skills/architecture/SKILL.md +41 -0
  15. package/skills/architecture/api-design.md +225 -0
  16. package/skills/architecture/caching.md +299 -0
  17. package/skills/architecture/cloud-native.md +285 -0
  18. package/skills/architecture/compliance.md +299 -0
  19. package/skills/architecture/data-security.md +184 -0
  20. package/skills/architecture/message-queue.md +329 -0
  21. package/skills/architecture/security-arch.md +210 -0
  22. package/skills/development/SKILL.md +43 -0
  23. package/skills/development/cpp.md +246 -0
  24. package/skills/development/go.md +323 -0
  25. package/skills/development/java.md +277 -0
  26. package/skills/development/python.md +288 -0
  27. package/skills/development/rust.md +313 -0
  28. package/skills/development/shell.md +313 -0
  29. package/skills/development/typescript.md +277 -0
  30. package/skills/devops/SKILL.md +36 -0
  31. package/skills/devops/cost-optimization.md +272 -0
  32. package/skills/devops/database.md +217 -0
  33. package/skills/devops/devsecops.md +198 -0
  34. package/skills/devops/git-workflow.md +181 -0
  35. package/skills/devops/observability.md +280 -0
  36. package/skills/devops/performance.md +273 -0
  37. package/skills/devops/testing.md +186 -0
  38. package/skills/gen-docs/SKILL.md +114 -0
  39. package/skills/gen-docs/scripts/doc_generator.py +491 -0
  40. package/skills/multi-agent/SKILL.md +268 -0
  41. package/skills/run_skill.py +88 -0
  42. package/skills/security/SKILL.md +51 -0
  43. package/skills/security/blue-team.md +379 -0
  44. package/skills/security/code-audit.md +265 -0
  45. package/skills/security/pentest.md +226 -0
  46. package/skills/security/red-team.md +321 -0
  47. package/skills/security/threat-intel.md +322 -0
  48. package/skills/security/vuln-research.md +369 -0
  49. package/skills/tests/README.md +225 -0
  50. package/skills/tests/SUMMARY.md +362 -0
  51. package/skills/tests/__init__.py +3 -0
  52. package/skills/tests/test_change_analyzer.py +558 -0
  53. package/skills/tests/test_doc_generator.py +538 -0
  54. package/skills/tests/test_module_scanner.py +376 -0
  55. package/skills/tests/test_quality_checker.py +516 -0
  56. package/skills/tests/test_security_scanner.py +426 -0
  57. package/skills/verify-change/SKILL.md +138 -0
  58. package/skills/verify-change/scripts/change_analyzer.py +529 -0
  59. package/skills/verify-module/SKILL.md +125 -0
  60. package/skills/verify-module/scripts/module_scanner.py +321 -0
  61. package/skills/verify-quality/SKILL.md +158 -0
  62. package/skills/verify-quality/scripts/quality_checker.py +481 -0
  63. package/skills/verify-security/SKILL.md +141 -0
  64. package/skills/verify-security/scripts/security_scanner.py +368 -0
@@ -0,0 +1,529 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ 变更分析器
4
+ 分析代码变更,检测文档同步状态,评估变更影响
5
+ """
6
+
7
+ import os
8
+ import re
9
+ import sys
10
+ import json
11
+ import subprocess
12
+ from pathlib import Path
13
+ from dataclasses import dataclass, field
14
+ from typing import List, Dict, Optional, Set
15
+ from enum import Enum
16
+
17
+
18
+ class ChangeType(Enum):
19
+ ADDED = "added"
20
+ MODIFIED = "modified"
21
+ DELETED = "deleted"
22
+ RENAMED = "renamed"
23
+
24
+
25
+ class Severity(Enum):
26
+ ERROR = "error"
27
+ WARNING = "warning"
28
+ INFO = "info"
29
+
30
+
31
+ @dataclass
32
+ class FileChange:
33
+ path: str
34
+ change_type: ChangeType
35
+ additions: int = 0
36
+ deletions: int = 0
37
+ is_code: bool = False
38
+ is_doc: bool = False
39
+ is_test: bool = False
40
+ is_config: bool = False
41
+
42
+
43
+ @dataclass
44
+ class Issue:
45
+ severity: Severity
46
+ message: str
47
+ related_files: List[str] = field(default_factory=list)
48
+
49
+
50
+ @dataclass
51
+ class AnalysisResult:
52
+ changes: List[FileChange] = field(default_factory=list)
53
+ issues: List[Issue] = field(default_factory=list)
54
+ affected_modules: Set[str] = field(default_factory=set)
55
+ doc_sync_status: Dict[str, bool] = field(default_factory=dict)
56
+
57
+ @property
58
+ def passed(self) -> bool:
59
+ return not any(i.severity == Severity.ERROR for i in self.issues)
60
+
61
+ @property
62
+ def total_additions(self) -> int:
63
+ return sum(c.additions for c in self.changes)
64
+
65
+ @property
66
+ def total_deletions(self) -> int:
67
+ return sum(c.deletions for c in self.changes)
68
+
69
+
70
+ CODE_EXTENSIONS = {'.py', '.go', '.rs', '.ts', '.js', '.jsx', '.tsx', '.java', '.c', '.cpp', '.h', '.hpp'}
71
+ DOC_EXTENSIONS = {'.md', '.rst', '.txt', '.adoc'}
72
+ TEST_PATTERNS = ['test_', '_test.', '.test.', 'spec_', '_spec.', '/tests/', '/test/', '/__tests__/']
73
+ CONFIG_FILES = {'package.json', 'pyproject.toml', 'go.mod', 'Cargo.toml', 'pom.xml', 'Makefile', 'Dockerfile'}
74
+
75
+
76
+ def classify_file(path: str) -> FileChange:
77
+ """分类文件类型"""
78
+ p = Path(path)
79
+ suffix = p.suffix.lower()
80
+ name = p.name.lower()
81
+
82
+ change = FileChange(path=path, change_type=ChangeType.MODIFIED)
83
+ change.is_code = suffix in CODE_EXTENSIONS
84
+ change.is_doc = suffix in DOC_EXTENSIONS
85
+ change.is_test = any(pattern in path.lower() for pattern in TEST_PATTERNS)
86
+ change.is_config = name in CONFIG_FILES or suffix in {'.yaml', '.yml', '.json', '.toml', '.ini'}
87
+
88
+ return change
89
+
90
+
91
+ def normalize_path(path: str) -> str:
92
+ """规范化相对路径"""
93
+ normalized = path.strip()
94
+
95
+ if normalized.startswith('"') and normalized.endswith('"') and len(normalized) >= 2:
96
+ normalized = normalized[1:-1]
97
+ normalized = normalized.replace('\\"', '"').replace('\\\\', '\\')
98
+
99
+ if normalized.startswith("./"):
100
+ normalized = normalized[2:]
101
+
102
+ return normalized
103
+
104
+
105
+ def parse_name_status_line(line: str) -> Optional[FileChange]:
106
+ """解析 git diff --name-status 输出行"""
107
+ parts = line.split('\t')
108
+ if len(parts) < 2:
109
+ return None
110
+
111
+ status_token = parts[0]
112
+ status = status_token[0]
113
+ path = normalize_path(parts[-1])
114
+
115
+ if not path:
116
+ return None
117
+
118
+ change = classify_file(path)
119
+
120
+ if status == 'A':
121
+ change.change_type = ChangeType.ADDED
122
+ elif status == 'M':
123
+ change.change_type = ChangeType.MODIFIED
124
+ elif status == 'D':
125
+ change.change_type = ChangeType.DELETED
126
+ elif status == 'R':
127
+ change.change_type = ChangeType.RENAMED
128
+
129
+ return change
130
+
131
+
132
+ def parse_porcelain_line(line: str) -> Optional[FileChange]:
133
+ """解析 git status --porcelain 输出行"""
134
+ if len(line) < 3:
135
+ return None
136
+
137
+ status = line[:2]
138
+ raw_path = line[3:] if len(line) > 3 else ""
139
+
140
+ if not raw_path:
141
+ return None
142
+
143
+ if " -> " in raw_path:
144
+ raw_path = raw_path.split(" -> ", 1)[1]
145
+
146
+ path = normalize_path(raw_path)
147
+ if not path:
148
+ return None
149
+
150
+ change = classify_file(path)
151
+
152
+ if '?' in status or 'A' in status:
153
+ change.change_type = ChangeType.ADDED
154
+ elif 'R' in status:
155
+ change.change_type = ChangeType.RENAMED
156
+ elif 'M' in status:
157
+ change.change_type = ChangeType.MODIFIED
158
+ elif 'D' in status:
159
+ change.change_type = ChangeType.DELETED
160
+
161
+ return change
162
+
163
+
164
+ def is_path_in_module(file_path: str, module: str) -> bool:
165
+ """判断文件是否属于模块范围"""
166
+ normalized_path = normalize_path(file_path)
167
+
168
+ if module == ".":
169
+ return len(Path(normalized_path).parts) == 1
170
+
171
+ module_prefix = f"{module}/"
172
+ return normalized_path == module or normalized_path.startswith(module_prefix)
173
+
174
+
175
+ def get_git_changes(base: str = "HEAD~1", target: str = "HEAD") -> List[FileChange]:
176
+ """获取 Git 变更"""
177
+ changes = []
178
+
179
+ try:
180
+ # 获取变更文件列表
181
+ result = subprocess.run(
182
+ ["git", "diff", "--name-status", base, target],
183
+ capture_output=True, text=True, check=True
184
+ )
185
+
186
+ for line in result.stdout.splitlines():
187
+ if not line:
188
+ continue
189
+
190
+ change = parse_name_status_line(line)
191
+ if change:
192
+ changes.append(change)
193
+
194
+ # 获取行数统计
195
+ stat_result = subprocess.run(
196
+ ["git", "diff", "--numstat", base, target],
197
+ capture_output=True, text=True, check=True
198
+ )
199
+
200
+ stat_map = {}
201
+ for line in stat_result.stdout.splitlines():
202
+ if not line:
203
+ continue
204
+ parts = line.split('\t')
205
+ if len(parts) >= 3:
206
+ adds = int(parts[0]) if parts[0] != '-' else 0
207
+ dels = int(parts[1]) if parts[1] != '-' else 0
208
+ stat_map[normalize_path(parts[2])] = (adds, dels)
209
+
210
+ for change in changes:
211
+ if change.path in stat_map:
212
+ change.additions, change.deletions = stat_map[change.path]
213
+
214
+ except subprocess.CalledProcessError:
215
+ pass
216
+ except FileNotFoundError:
217
+ pass
218
+
219
+ return changes
220
+
221
+
222
+ def get_staged_changes() -> List[FileChange]:
223
+ """获取暂存区变更"""
224
+ changes = []
225
+
226
+ try:
227
+ result = subprocess.run(
228
+ ["git", "diff", "--cached", "--name-status"],
229
+ capture_output=True, text=True, check=True
230
+ )
231
+
232
+ for line in result.stdout.splitlines():
233
+ if not line:
234
+ continue
235
+
236
+ change = parse_name_status_line(line)
237
+ if change:
238
+ changes.append(change)
239
+
240
+ except (subprocess.CalledProcessError, FileNotFoundError):
241
+ pass
242
+
243
+ return changes
244
+
245
+
246
+ def get_working_changes() -> List[FileChange]:
247
+ """获取工作区变更"""
248
+ changes = []
249
+
250
+ try:
251
+ result = subprocess.run(
252
+ ["git", "status", "--porcelain"],
253
+ capture_output=True, text=True, check=True
254
+ )
255
+
256
+ for line in result.stdout.splitlines():
257
+ if not line:
258
+ continue
259
+
260
+ change = parse_porcelain_line(line)
261
+ if change:
262
+ changes.append(change)
263
+
264
+ except (subprocess.CalledProcessError, FileNotFoundError):
265
+ pass
266
+
267
+ return changes
268
+
269
+
270
+ def identify_affected_modules(changes: List[FileChange]) -> Set[str]:
271
+ """识别受影响的模块"""
272
+ modules = set()
273
+
274
+ for change in changes:
275
+ normalized_path = normalize_path(change.path)
276
+ parts = Path(normalized_path).parts
277
+
278
+ if len(parts) == 1:
279
+ modules.add(".")
280
+ continue
281
+
282
+ # 查找模块边界(包含 README.md 或 DESIGN.md 的目录)
283
+ for i in range(len(parts)):
284
+ potential_module = Path(*parts[:i+1])
285
+ if (potential_module / "README.md").exists() or (potential_module / "DESIGN.md").exists():
286
+ modules.add(str(potential_module))
287
+ break
288
+ else:
289
+ # 使用顶层目录作为模块
290
+ if len(parts) > 1:
291
+ modules.add(parts[0])
292
+
293
+ return modules
294
+
295
+
296
+ def check_doc_sync(changes: List[FileChange], modules: Set[str]) -> tuple[Dict[str, bool], List[Issue]]:
297
+ """检查文档同步状态"""
298
+ doc_status = {}
299
+ issues = []
300
+
301
+ code_changes = [c for c in changes if c.is_code and c.change_type != ChangeType.DELETED]
302
+ doc_changes = {normalize_path(c.path) for c in changes if c.is_doc}
303
+
304
+ # 检查每个模块
305
+ for module in modules:
306
+ module_path = Path(module)
307
+ readme = normalize_path(str(module_path / "README.md"))
308
+ design = normalize_path(str(module_path / "DESIGN.md"))
309
+
310
+ # 检查模块内是否有代码变更
311
+ module_code_changes = [c for c in code_changes if is_path_in_module(c.path, module)]
312
+
313
+ if module_code_changes:
314
+ # 检查是否有对应的文档更新
315
+ readme_updated = readme in doc_changes
316
+ design_updated = design in doc_changes
317
+
318
+ # 计算变更规模
319
+ total_changes = sum(c.additions + c.deletions for c in module_code_changes)
320
+
321
+ if total_changes > 50 and not design_updated:
322
+ issues.append(Issue(
323
+ severity=Severity.WARNING,
324
+ message=f"模块 {module} 有较大代码变更 ({total_changes} 行),但 DESIGN.md 未更新",
325
+ related_files=[c.path for c in module_code_changes]
326
+ ))
327
+ doc_status[f"{module}/DESIGN.md"] = False
328
+ else:
329
+ doc_status[f"{module}/DESIGN.md"] = True
330
+
331
+ # 新增文件检查
332
+ new_files = [c for c in module_code_changes if c.change_type == ChangeType.ADDED]
333
+ if new_files and not readme_updated:
334
+ issues.append(Issue(
335
+ severity=Severity.INFO,
336
+ message=f"模块 {module} 新增了文件,建议更新 README.md",
337
+ related_files=[c.path for c in new_files]
338
+ ))
339
+
340
+ return doc_status, issues
341
+
342
+
343
+ def analyze_impact(changes: List[FileChange]) -> List[Issue]:
344
+ """分析变更影响"""
345
+ issues = []
346
+
347
+ # 检查是否只改代码不改测试
348
+ code_changes = [c for c in changes if c.is_code and not c.is_test]
349
+ test_changes = [c for c in changes if c.is_test]
350
+
351
+ if code_changes and not test_changes:
352
+ total_code_changes = sum(c.additions + c.deletions for c in code_changes)
353
+ if total_code_changes > 30:
354
+ issues.append(Issue(
355
+ severity=Severity.WARNING,
356
+ message=f"代码变更 {total_code_changes} 行,但没有对应的测试更新",
357
+ related_files=[c.path for c in code_changes]
358
+ ))
359
+
360
+ # 检查配置文件变更
361
+ config_changes = [c for c in changes if c.is_config]
362
+ if config_changes:
363
+ issues.append(Issue(
364
+ severity=Severity.INFO,
365
+ message="配置文件有变更,请确认是否需要更新文档",
366
+ related_files=[c.path for c in config_changes]
367
+ ))
368
+
369
+ # 检查删除操作
370
+ deleted = [c for c in changes if c.change_type == ChangeType.DELETED]
371
+ if deleted:
372
+ issues.append(Issue(
373
+ severity=Severity.INFO,
374
+ message=f"删除了 {len(deleted)} 个文件,请确认相关引用已清理",
375
+ related_files=[c.path for c in deleted]
376
+ ))
377
+
378
+ return issues
379
+
380
+
381
+ def analyze_changes(mode: str = "working") -> AnalysisResult:
382
+ """分析变更"""
383
+ result = AnalysisResult()
384
+
385
+ # 获取变更
386
+ if mode == "staged":
387
+ result.changes = get_staged_changes()
388
+ elif mode == "committed":
389
+ result.changes = get_git_changes()
390
+ else:
391
+ result.changes = get_working_changes()
392
+
393
+ if not result.changes:
394
+ return result
395
+
396
+ # 识别受影响模块
397
+ result.affected_modules = identify_affected_modules(result.changes)
398
+
399
+ # 检查文档同步
400
+ doc_status, doc_issues = check_doc_sync(result.changes, result.affected_modules)
401
+ result.doc_sync_status = doc_status
402
+ result.issues.extend(doc_issues)
403
+
404
+ # 分析影响
405
+ impact_issues = analyze_impact(result.changes)
406
+ result.issues.extend(impact_issues)
407
+
408
+ return result
409
+
410
+
411
+ def format_report(result: AnalysisResult, verbose: bool = False) -> str:
412
+ """格式化分析报告"""
413
+ lines = []
414
+ lines.append("=" * 60)
415
+ lines.append("变更分析报告")
416
+ lines.append("=" * 60)
417
+
418
+ lines.append(f"\n变更文件: {len(result.changes)}")
419
+ lines.append(f"新增行数: +{result.total_additions}")
420
+ lines.append(f"删除行数: -{result.total_deletions}")
421
+ lines.append(f"受影响模块: {', '.join(result.affected_modules) or '无'}")
422
+ lines.append(f"分析结果: {'✓ 通过' if result.passed else '✗ 需要关注'}")
423
+
424
+ if result.changes and verbose:
425
+ lines.append("\n" + "-" * 40)
426
+ lines.append("变更文件列表:")
427
+ lines.append("-" * 40)
428
+
429
+ type_icons = {
430
+ ChangeType.ADDED: "➕",
431
+ ChangeType.MODIFIED: "📝",
432
+ ChangeType.DELETED: "➖",
433
+ ChangeType.RENAMED: "📋"
434
+ }
435
+
436
+ for change in result.changes:
437
+ icon = type_icons[change.change_type]
438
+ tags = []
439
+ if change.is_code:
440
+ tags.append("代码")
441
+ if change.is_doc:
442
+ tags.append("文档")
443
+ if change.is_test:
444
+ tags.append("测试")
445
+ if change.is_config:
446
+ tags.append("配置")
447
+
448
+ tag_str = f" [{', '.join(tags)}]" if tags else ""
449
+ lines.append(f" {icon} {change.path}{tag_str} (+{change.additions}/-{change.deletions})")
450
+
451
+ if result.issues:
452
+ lines.append("\n" + "-" * 40)
453
+ lines.append("问题与建议:")
454
+ lines.append("-" * 40)
455
+
456
+ severity_icons = {"error": "✗", "warning": "⚠", "info": "ℹ"}
457
+
458
+ for issue in result.issues:
459
+ icon = severity_icons[issue.severity.value]
460
+ lines.append(f"\n {icon} [{issue.severity.value.upper()}] {issue.message}")
461
+ if verbose and issue.related_files:
462
+ for f in issue.related_files[:5]:
463
+ lines.append(f" - {f}")
464
+ if len(issue.related_files) > 5:
465
+ lines.append(f" ... 及其他 {len(issue.related_files) - 5} 个文件")
466
+
467
+ if result.doc_sync_status:
468
+ lines.append("\n" + "-" * 40)
469
+ lines.append("文档同步状态:")
470
+ lines.append("-" * 40)
471
+
472
+ for doc, synced in result.doc_sync_status.items():
473
+ icon = "✓" if synced else "✗"
474
+ lines.append(f" {icon} {doc}")
475
+
476
+ lines.append("\n" + "=" * 60)
477
+ return "\n".join(lines)
478
+
479
+
480
+ def main():
481
+ import argparse
482
+
483
+ parser = argparse.ArgumentParser(description="变更分析器")
484
+ parser.add_argument("--mode", choices=["working", "staged", "committed"],
485
+ default="working", help="分析模式")
486
+ parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
487
+ parser.add_argument("--json", action="store_true", help="JSON 格式输出")
488
+
489
+ args = parser.parse_args()
490
+
491
+ result = analyze_changes(args.mode)
492
+
493
+ if args.json:
494
+ output = {
495
+ "passed": result.passed,
496
+ "total_additions": result.total_additions,
497
+ "total_deletions": result.total_deletions,
498
+ "affected_modules": list(result.affected_modules),
499
+ "changes": [
500
+ {
501
+ "path": c.path,
502
+ "type": c.change_type.value,
503
+ "additions": c.additions,
504
+ "deletions": c.deletions,
505
+ "is_code": c.is_code,
506
+ "is_doc": c.is_doc,
507
+ "is_test": c.is_test
508
+ }
509
+ for c in result.changes
510
+ ],
511
+ "issues": [
512
+ {
513
+ "severity": i.severity.value,
514
+ "message": i.message,
515
+ "related_files": i.related_files
516
+ }
517
+ for i in result.issues
518
+ ],
519
+ "doc_sync_status": result.doc_sync_status
520
+ }
521
+ print(json.dumps(output, ensure_ascii=False, indent=2))
522
+ else:
523
+ print(format_report(result, args.verbose))
524
+
525
+ sys.exit(0 if result.passed else 1)
526
+
527
+
528
+ if __name__ == "__main__":
529
+ main()
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: verify-module
3
+ description: 模块完整性校验关卡。扫描目录结构、检测缺失文档、验证代码与文档同步。当魔尊提到模块校验、文档检查、结构完整性、README检查、DESIGN检查时使用。在新建模块完成时自动触发。
4
+ user-invocable: true
5
+ disable-model-invocation: false
6
+ allowed-tools: Bash, Read, Glob
7
+ argument-hint: <模块路径>
8
+ ---
9
+
10
+ # ⚖ 校验关卡 · 模块完整性
11
+
12
+
13
+ ## 核心原则
14
+
15
+ ```
16
+ 模块 = 代码 + README.md + DESIGN.md
17
+ 缺一不可,残缺即异端
18
+ ```
19
+
20
+ ## 自动扫描
21
+
22
+ 运行扫描脚本(跨平台):
23
+
24
+ ```bash
25
+ # 在 verify-module 目录下运行(推荐)
26
+ python scripts/module_scanner.py <模块路径>
27
+ python scripts/module_scanner.py <模块路径> -v # 详细模式
28
+ python scripts/module_scanner.py <模块路径> --json # JSON 输出
29
+ ```
30
+
31
+ ## 校验标准
32
+
33
+ 一个完整的模块必须包含:
34
+
35
+ ```
36
+ module/
37
+ ├── README.md # 必须 - 模块是什么、为什么存在
38
+ ├── DESIGN.md # 必须 - 设计决策、权衡取舍
39
+ ├── src/ # 代码实现
40
+ └── tests/ # 测试用例(如适用)
41
+ ```
42
+
43
+ ## 检测项
44
+
45
+ ### 必须存在
46
+
47
+ | 文件 | 说明 | 缺失后果 |
48
+ |------|------|----------|
49
+ | `README.md` | 模块说明文档 | 🔴 阻断交付 |
50
+ | `DESIGN.md` | 设计决策文档 | 🔴 阻断交付 |
51
+
52
+ ### 推荐存在
53
+
54
+ | 文件/目录 | 说明 | 缺失后果 |
55
+ |-----------|------|----------|
56
+ | `tests/` | 测试目录 | 🟠 警告 |
57
+ | `__init__.py` | Python 包标识 | 🟡 提示 |
58
+ | `.gitignore` | Git 忽略配置 | 🔵 信息 |
59
+
60
+ ### README.md 必须包含
61
+
62
+ - [ ] **模块名称与定位** — 一句话说明是什么
63
+ - [ ] **存在理由** — 为什么需要这个模块
64
+ - [ ] **核心职责** — 做什么、不做什么
65
+ - [ ] **依赖关系** — 依赖谁、被谁依赖
66
+ - [ ] **快速使用** — 最简示例
67
+
68
+ ### DESIGN.md 必须包含
69
+
70
+ - [ ] **设计目标** — 要解决什么问题
71
+ - [ ] **方案选择** — 考虑过哪些方案、为何选当前方案
72
+ - [ ] **关键决策** — 重要的技术决策及理由
73
+ - [ ] **已知限制** — 当前方案的局限性
74
+ - [ ] **变更历史** — 重大变更记录
75
+
76
+ ## 自动触发时机
77
+
78
+ | 场景 | 触发条件 |
79
+ |------|----------|
80
+ | 新建模块 | 模块创建完成时 |
81
+ | 模块重构 | 重构完成时 |
82
+ | 提交前 | 代码提交前检查 |
83
+
84
+ ## 校验流程
85
+
86
+ ```
87
+ 1. 运行 module_scanner.py 自动扫描
88
+ 2. 检查文件结构是否完整
89
+ 3. 检查 README.md 各项是否齐全
90
+ 4. 检查 DESIGN.md 各项是否齐全
91
+ 5. 检查代码与文档描述是否一致
92
+ 6. 输出校验报告
93
+ ```
94
+
95
+ ## 校验报告格式
96
+
97
+ ```
98
+ ## 模块校验报告
99
+
100
+ ### 模块: <模块名>
101
+
102
+ ✓ 通过 | ✗ 未通过
103
+
104
+ ### 文件检查
105
+ - README.md: ✓ 存在 / ✗ 缺失
106
+ - DESIGN.md: ✓ 存在 / ✗ 缺失
107
+ - tests/: ✓ 存在 / ⚠️ 缺失
108
+
109
+ ### 内容检查
110
+ - README 完整性: ✓ 完整 / ⚠️ 缺少 [X, Y, Z]
111
+ - DESIGN 完整性: ✓ 完整 / ⚠️ 缺少 [X, Y, Z]
112
+
113
+ ### 结论
114
+ 可交付 / 需补充后交付
115
+ ```
116
+
117
+ ## 快速修复
118
+
119
+ 如果缺少文档,可使用文档生成器:
120
+
121
+ ```bash
122
+ /gen-docs <模块路径>
123
+ ```
124
+
125
+ ---