zco-claude 0.0.8__py3-none-any.whl

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 (34) hide show
  1. ClaudeSettings/DOT.claudeignore +7 -0
  2. ClaudeSettings/README.md +100 -0
  3. ClaudeSettings/commands/generate_changelog.sh +49 -0
  4. ClaudeSettings/commands/show_env +92 -0
  5. ClaudeSettings/commands/zco-clean +164 -0
  6. ClaudeSettings/commands/zco-git-summary +15 -0
  7. ClaudeSettings/commands/zco-git-tag +42 -0
  8. ClaudeSettings/hooks/CHANGELOG.md +157 -0
  9. ClaudeSettings/hooks/README.md +254 -0
  10. ClaudeSettings/hooks/save_chat_plain.py +148 -0
  11. ClaudeSettings/hooks/save_chat_spec.py +398 -0
  12. ClaudeSettings/rules/README.md +270 -0
  13. ClaudeSettings/rules/go/.golangci.yml.template +170 -0
  14. ClaudeSettings/rules/go/GoBuildAutoVersion.v250425.md +95 -0
  15. ClaudeSettings/rules/go/check-standards.sh +128 -0
  16. ClaudeSettings/rules/go/coding-standards.md +973 -0
  17. ClaudeSettings/rules/go/example.go +207 -0
  18. ClaudeSettings/rules/go/go-testing.md +691 -0
  19. ClaudeSettings/rules/go/list-comments.sh +85 -0
  20. ClaudeSettings/settings.sample.json +71 -0
  21. ClaudeSettings/skills/README.md +225 -0
  22. ClaudeSettings/skills/zco-docs-update/SKILL.md +381 -0
  23. ClaudeSettings/skills/zco-help/SKILL.md +601 -0
  24. ClaudeSettings/skills/zco-plan/SKILL.md +661 -0
  25. ClaudeSettings/skills/zco-plan-new/SKILL.md +585 -0
  26. ClaudeSettings/zco-scripts/co-docs-update.sh +150 -0
  27. ClaudeSettings/zco-scripts/test_update_plan_metadata.py +328 -0
  28. ClaudeSettings/zco-scripts/update-plan-metadata.py +324 -0
  29. zco_claude-0.0.8.dist-info/METADATA +190 -0
  30. zco_claude-0.0.8.dist-info/RECORD +34 -0
  31. zco_claude-0.0.8.dist-info/WHEEL +5 -0
  32. zco_claude-0.0.8.dist-info/entry_points.txt +3 -0
  33. zco_claude-0.0.8.dist-info/top_level.txt +1 -0
  34. zco_claude_init.py +1732 -0
@@ -0,0 +1,398 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Claude Code 对话自动保存脚本(增强版)
4
+ 保存完整对话 + 工具调用 + 参考资源
5
+
6
+ Environment Variables:
7
+ - YJ_CLAUDE_CHAT_SAVE_SPEC: Must be "1" to enable this hook
8
+ - YJ_CLAUDE_CHAT_SAVE_DIR: Output directory (default: ${GIT_ROOT}/_.claude_hist)
9
+ """
10
+ import json
11
+ import os
12
+ import sys
13
+ import re
14
+ import subprocess
15
+ from datetime import datetime
16
+ from pathlib import Path
17
+ from typing import List, Dict, Any, Set
18
+
19
+
20
+ def extract_keywords(text: str, max_keywords: int = 3) -> str:
21
+ """从文本中提取关键词"""
22
+ text = re.sub(r'[^\w\s\u4e00-\u9fff]', ' ', text)
23
+ words = text.split()
24
+
25
+ stop_words = {'的', '了', '是', '在', '我', '有', '和', '就', '不', '人', '都', '一', '一个',
26
+ 'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'is', 'are',
27
+ '请', '帮', '我要', '能否', '如何', '什么', '怎么', '吗', '呢'}
28
+
29
+ keywords = []
30
+ for word in words:
31
+ word = word.strip()
32
+ if len(word) >= 2 and word not in stop_words:
33
+ if word not in keywords:
34
+ keywords.append(word)
35
+ if len(keywords) >= max_keywords:
36
+ break
37
+
38
+ if not keywords:
39
+ return "对话记录"
40
+
41
+ return '_'.join(keywords[:max_keywords])
42
+
43
+ def get_git_root(project_dir: Path=None) -> Path:
44
+ """获取当前 Git 仓库根目录"""
45
+ try:
46
+ # 执行 git rev-parse --show-toplevel 命令
47
+ if project_dir:
48
+ result = subprocess.run(
49
+ ['git', '-C', str(project_dir), 'rev-parse', '--show-toplevel'],
50
+ capture_output=True, text=True, check=True
51
+ )
52
+ else:
53
+ result = subprocess.run(
54
+ ['git', 'rev-parse', '--show-toplevel'],
55
+ capture_output=True, text=True, check=True
56
+ )
57
+ return Path(result.stdout.strip())
58
+ except (subprocess.CalledProcessError, FileNotFoundError):
59
+ return Path.cwd()
60
+
61
+ def get_hist_dir(project_dir: Path=None) -> Path:
62
+ """获取历史记录目录"""
63
+ hist_dir_name = os.environ.get('YJ_CLAUDE_CHAT_SAVE_DIR', None)
64
+ git_root = get_git_root(project_dir)
65
+ if not hist_dir_name:
66
+ hist_dir = git_root / '_.claude_hist'
67
+ else:
68
+ hist_dir = os.path.abspath(os.path.join(str(git_root), hist_dir_name))
69
+ hist_dir.mkdir(exist_ok=True)
70
+ return hist_dir
71
+
72
+ def format_message_content(msg_data: Any) -> str:
73
+ """格式化消息内容(支持 Claude Code 格式)"""
74
+ # Claude Code 格式:外层 message 对象包含 role 和 content
75
+ if isinstance(msg_data, dict) and 'message' in msg_data:
76
+ msg_data = msg_data.get('message', {})
77
+
78
+ # 提取 content
79
+ content = msg_data.get('content', msg_data) if isinstance(msg_data, dict) else msg_data
80
+ if not content:
81
+ return ''
82
+ if isinstance(content, str):
83
+ return content
84
+ elif isinstance(content, list):
85
+ parts = []
86
+ for item in content:
87
+ if isinstance(item, dict):
88
+ if item.get('type') == 'text':
89
+ parts.append(item.get('text', ''))
90
+ elif item.get('type') == 'tool_use':
91
+ tool_name = item.get('name', 'unknown')
92
+ parts.append(f"\n[使用工具: {tool_name}]\n")
93
+ elif isinstance(item, str):
94
+ parts.append(item)
95
+ return ''.join(parts)
96
+ return str(content)
97
+
98
+
99
+ def extract_tool_calls(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
100
+ """提取所有工具调用(支持 Claude Code 格式)"""
101
+ tool_calls = []
102
+
103
+ for msg in messages:
104
+ # Claude Code 格式:type 在外层
105
+ msg_type = msg.get('type', '')
106
+ if msg_type != 'assistant':
107
+ continue
108
+
109
+ # 内层 message 对象
110
+ inner_msg = msg.get('message', {})
111
+ content = inner_msg.get('content', [])
112
+ if not isinstance(content, list):
113
+ continue
114
+
115
+ for item in content:
116
+ if isinstance(item, dict) and item.get('type') == 'tool_use':
117
+ tool_calls.append({
118
+ 'name': item.get('name', 'unknown'),
119
+ 'input': item.get('input', {}),
120
+ 'id': item.get('id', '')
121
+ })
122
+
123
+ return tool_calls
124
+
125
+
126
+ def extract_tool_results(messages: List[Dict[str, Any]]) -> Dict[str, Any]:
127
+ """提取工具返回结果(支持 Claude Code 格式)"""
128
+ tool_results = {}
129
+
130
+ for msg in messages:
131
+ # Claude Code 格式:检查外层 type
132
+ msg_type = msg.get('type', '')
133
+ if msg_type != 'user':
134
+ continue
135
+
136
+ # 检查是否有 toolUseResult
137
+ tool_result = msg.get('toolUseResult')
138
+ if tool_result and isinstance(tool_result, dict):
139
+ tool_id = tool_result.get('tool_use_id', '')
140
+ result_content = tool_result.get('content', '')
141
+
142
+ # 解析结果内容
143
+ if isinstance(result_content, list):
144
+ text_parts = []
145
+ for part in result_content:
146
+ if isinstance(part, dict) and part.get('type') == 'text':
147
+ text_parts.append(part.get('text', ''))
148
+ result_content = '\n'.join(text_parts)
149
+
150
+ tool_results[tool_id] = result_content
151
+
152
+ # 也检查内层 message 中的 content
153
+ inner_msg = msg.get('message', {})
154
+ content = inner_msg.get('content', [])
155
+ if not isinstance(content, list):
156
+ continue
157
+
158
+ for item in content:
159
+ if isinstance(item, dict) and item.get('type') == 'tool_result':
160
+ tool_id = item.get('tool_use_id', '')
161
+ result_content = item.get('content', '')
162
+
163
+ # 解析结果内容
164
+ if isinstance(result_content, list):
165
+ text_parts = []
166
+ for part in result_content:
167
+ if isinstance(part, dict) and part.get('type') == 'text':
168
+ text_parts.append(part.get('text', ''))
169
+ result_content = '\n'.join(text_parts)
170
+
171
+ tool_results[tool_id] = result_content
172
+
173
+ return tool_results
174
+
175
+
176
+ def extract_references(tool_calls: List[Dict], tool_results: Dict) -> Set[str]:
177
+ """提取参考资源(URLs、文件路径等)"""
178
+ references = set()
179
+
180
+ # 从工具调用中提取
181
+ for call in tool_calls:
182
+ tool_name = call.get('name', '')
183
+ tool_input = call.get('input', {})
184
+
185
+ # WebFetch 工具
186
+ if tool_name == 'WebFetch' or tool_name == 'WebSearch':
187
+ url = tool_input.get('url', '')
188
+ if url:
189
+ references.add(f"🌐 {url}")
190
+
191
+ # Read 工具
192
+ elif tool_name == 'Read':
193
+ file_path = tool_input.get('file_path', '')
194
+ if file_path:
195
+ references.add(f"📄 {file_path}")
196
+
197
+ # Task 工具(Agent 调用)
198
+ elif tool_name == 'Task':
199
+ agent_type = tool_input.get('subagent_type', '')
200
+ if agent_type:
201
+ references.add(f"🤖 Agent: {agent_type}")
202
+
203
+ # 从工具结果中提取 URLs
204
+ for result in tool_results.values():
205
+ if isinstance(result, str):
206
+ # 提取 http/https URLs
207
+ urls = re.findall(r'https?://[^\s<>"{}|\\^`\[\]]+', result)
208
+ for url in urls:
209
+ references.add(f"🌐 {url}")
210
+
211
+ return references
212
+
213
+
214
+ def parse_transcript(transcript_path: str) -> List[Dict[str, Any]]:
215
+ """解析 Claude Code 的会话文件(JSONL 格式)"""
216
+ messages = []
217
+
218
+ try:
219
+ with open(transcript_path, 'r', encoding='utf-8') as f:
220
+ for line in f:
221
+ try:
222
+ msg = json.loads(line.strip())
223
+ # 只保留 user 和 assistant 类型的消息
224
+ if msg and msg.get('type') in ['user', 'assistant']:
225
+ messages.append(msg)
226
+ except json.JSONDecodeError:
227
+ continue
228
+ except Exception as e:
229
+ print(f"Error reading transcript: {e}", file=sys.stderr)
230
+ return []
231
+
232
+ return messages
233
+
234
+
235
+ def generate_markdown(messages: List[Dict[str, Any]],
236
+ tool_calls: List[Dict],
237
+ references: Set[str]) -> str:
238
+ """将消息列表转换为 Markdown 格式(增强版)"""
239
+ if not messages:
240
+ return "# 对话记录\n\n无对话内容。\n"
241
+
242
+ lines = []
243
+ lines.append("# Claude Code 对话记录\n")
244
+ lines.append(f"**时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
245
+
246
+ # 添加参考资源部分
247
+ if references:
248
+ lines.append("\n## 📚 参考资源\n")
249
+ for ref in sorted(references):
250
+ lines.append(f"- {ref}\n")
251
+
252
+ # 添加工具使用统计
253
+ if tool_calls:
254
+ lines.append(f"\n**使用工具**: {len(tool_calls)} 次\n")
255
+ tool_counts = {}
256
+ for call in tool_calls:
257
+ name = call.get('name', 'unknown')
258
+ tool_counts[name] = tool_counts.get(name, 0) + 1
259
+ for name, count in sorted(tool_counts.items()):
260
+ lines.append(f" - {name}: {count} 次\n")
261
+
262
+ lines.append("\n---\n")
263
+
264
+ # 对话内容
265
+ for idx, msg in enumerate(messages, 1):
266
+ msg_type = msg.get('type', 'unknown')
267
+ text = format_message_content(msg)
268
+ if text.strip() == '':
269
+ continue
270
+
271
+ if msg_type == 'user':
272
+ lines.append(f"\n## 👤 用户提问 #{idx}\n")
273
+ lines.append(f"{text}\n")
274
+ elif msg_type == 'assistant':
275
+ lines.append(f"\n## 🤖 Claude 回答 #{idx}\n")
276
+ lines.append(f"{text}\n")
277
+
278
+ lines.append("\n---\n")
279
+
280
+ # 附录:详细的工具调用记录
281
+ if tool_calls:
282
+ lines.append("\n## 📋 附录:工具调用详情\n")
283
+ for idx, call in enumerate(tool_calls, 1):
284
+ lines.append(f"\n### 工具 {idx}: {call.get('name', 'unknown')}\n")
285
+ lines.append("```json\n")
286
+ lines.append(json.dumps(call, indent=2, ensure_ascii=False, default=str))
287
+ lines.append("\n```\n")
288
+
289
+ lines.append(f"\n---\n")
290
+ lines.append(f"*自动生成于 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n")
291
+
292
+ return '\n'.join(lines)
293
+
294
+
295
+ def save_resources(references: Set[str], output_dir: Path, base_filename: str):
296
+ """保存参考资源列表到单独文件"""
297
+ if not references:
298
+ return
299
+
300
+ resources_file = output_dir / f"{base_filename}_resources.txt"
301
+
302
+ try:
303
+ with open(resources_file, 'w', encoding='utf-8') as f:
304
+ f.write(f"# 参考资源\n")
305
+ f.write(f"# 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
306
+ f.write(f"# 对话文件: {base_filename}.md\n\n")
307
+
308
+ for ref in sorted(references):
309
+ f.write(f"{ref}\n")
310
+
311
+ print(f"Resources saved to: {resources_file}", file=sys.stderr)
312
+ except Exception as e:
313
+ print(f"Error saving resources: {e}", file=sys.stderr)
314
+
315
+
316
+ def save_conversation(transcript_path: str, project_dir: str):
317
+ """保存对话到 Markdown 文件(增强版)"""
318
+ try:
319
+ # 解析会话文件
320
+ messages = parse_transcript(transcript_path)
321
+ if not messages:
322
+ print("No messages to save", file=sys.stderr)
323
+ return
324
+
325
+ # 提取工具调用和结果
326
+ tool_calls = extract_tool_calls(messages)
327
+ tool_results = extract_tool_results(messages)
328
+ references = extract_references(tool_calls, tool_results)
329
+
330
+ # 提取第一个用户提问作为关键词来源
331
+ first_user_msg = ""
332
+ for msg in messages:
333
+ if msg.get('type') == 'user':
334
+ first_user_msg = format_message_content(msg)
335
+ if first_user_msg:
336
+ break
337
+
338
+ # 提取关键词
339
+ keywords = extract_keywords(first_user_msg) if first_user_msg else "spec"
340
+
341
+ # 生成文件名: YYmmddHH_{关键词}
342
+ timestamp = datetime.now().strftime('%y%m%d_%H%M%S')
343
+ base_filename = f"claude_log_{timestamp}_{keywords}"
344
+ filename = f"{base_filename}.md"
345
+
346
+ # 使用环境变量指定的目录,默认 _.claude_hist
347
+ hist_dir = get_hist_dir(project_dir)
348
+
349
+ # 生成 Markdown 内容
350
+ markdown_content = generate_markdown(messages, tool_calls, references)
351
+
352
+ # 保存主文件
353
+ output_file = hist_dir / filename
354
+ with open(output_file, 'w', encoding='utf-8') as f:
355
+ f.write(markdown_content)
356
+
357
+ print(f"Conversation saved to: {output_file}", file=sys.stderr)
358
+
359
+ # 保存参考资源列表
360
+ save_resources(references, hist_dir, base_filename)
361
+
362
+ except Exception as e:
363
+ print(f"Error saving conversation: {e}", file=sys.stderr)
364
+ import traceback
365
+ traceback.print_exc(file=sys.stderr)
366
+
367
+
368
+ def main():
369
+ """主函数"""
370
+ try:
371
+ # Check if this hook is enabled via environment variable
372
+ if os.environ.get('YJ_CLAUDE_CHAT_SAVE_SPEC') != '1':
373
+ # Silently exit if not enabled
374
+ sys.exit(0)
375
+
376
+ input_data = json.load(sys.stdin)
377
+ hook_event = input_data.get('hook_event_name', '')
378
+
379
+ if hook_event == 'Stop':
380
+ transcript_path = input_data.get('transcript_path', '')
381
+ cwd = input_data.get('cwd', '')
382
+
383
+ if transcript_path and cwd:
384
+ save_conversation(transcript_path, cwd)
385
+ else:
386
+ print(f"Missing required data: transcript_path={transcript_path}, cwd={cwd}", file=sys.stderr)
387
+
388
+ sys.exit(0)
389
+
390
+ except Exception as e:
391
+ print(f"Hook error: {e}", file=sys.stderr)
392
+ import traceback
393
+ traceback.print_exc(file=sys.stderr)
394
+ sys.exit(1)
395
+
396
+
397
+ if __name__ == '__main__':
398
+ main()
@@ -0,0 +1,270 @@
1
+ # 项目开发规范
2
+
3
+ 本目录包含项目的编程标准和开发规范。
4
+
5
+ ## 📚 规范文档
6
+
7
+ ### Go 语言规范
8
+
9
+ - **[coding-standards.md](go/coding-standards.md)** - Go 项目编程标准
10
+ - 注释规范(`//` vs `//;` 约定)
11
+ - 命名规范
12
+ - 代码组织
13
+ - 错误处理
14
+ - 并发编程
15
+ - 测试规范
16
+ - 性能优化
17
+
18
+ ## 🛠️ 工具脚本
19
+
20
+ ### Go 项目工具
21
+
22
+ 1. **`check-standards.sh`** - 全面的代码标准检查
23
+ ```bash
24
+ # 在项目根目录运行
25
+ ./.claude/rules/go/check-standards.sh
26
+ ```
27
+
28
+ 检查项:
29
+ - ✅ 代码格式(gofmt)
30
+ - ✅ Imports 顺序(goimports)
31
+ - ✅ 测试通过率
32
+ - ✅ 测试覆盖率(≥ 80%)
33
+ - ✅ 竞态条件检测
34
+ - ✅ Linter 检查
35
+ - ✅ 注释规范统计
36
+
37
+ 2. **`list-comments.sh`** - 列出所有非代码注释
38
+ ```bash
39
+ # 在项目根目录运行
40
+ ./.claude/rules/go/list-comments.sh
41
+ ```
42
+
43
+ 显示:
44
+ - 📋 TODO 列表
45
+ - 🔧 FIXME 列表
46
+ - ⚠️ HACK 列表
47
+ - ⚡ OPTIMIZE 列表
48
+ - 🗑️ DEPRECATED 列表
49
+ - 📝 NOTE 列表
50
+
51
+ ## 🚀 快速开始
52
+
53
+ ### 1. 安装必要工具
54
+
55
+ ```bash
56
+ # 安装 golangci-lint
57
+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
58
+
59
+ # 安装 goimports
60
+ go install golang.org/x/tools/cmd/goimports@latest
61
+ ```
62
+
63
+ ### 2. 配置项目
64
+
65
+ 在项目根目录创建 `.golangci.yml`:
66
+
67
+ ```yaml
68
+ linters:
69
+ enable:
70
+ - gofmt
71
+ - goimports
72
+ - govet
73
+ - errcheck
74
+ - staticcheck
75
+ - unused
76
+ - gosimple
77
+ - ineffassign
78
+ - deadcode
79
+ - typecheck
80
+ - gocyclo
81
+ - funlen
82
+
83
+ linters-settings:
84
+ gocyclo:
85
+ min-complexity: 10
86
+ funlen:
87
+ lines: 50
88
+ statements: 40
89
+ ```
90
+
91
+ ### 3. 设置 Git Hooks(可选)
92
+
93
+ 创建 `.git/hooks/pre-commit`:
94
+
95
+ ```bash
96
+ #!/bin/bash
97
+ ./.claude/rules/go/check-standards.sh
98
+ ```
99
+
100
+ ```bash
101
+ chmod +x .git/hooks/pre-commit
102
+ ```
103
+
104
+ ### 4. 在代码中使用注释约定
105
+
106
+ ```go
107
+ package main
108
+
109
+ // Add 计算两个整数的和
110
+ // 这是标准的代码注释,使用 //
111
+ func Add(a, b int) int {
112
+ //; TODO: 添加溢出检查
113
+ //; NOTE: 这个函数会在 v2.0 中支持浮点数
114
+ return a + b
115
+ }
116
+
117
+ //; DEPRECATED: 使用 Add 函数替代
118
+ //; 此函数将在 v2.0 移除
119
+ func AddLegacy(a, b int) int {
120
+ return a + b
121
+ }
122
+ ```
123
+
124
+ ## 📋 注释规范速查
125
+
126
+ | 前缀 | 用途 | 示例 |
127
+ |------|------|------|
128
+ | `//` | 代码功能注释 | `// CalculateTotal 计算订单总金额` |
129
+ | `//; TODO:` | 待实现功能 | `//; TODO: 添加参数验证` |
130
+ | `//; FIXME:` | 需要修复的问题 | `//; FIXME: Redis 连接超时问题` |
131
+ | `//; HACK:` | 临时解决方案 | `//; HACK: 等待 API v2 升级后移除` |
132
+ | `//; OPTIMIZE:` | 性能优化点 | `//; OPTIMIZE: 可以使用批量查询` |
133
+ | `//; DEPRECATED:` | 已废弃代码 | `//; DEPRECATED: 使用 NewAPI 替代` |
134
+ | `//; NOTE:` | 开发者备注 | `//; NOTE: 这里需要考虑并发安全` |
135
+ | `//; DEBUG:` | 调试信息 | `//; DEBUG: 临时日志,发布前删除` |
136
+
137
+ ## 🎯 质量标准
138
+
139
+ ### 强制要求(MUST)
140
+
141
+ - ✅ 代码覆盖率 ≥ 80%
142
+ - ✅ 无编译错误和 linter 错误
143
+ - ✅ 所有测试通过
144
+ - ✅ 无竞态条件
145
+ - ✅ 正确使用注释标记(`//` vs `//;`)
146
+
147
+ ### 推荐要求(SHOULD)
148
+
149
+ - ⭐ 函数长度 ≤ 50 行
150
+ - ⭐ 圈复杂度 ≤ 10
151
+ - ⭐ 参数数量 ≤ 5 个
152
+ - ⭐ 无重复代码
153
+
154
+ ## 📖 使用示例
155
+
156
+ ### 示例 1:检查代码标准
157
+
158
+ ```bash
159
+ # 运行完整检查
160
+ $ ./.claude/rules/go/check-standards.sh
161
+
162
+ 🔍 开始检查 Go 编程标准...
163
+
164
+ 📝 [1/7] 检查代码格式...
165
+ ✓ 代码格式正确
166
+
167
+ 📦 [2/7] 检查 imports 顺序...
168
+ ✓ Imports 顺序正确
169
+
170
+ 🧪 [3/7] 运行测试...
171
+ ✓ 所有测试通过
172
+
173
+ 📊 [4/7] 检查测试覆盖率...
174
+ ✓ 测试覆盖率: 87.5% (≥ 80%)
175
+
176
+ 🏃 [5/7] 检查竞态条件...
177
+ ✓ 无竞态条件
178
+
179
+ 🔍 [6/7] 运行 linter...
180
+ ✓ Linter 检查通过
181
+
182
+ 💬 [7/7] 检查注释规范...
183
+ - TODO: 3 项
184
+ - FIXME: 1 项
185
+ - HACK: 0 项
186
+ - DEPRECATED: 0 项
187
+
188
+ ================================
189
+ ✓ 所有检查通过!
190
+ ```
191
+
192
+ ### 示例 2:查看待办事项
193
+
194
+ ```bash
195
+ # 列出所有非代码注释
196
+ $ ./.claude/rules/go/list-comments.sh
197
+
198
+ 💬 Go 项目非代码注释列表
199
+ ======================================
200
+
201
+ 📋 TODO 列表:
202
+ ./service/user.go:45://; TODO: 添加邮箱验证
203
+ ./handler/order.go:78://; TODO: 实现订单取消功能
204
+
205
+ 🔧 FIXME 列表:
206
+ ./cache/redis.go:23://; FIXME: Redis 连接偶尔超时
207
+
208
+ ⚠️ HACK 列表:
209
+ (无)
210
+
211
+ ======================================
212
+ 📊 统计信息:
213
+ TODO: 2 项
214
+ FIXME: 1 项
215
+ HACK: 0 项
216
+ ```
217
+
218
+ ## 🔧 集成到 IDE
219
+
220
+ ### VS Code
221
+
222
+ 创建 `.vscode/settings.json`:
223
+
224
+ ```json
225
+ {
226
+ "go.lintTool": "golangci-lint",
227
+ "go.lintOnSave": "package",
228
+ "go.formatTool": "gofmt",
229
+ "editor.formatOnSave": true
230
+ }
231
+ ```
232
+
233
+ ### GoLand / IntelliJ IDEA
234
+
235
+ 1. Settings → Tools → File Watchers
236
+ 2. 添加 gofmt 和 goimports
237
+ 3. Settings → Editor → Inspections → Go
238
+ 4. 启用所有推荐的检查项
239
+
240
+ ## 📝 提交代码前检查清单
241
+
242
+ 在提交代码前,确保:
243
+
244
+ - [ ] 运行 `check-standards.sh` 并全部通过
245
+ - [ ] 使用 `list-comments.sh` 检查是否有未完成的 TODO/FIXME
246
+ - [ ] 所有新增代码都有单元测试
247
+ - [ ] 所有导出的函数都有文档注释(使用 `//`)
248
+ - [ ] 所有 TODO、FIXME 等使用 `//;` 前缀
249
+ - [ ] 代码已通过 code review
250
+
251
+ ## 🤝 贡献规范更新
252
+
253
+ 如果需要更新或改进这些规范:
254
+
255
+ 1. 修改对应的 `.md` 文件
256
+ 2. 如有必要,更新检查脚本
257
+ 3. 在团队中讨论并达成共识
258
+ 4. 提交 PR 并说明修改原因
259
+
260
+ ## 📚 参考资源
261
+
262
+ - [Effective Go](https://golang.org/doc/effective_go)
263
+ - [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
264
+ - [Uber Go Style Guide](https://github.com/uber-go/guide)
265
+ - [Google Go Style Guide](https://google.github.io/styleguide/go/)
266
+
267
+ ---
268
+
269
+ **维护者**: 开发团队
270
+ **最后更新**: 2026-01-06