#!/usr/bin/env python3 """ 自动完成检查 Hook 拦截任务结束,执行代码质量检查 """ import json import sys import os from pathlib import Path # 导入模块 sys.path.insert(0, str(Path(__file__).parent)) from requirements_tracker import generate_requirement_checklist, save_checklist from code_analyzer import analyze_code_quality, calculate_completeness_score from notification_sender import notify_check_result def load_iteration_tracker(project_root): """加载迭代计数器""" tracker_file = Path(project_root) / '.claude' / 'iteration-tracker.json' if tracker_file.exists(): with open(tracker_file, 'r', encoding='utf-8') as f: return json.load(f) return {} def update_iteration_count(project_root, task_id, increment=True): """更新迭代计数""" tracker = load_iteration_tracker(project_root) if task_id not in tracker: tracker[task_id] = 0 if increment: tracker[task_id] += 1 # 保存 tracker_file = Path(project_root) / '.claude' / 'iteration-tracker.json' tracker_file.parent.mkdir(parents=True, exist_ok=True) with open(tracker_file, 'w', encoding='utf-8') as f: json.dump(tracker, f, ensure_ascii=False, indent=2) return tracker[task_id] def reset_iteration_count(project_root, task_id): """重置迭代计数(任务完成时)""" return update_iteration_count(project_root, task_id, increment=False) def generate_fix_requirements(issues, requirements_checklist): """生成修复要求""" fix_requirements = [] # 从代码问题生成修复要求 if issues['todo']: fix_requirements.append(f"- 处理 {len(issues['todo'])} 个 TODO/FIXME 项") if issues['empty_functions']: fix_requirements.append(f"- 实现以下空函数: {', '.join([f'{i[\"file\"]}:{i[\"line\"]}' for i in issues['empty_functions'][:3]])}") if issues['placeholders']: fix_requirements.append(f"- 移除或实现占位符代码 ({len(issues['placeholders'])} 处)") if issues['commented_code']: fix_requirements.append(f"- 清理或取消注释代码 ({len(issues['commented_code'])} 处)") # 从需求清单生成修复要求 unverified = [r for r in requirements_checklist.get('requirements', []) if not r.get('verified', False)] if unverified: fix_requirements.append(f"- 验证以下需求已完成:\n " + "\n ".join([f"{i+1}. {r['description']}" for i, r in enumerate(unverified[:5])])) return "\n".join(fix_requirements) if fix_requirements else "未发现明显问题,建议人工审查" def perform_quick_check(project_root, task_id, conversation_context=''): """执行快速检查""" # 1. 生成需求检查清单 requirements_checklist = generate_requirement_checklist(project_root, conversation_context) save_checklist(requirements_checklist, task_id, project_root) # 2. 代码质量分析 analysis_result = analyze_code_quality(project_root) score = analysis_result['score'] issues = analysis_result['issues'] # 3. 检查逻辑 passed = score >= 80 critical_issues = len(issues['empty_functions']) + len(issues['placeholders']) # 4. 获取迭代计数 iteration_count = load_iteration_tracker(project_root).get(task_id, 0) requires_review = iteration_count >= 3 # 5. 生成结果 result = { 'passed': passed, 'score': score, 'iteration_count': iteration_count, 'requires_review': requires_review, 'issues': analysis_result['summary'], 'total_issues': analysis_result['total_issues'] } # 6. 决定是否阻止完成 if not passed and not requires_review: # 增加迭代计数 new_count = update_iteration_count(project_root, task_id) result['iteration_count'] = new_count # 生成修复要求 fix_requirements = generate_fix_requirements(issues, requirements_checklist) result['fix_requirements'] = fix_requirements result['block_completion'] = True result['message'] = f'代码质量检查未通过 (评分: {score}/100,迭代: {new_count}/3)' elif requires_review: result['block_completion'] = True result['message'] = f'已达最大迭代次数 ({iteration_count}/3),需要深度审查' result['trigger_review_agent'] = True else: # 通过,重置计数 reset_iteration_count(project_root, task_id) result['block_completion'] = False result['message'] = f'代码质量检查通过 (评分: {score}/100)' return result def main(): """主函数""" try: # 加载输入 input_data = json.load(sys.stdin) except json.JSONDecodeError: input_data = {} # 获取参数 project_root = input_data.get('projectRoot', os.getcwd()) task_id = input_data.get('taskId', 'default') conversation_context = input_data.get('conversationContext', '') # 执行快速检查 check_result = perform_quick_check(project_root, task_id, conversation_context) # 发送通知(异步,不阻塞) if check_result.get('passed') or check_result.get('requires_review'): try: notify_check_result(check_result) except Exception: pass # 通知失败不影响主流程 # 显示终端信息 if not check_result.get('passed'): print(f"\n{'='*60}", file=sys.stderr) print(f"⚠️ 代码质量检查未通过", file=sys.stderr) print(f"{'='*60}", file=sys.stderr) print(f"评分: {check_result['score']}/100", file=sys.stderr) print(f"迭代次数: {check_result['iteration_count']}/3", file=sys.stderr) print(f"\n发现的问题:", file=sys.stderr) for key, count in check_result['issues'].items(): if count > 0: print(f" - {key}: {count}", file=sys.stderr) print(f"\n修复要求:", file=sys.stderr) print(check_result.get('fix_requirements', ''), file=sys.stderr) print(f"{'='*60}\n", file=sys.stderr) # 构造 Hook 输出 output = { 'hookSpecificOutput': { 'hookEventName': 'TaskEnd', 'blockCompletion': check_result.get('block_completion', False), 'additionalContext': check_result.get('fix_requirements', ''), 'triggerReviewAgent': check_result.get('trigger_review_agent', False), 'checkResult': check_result } } # 如果通过,添加成功消息 if check_result.get('passed'): output['hookSpecificOutput']['message'] = f"✅ 代码质量检查通过 (评分: {check_result['score']}/100)" # 输出 JSON print(json.dumps(output, ensure_ascii=False)) if __name__ == '__main__': main()