开发code-quality

This commit is contained in:
2026-01-30 00:42:33 +08:00
parent f95b5f5b13
commit 3367268ace
14 changed files with 1636 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"superpowers@claude-plugins-official": true
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"permissions": {
"allow": [
"mcp__web-search-prime__webSearchPrime",
"mcp__web-reader__webReader",
"Bash(tree:*)",
"Bash(powershell:*)"
]
}
}
+321
View File
@@ -0,0 +1,321 @@
# 代码质量保障系统
一套完整的 Agent + Hook + Skill 组合,让 AI 能够写出更完善的代码。
## 🎯 核心功能
### 1. 自动完成检查 (Auto-Complete Hook)
- 拦截 Agent 任务结束,自动检查代码质量
- 检测未完成的功能、TODO、空函数、占位符
- 最多允许 3 次迭代修复
- 未通过时阻止任务完成,生成修复要求
### 2. 深度质量检查 (Code-Quality Skill)
- 手动触发命令:`/code-quality`
- 全面检查:功能、代码、测试、文档、规范、安全
- 生成详细的质量报告
- 提供修复建议和自动修复选项
### 3. 智能通知系统
- Windows 桌面通知
- 声音提醒(成功/警告/注意)
- 异步发送,不阻塞工作流程
## 📁 文件结构
```
code-quality-system/
├── hooks/ # Hook 脚本
│ ├── auto-complete-check.py # 主检查逻辑
│ ├── requirements-tracker.py # 需求追踪器
│ ├── code-analyzer.py # 代码分析器
│ ├── notification-sender.py # 通知发送器
│ └── requirements.txt # Python 依赖
├── custom-skills/ # 自定义技能
│ └── code-quality/
│ ├── skill.json # 技能定义
│ └── instructions.md # 技能指令
├── config/ # 配置文件
│ └── code-quality-config.json # 系统配置
├── sounds/ # 声音资源
│ ├── README.md # 声音文件说明
│ ├── success.wav # 成功提示音
│ ├── warning.wav # 警告提示音
│ └── attention.wav # 注意提示音
├── deploy.bat # 一键部署脚本
└── README.md # 本文件
```
## 🚀 快速开始
### 方法 1: 使用一键部署脚本(推荐)
1. 双击运行 `deploy.bat`
2. 选择部署模式:
- **全局部署**:所有项目自动启用
- **项目部署**:仅当前项目启用
3. 重启 Claude Code
4. 完成!
### 方法 2: 手动部署
#### 全局部署
```bash
# 1. 复制文件到 Claude Code 配置目录
cp -r hooks/* ~/.claude/hooks/
cp -r custom-skills/* ~/.claude/custom-skills/
cp config/code-quality-config.json ~/.claude/
# 2. 安装 Python 依赖
pip install plyer pygame
# 3. 配置 settings.json
# 添加以下内容到 ~/.claude/settings.json:
{
"hooks": {
"TaskEnd": [
{
"type": "command",
"command": "python ~/.claude/hooks/auto-complete-check.py"
}
]
}
}
```
#### 项目部署
```bash
# 1. 复制文件到项目目录
cp -r hooks/* .claude/hooks/
cp -r custom-skills/* .claude/custom-skills/
cp config/code-quality-config.json .claude/
# 2. 安装 Python 依赖
pip install plyer pygame
```
## 🔧 配置说明
编辑 `code-quality-config.json` 自定义系统行为:
```json
{
"enabled": true, // 是否启用
"checkLevel": "standard", // 检查级别: standard/deep
"maxIterations": 3, // 最大迭代次数
"notification": {
"enabled": true, // 启用通知
"sound": true, // 启用声音
"desktop": true, // 启用桌面通知
"soundVolume": 0.7 // 音量 (0.0-1.0)
},
"thresholds": {
"passingScore": 80, // 通过分数
"warningScore": 60, // 警告分数
"maxTodos": 5, // 最大 TODO 数量
"maxEmptyFunctions": 0, // 最大空函数数量
"maxPlaceholders": 0 // 最大占位符数量
}
}
```
## 📖 使用方法
### 自动检查(默认启用)
系统会在以下情况自动触发检查:
- 主 Agent 完成任务时
- 任何子 Agent 完成任务时
- 不需要手动干预
### 手动检查
使用 `/code-quality` 命令:
```
# 标准检查
/code-quality
# 深度检查
/code-quality --deep
# 聚焦特定方面
/code-quality --focus security
/code-quality --focus documentation
/code-quality --focus code-style
```
### 工作流程
```
┌─────────────────┐
│ AI 开始编码 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ AI 声明完成 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Hook 拦截 │◄───────────────┐
└────────┬────────┘ │
│ │
▼ │
┌─────────────────┐ │
│ 执行快速检查 │ │
└────────┬────────┘ │
│ │
┌────┴────┐ │
│ │ │
通过❌ 通过✅ │
│ │ │
▼ ▼ │
┌─────────┐ ┌──────────┐ │
│迭代+1 │ │允许结束 │ │
└────┬────┘ └──────────┘ │
│ │
▼ │
┌─────────┐ │
│生成修复 │ │
│要求 │ │
└────┬────┘ │
│ │
▼ │
┌─────────────────┐ │
│ AI 继续修复 │────────────────┘
└─────────────────┘
```
## 🔍 检查维度
### 1. 功能完整性
- 对比需求清单
- 验证所有功能已实现
- 检查缺失的功能
### 2. 代码完整性
- 检测 TODO、FIXME
- 检测空函数、占位符
- 检测被注释的代码
- 检测调试语句
### 3. 代码规范
- 命名规范
- 格式一致性
- 语言特定规范(ESLint、PEP 8、Clippy)
- 项目特定规范
### 4. 测试覆盖
- 测试文件存在性
- 测试用例数量
- 关键功能测试
### 5. 文档完整性
- 函数/类注释
- README 文档
- API 文档
### 6. 安全检查
- SQL 注入风险
- XSS 漏洞
- 硬编码密钥
- 不安全的函数调用
## 📊 检查报告示例
```
## 代码质量检查报告
### 总体评分:85/100
### 完成度分析
✅ 用户登录功能 (100%)
✅ 数据库连接 (100%)
⚠️ API 错误处理 (60%) - 缺少部分错误码
❌ 日志记录 (0%) - 未实现
### 代码质量
- TODO: 3 个
- 空函数: 0 个
- 被注释代码: 2 处
- 占位符: 1 个
### 修复建议(按优先级)
1. [高] 实现日志记录模块
2. [高] 补充 API 错误码
3. [中] 清理被注释的代码
4. [低] 处理 TODO 项
```
## 🛠️ 故障排除
### 通知不工作
1. 检查依赖是否安装:
```bash
pip install plyer pygame
```
2. 测试通知:
```bash
python ~/.claude/hooks/notification-sender.py test
```
3. 检查配置文件中的 `notification.enabled` 是否为 `true`
### Hook 不触发
1. 检查 `settings.json` 配置是否正确
2. 检查 Python 脚本是否有执行权限
3. 查看 Claude Code 日志:`~/.claude/logs/`
### 声音文件缺失
系统会自动使用 Windows 系统 Beep 音效作为回退,不影响功能。
如需自定义声音,参考 `sounds/README.md`。
## 📝 卸载
### 使用部署脚本
1. 运行 `deploy.bat`
2. 选择"卸载"
3. 选择要卸载的组件(全局/项目)
### 手动卸载
```bash
# 全局部署
rm ~/.claude/hooks/auto-complete-check.py
rm ~/.claude/hooks/requirements-tracker.py
rm ~/.claude/hooks/code-analyzer.py
rm ~/.claude/hooks/notification-sender.py
rm -rf ~/.claude/custom-skills/code-quality
rm ~/.claude/code-quality-config.json
# 项目部署
rm -rf .claude
```
## 🤝 贡献
欢迎提交问题和改进建议!
## 📄 许可
MIT License
## 🔗 相关资源
- [Claude Code 官方文档](https://github.com/anthropics/claude-code)
- [Hook 开发指南](./README.md) - 项目根目录的 Hook 使用指南
- [Superpowers 技能集](https://github.com/obra/superpowers-marketplace)
---
**让 AI 写出更完善的代码!** 🚀
@@ -0,0 +1,46 @@
{
"enabled": true,
"checkLevel": "standard",
"maxIterations": 3,
"notification": {
"enabled": true,
"sound": true,
"desktop": true,
"soundVolume": 0.7
},
"checks": {
"functionality": true,
"codeCompleteness": true,
"testCoverage": "recommended",
"documentation": "optional",
"languageStandards": true,
"projectStandards": true,
"security": "smart"
},
"projectSpecific": {
"eslintPath": "./eslint.config.js",
"testPatterns": [
"**/*.test.js",
"**/*.spec.js",
"**/*.test.py",
"**/*.spec.py"
],
"docPatterns": [
"README.md",
"docs/**/*.md",
"api/**/*.md"
]
},
"reporting": {
"format": "markdown",
"saveReports": true,
"reportPath": "./.claude/reports"
},
"thresholds": {
"passingScore": 80,
"warningScore": 60,
"maxTodos": 5,
"maxEmptyFunctions": 0,
"maxPlaceholders": 0
}
}
@@ -0,0 +1,110 @@
# Code Quality Check Skill
你是一个代码质量检查专家。当用户调用 `/code-quality` 时,执行以下检查流程。
## 检查流程
### 1. 收集信息
- 读取项目配置文件(如果存在):
- `code-quality-config.json`
- `.eslintrc.js` / `eslint.config.js`
- `pyproject.toml` / `setup.py`
- `.prettierrc`
- 读取需求文档:
- `docs/plans/*.md`
- `README.md`
- 扫描项目代码文件
### 2. 执行检查(根据 depth 参数)
#### Standard 检查(默认)
- **功能完整性**:对比需求清单,检查是否实现
- **代码完整性**:
- 搜索 TODO、FIXME、XXX、HACK
- 检测空函数、占位符
- 检测被注释的代码
- **基础代码规范**:
- 命名规范
- 格式一致性
- 明显的语法错误
#### Deep 检查(深度)
包含 Standard 检查的所有内容,额外添加:
- **测试覆盖**:
- 检查测试文件存在性
- 估算测试用例数量
- 检查关键功能是否有测试
- **文档完整性**:
- 函数/类注释
- README 文档
- API 文档
- **语言特定规范**:
- JavaScript/TypeScript:执行 ESLint 检查
- Python:检查 PEP 8 规范
- Rust:执行 Clippy 检查
- **项目规范**:读取并检查项目配置的规范
- **安全检查**:
- SQL 注入风险
- XSS 漏洞
- 硬编码密钥/密码
- 不安全的函数调用
### 3. 根据焦点检查(focus 参数)
- `all`: 执行所有检查
- `functionality`: 只检查功能完整性
- `code-style`: 只检查代码规范
- `security`: 只检查安全问题
- `documentation`: 只检查文档
### 4. 生成报告
生成 Markdown 格式的报告,包含:
```markdown
## 代码质量检查报告
### 总体评分:XX/100
### 完成度分析
[功能列表及完成状态]
### 代码质量
- 发现的问题统计
- 按优先级排序的问题列表
### 测试覆盖(如果检查)
- 测试文件数量
- 覆盖率估算
### 文档完整性(如果检查)
- 文档评分
- 缺失的文档
### 修复建议
按优先级排序的修复建议
### 自动修复
[如果可以自动修复,提供修复方案]
```
### 5. 输出格式
- 在终端显示彩色输出(使用 ANSI 颜色代码)
- 保存报告到 `.claude/reports/code-quality-<timestamp>.md`
- 如果发现问题,询问用户是否需要自动修复
### 6. 触发通知
如果检查完成,触发通知:
- 通过:绿色通知 + 成功音效
- 失败:黄色通知 + 警告音效
- 需要深度审查:蓝色通知 + 注意音效
## 注意事项
- 检查时要考虑项目类型(Web、CLI、库等)
- 不同语言有不同的规范标准
- 优先报告阻塞问题,然后是重要问题,最后是建议改进
- 如果配置文件存在,遵循项目特定的规范配置
- 检查时间控制在合理范围内(Deep 检查不超过 30 秒)
@@ -0,0 +1,20 @@
{
"name": "code-quality",
"description": "执行全面的代码质量检查,包括功能完整性、代码规范、测试覆盖、文档完整性等",
"userInvocable": true,
"instructionsFile": "instructions.md",
"arguments": {
"depth": {
"description": "检查深度: standard(标准) 或 deep(深度)",
"type": "string",
"default": "standard",
"enum": ["standard", "deep"]
},
"focus": {
"description": "检查重点: all, functionality, code-style, security, documentation",
"type": "string",
"default": "all",
"enum": ["all", "functionality", "code-style", "security", "documentation"]
}
}
}
+286
View File
@@ -0,0 +1,286 @@
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
echo.
echo ========================================
echo 代码质量保障系统 - 一键部署脚本
echo ========================================
echo.
REM 检测 Python 是否安装
python --version >nul 2>&1
if errorlevel 1 (
echo ❌ 错误: 未检测到 Python,请先安装 Python 3.7+
pause
exit /b 1
)
echo ✅ Python 已安装
echo.
REM 获取脚本所在目录
set "SCRIPT_DIR=%~dp0"
cd /d "%SCRIPT_DIR%"
REM 显示部署选项
echo 请选择部署模式:
echo.
echo [1] 全局部署 (推荐)
echo - 部署到用户目录 (~/.claude/)
echo - 所有项目自动启用
echo - 需要管理员权限
echo.
echo [2] 项目部署
echo - 部署到当前项目的 .claude/ 目录
echo - 仅当前项目启用
echo - 不需要管理员权限
echo.
echo [3] 卸载
echo - 从系统中移除已部署的组件
echo.
echo [Q] 退出
echo.
set /p choice="请输入选择 (1/2/3/Q): "
if /i "%choice%"=="1" goto global_deploy
if /i "%choice%"=="2" goto project_deploy
if /i "%choice%"=="3" goto uninstall
if /i "%choice%"=="Q" goto end
if /i "%choice%"=="q" goto end
echo ❌ 无效的选择
pause
exit /b 1
:global_deploy
echo.
echo ========================================
echo 全局部署模式
echo ========================================
echo.
REM 检测 Claude Code 配置目录
set "CLAUDE_DIR=%USERPROFILE%\.claude"
if not exist "%CLAUDE_DIR%" (
echo ⚠️ Claude Code 配置目录不存在,正在创建...
mkdir "%CLAUDE_DIR%"
)
REM 部署 Hooks
echo 📦 正在部署 Hooks...
set "HOOKS_DIR=%CLAUDE_DIR%\hooks"
if not exist "%HOOKS_DIR%" mkdir "%HOOKS_DIR%"
copy /Y "%SCRIPT_DIR%hooks\*.py" "%HOOKS_DIR%\" >nul
if errorlevel 1 (
echo ❌ Hooks 部署失败
pause
exit /b 1
)
echo ✅ Hooks 部署成功
REM 部署 Skills
echo 📦 正在部署 Skills...
set "SKILLS_DIR=%CLAUDE_DIR%\custom-skills\code-quality"
if not exist "%SKILLS_DIR%" mkdir "%SKILLS_DIR%"
copy /Y "%SCRIPT_DIR%custom-skills\code-quality\*" "%SKILLS_DIR%\" >nul
if errorlevel 1 (
echo ❌ Skills 部署失败
pause
exit /b 1
)
echo ✅ Skills 部署成功
REM 部署配置
echo 📦 正在部署配置文件...
copy /Y "%SCRIPT_DIR%config\code-quality-config.json" "%CLAUDE_DIR%\" >nul
echo ✅ 配置文件部署成功
REM 复制声音文件(如果存在)
if exist "%SCRIPT_DIR%sounds\*.wav" (
echo 📦 正在部署声音文件...
set "SOUNDS_DIR=%CLAUDE_DIR%\sounds"
if not exist "%SOUNDS_DIR%" mkdir "%SOUNDS_DIR%"
copy /Y "%SCRIPT_DIR%sounds\*.wav" "%SOUNDS_DIR%\" >nul
echo ✅ 声音文件部署成功
) else (
echo ⚠️ 未找到声音文件,将使用系统提示音
)
REM 安装 Python 依赖
echo 📦 正在安装 Python 依赖...
pip install -q plyer pygame
if errorlevel 1 (
echo ⚠️ 部分依赖安装失败,通知功能可能不可用
) else (
echo ✅ 依赖安装成功
)
REM 配置 settings.json
echo 📦 正在配置 Claude Code 设置...
set "SETTINGS_FILE=%CLAUDE_DIR%\settings.json"
REM 创建或更新 settings.json
if exist "%SETTINGS_FILE%" (
echo 检测到现有配置文件,正在更新...
python -c "import json; data=json.load(open('%SETTINGS_FILE%', encoding='utf-8')); data.setdefault('hooks', {}).setdefault('TaskEnd', []).append({'type': 'command', 'command': 'python %USERPROFILE%\.claude\hooks/auto-complete-check.py'}); json.dump(data, open('%SETTINGS_FILE%', 'w', encoding='utf-8'), ensure_ascii=False, indent=2)" 2>nul
) else (
echo 创建新的配置文件...
echo {> "%SETTINGS_FILE%"
echo "hooks": {>> "%SETTINGS_FILE%"
echo "TaskEnd": [>> "%SETTINGS_FILE%"
echo {>> "%SETTINGS_FILE%"
echo "type": "command",>> "%SETTINGS_FILE%"
echo "command": "python %%USERPROFILE%%\\.claude\\hooks/auto-complete-check.py">> "%SETTINGS_FILE%"
echo }>> "%SETTINGS_FILE%"
echo ]>> "%SETTINGS_FILE%"
echo }>> "%SETTINGS_FILE%"
echo }>> "%SETTINGS_FILE%"
)
echo ✅ 配置文件更新成功
echo.
echo ========================================
echo ✅ 全局部署完成!
echo ========================================
echo.
echo 部署位置:
echo - Hooks: %HOOKS_DIR%
echo - Skills: %SKILLS_DIR%
echo - 配置: %CLAUDE_DIR%
echo.
echo 使用方法:
echo 1. 重启 Claude Code
echo 2. 系统将自动检查代码质量
echo 3. 使用 /code-quality 命令手动检查
echo.
echo 注意事项:
echo - 首次使用建议运行测试: python "%HOOKS_DIR%\notification-sender.py" test
echo - 配置文件位置: %CLAUDE_DIR%\code-quality-config.json
echo.
pause
exit /b 0
:project_deploy
echo.
echo ========================================
echo 项目部署模式
echo ========================================
echo.
REM 检查是否在 Git 仓库中
git rev-parse --is-inside-work-tree >nul 2>&1
if errorlevel 1 (
echo ⚠️ 当前目录不是 Git 仓库,某些功能可能不可用
)
REM 部署到项目 .claude 目录
set "PROJECT_CLAUDE_DIR=.claude"
echo 📦 正在部署到项目目录...
if not exist "%PROJECT_CLAUDE_DIR%" mkdir "%PROJECT_CLAUDE_DIR%"
REM 复制 Hooks
if not exist "%PROJECT_CLAUDE_DIR%\hooks" mkdir "%PROJECT_CLAUDE_DIR%\hooks"
copy /Y "%SCRIPT_DIR%hooks\*.py" "%PROJECT_CLAUDE_DIR%\hooks\" >nul
REM 复制 Skills
if not exist "%PROJECT_CLAUDE_DIR%\custom-skills\code-quality" mkdir "%PROJECT_CLAUDE_DIR%\custom-skills\code-quality"
copy /Y "%SCRIPT_DIR%custom-skills\code-quality\*" "%PROJECT_CLAUDE_DIR%\custom-skills\code-quality\" >nul
REM 复制配置
copy /Y "%SCRIPT_DIR%config\code-quality-config.json" "%PROJECT_CLAUDE_DIR%\" >nul
REM 复制声音文件
if exist "%SCRIPT_DIR%sounds\*.wav" (
if not exist "%PROJECT_CLAUDE_DIR%\sounds" mkdir "%PROJECT_CLAUDE_DIR%\sounds"
copy /Y "%SCRIPT_DIR%sounds\*.wav" "%PROJECT_CLAUDE_DIR%\sounds\" >nul
)
echo ✅ 项目部署成功
echo.
echo ========================================
echo ✅ 项目部署完成!
echo ========================================
echo.
echo 部署位置: %CD%\%PROJECT_CLAUDE_DIR%
echo.
echo 使用方法:
echo 1. 在项目中打开 Claude Code
echo 2. 系统将自动检查代码质量
echo 3. 使用 /code-quality 命令手动检查
echo.
pause
exit /b 0
:uninstall
echo.
echo ========================================
echo 卸载模式
echo ========================================
echo.
echo 请选择要卸载的组件:
echo.
echo [1] 全局部署
echo [2] 项目部署
echo [B] 返回
echo.
set /p uninstall_choice="请输入选择 (1/2/B): "
if /i "%uninstall_choice%"=="1" (
echo 正在卸载全局部署...
set "CLAUDE_DIR=%USERPROFILE%\.claude"
REM 删除 Hooks
if exist "%CLAUDE_DIR%\hooks\auto-complete-check.py" del "%CLAUDE_DIR%\hooks\auto-complete-check.py"
if exist "%CLAUDE_DIR%\hooks\requirements-tracker.py" del "%CLAUDE_DIR%\hooks\requirements-tracker.py"
if exist "%CLAUDE_DIR%\hooks\code-analyzer.py" del "%CLAUDE_DIR%\hooks\code-analyzer.py"
if exist "%CLAUDE_DIR%\hooks\notification-sender.py" del "%CLAUDE_DIR%\hooks\notification-sender.py"
REM 删除 Skills
if exist "%CLAUDE_DIR%\custom-skills\code-quality" rmdir /s /q "%CLAUDE_DIR%\custom-skills\code-quality"
REM 删除配置
if exist "%CLAUDE_DIR%\code-quality-config.json" del "%CLAUDE_DIR%\code-quality-config.json"
REM 更新 settings.json(移除 hook 配置)
set "SETTINGS_FILE=%CLAUDE_DIR%\settings.json"
if exist "%SETTINGS_FILE%" (
echo 正在更新配置文件...
REM 这里需要 Python 来正确处理 JSON
python -c "import json; data=json.load(open('%SETTINGS_FILE%', encoding='utf-8')); hooks=data.get('hooks', {}).get('TaskEnd', []); data['hooks']['TaskEnd']=[h for h in hooks if 'auto-complete-check' not in str(h)]; json.dump(data, open('%SETTINGS_FILE%', 'w', encoding='utf-8'), ensure_ascii=False, indent=2)" 2>nul
)
echo ✅ 全局部署已卸载
echo 注意: Python 依赖 (plyer, pygame) 未卸载,如需请手动运行: pip uninstall plyer pygame
) else if /i "%uninstall_choice%"=="2" (
echo 正在卸载项目部署...
if exist ".claude" (
rmdir /s /q ".claude"
echo ✅ 项目部署已卸载
) else (
echo ⚠️ 未找到项目部署
)
) else if /i "%uninstall_choice%"=="B" (
goto end
) else (
echo ❌ 无效的选择
)
echo.
pause
exit /b 0
:end
echo 退出部署脚本
exit /b 0
@@ -0,0 +1,193 @@
#!/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()
+175
View File
@@ -0,0 +1,175 @@
#!/usr/bin/env python3
"""
代码分析器
扫描代码文件,检测常见问题
"""
import json
import sys
import os
import re
from pathlib import Path
def analyze_file(file_path):
"""分析单个代码文件"""
issues = []
try:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
lines = content.split('\n')
# 检测模式
patterns = {
'TODO': r'TODO|FIXME|XXX|HACK',
'empty_function': r'def\s+\w+\s*\([^)]*\)\s*:\s*(pass|#\s*.*|.{0})',
'empty_method': r'(def|async\s+def)\s+\w+\s*\([^)]*\)\s*:\s*(pass|.{0})',
'commented_code': r'^\s*#.*=[^#\n]|^\s*#.*\([^)]*\)',
'placeholder': r'(NotImplementedError|raise\s+NotImplemented|pass\s*#.*placeholder)',
'debug_print': r'print\([^)]*\)|console\.log\([^)]*\)',
}
for line_num, line in enumerate(lines, 1):
for issue_type, pattern in patterns.items():
if re.search(pattern, line, re.IGNORECASE):
issues.append({
'type': issue_type,
'line': line_num,
'content': line.strip(),
'file': str(file_path)
})
except Exception as e:
issues.append({
'type': 'read_error',
'message': str(e),
'file': str(file_path)
})
return issues
def detect_project_changes(project_root):
"""检测项目中的代码变更"""
import subprocess
try:
# 获取 Git 变更的文件
result = subprocess.run(
['git', 'diff', '--name-only', 'HEAD'],
cwd=project_root,
capture_output=True,
text=True,
timeout=5
)
if result.returncode == 0:
changed_files = result.stdout.strip().split('\n')
changed_files = [f for f in changed_files if f]
# 过滤代码文件
code_extensions = {'.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.go', '.rs', '.c', '.cpp', '.h'}
code_files = [
Path(project_root) / f
for f in changed_files
if Path(f).suffix.lower() in code_extensions
]
return code_files
except Exception:
pass
# 如果 Git 不可用,扫描所有代码文件
code_extensions = {'.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.go', '.rs', '.c', '.cpp', '.h'}
project_path = Path(project_root)
code_files = []
for ext in code_extensions:
code_files.extend(project_path.rglob(f'*{ext}'))
return code_files
def analyze_code_quality(project_root):
"""分析代码质量"""
all_issues = {
'todo': [],
'empty_functions': [],
'commented_code': [],
'placeholders': [],
'debug_statements': [],
'other': []
}
# 获取需要分析的文件
files_to_analyze = detect_project_changes(project_root)
for file_path in files_to_analyze:
if not file_path.exists():
continue
issues = analyze_file(file_path)
for issue in issues:
issue_type = issue['type']
if issue_type == 'TODO':
all_issues['todo'].append(issue)
elif 'empty' in issue_type:
all_issues['empty_functions'].append(issue)
elif issue_type == 'commented_code':
all_issues['commented_code'].append(issue)
elif issue_type == 'placeholder':
all_issues['placeholders'].append(issue)
elif issue_type == 'debug_print':
all_issues['debug_statements'].append(issue)
else:
all_issues['other'].append(issue)
return all_issues
def calculate_completeness_score(issues):
"""计算完整度评分"""
total_issues = sum(len(v) for v in issues.values())
# 严重问题权重
critical_issues = len(issues['empty_functions']) + len(issues['placeholders'])
minor_issues = len(issues['todo']) + len(issues['commented_code']) + len(issues['debug_statements'])
# 计算分数(0-100)
score = 100 - (critical_issues * 15) - (minor_issues * 5)
return max(0, min(100, score))
def main():
"""主函数"""
# 从命令行参数或 stdin 获取项目路径
if len(sys.argv) > 1:
project_root = sys.argv[1]
else:
project_root = os.getcwd()
# 执行分析
issues = analyze_code_quality(project_root)
score = calculate_completeness_score(issues)
# 输出结果
result = {
'score': score,
'issues': issues,
'total_issues': sum(len(v) for v in issues.values()),
'summary': {
'todo_count': len(issues['todo']),
'empty_functions_count': len(issues['empty_functions']),
'commented_code_count': len(issues['commented_code']),
'placeholder_count': len(issues['placeholders']),
'debug_statements_count': len(issues['debug_statements'])
}
}
print(json.dumps(result, ensure_ascii=False, indent=2))
if __name__ == '__main__':
main()
@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""
通知发送器
发送 Windows 桌面通知和播放声音
"""
import json
import sys
import os
import platform
from pathlib import Path
def send_notification(title, message, icon_path=None, duration=10):
"""发送 Windows 桌面通知"""
try:
from plyer import notification
notification.notify(
title=title,
message=message,
app_name='Claude Code',
app_icon=icon_path,
timeout=duration
)
return True
except ImportError:
# 如果 plyer 不可用,尝试使用 Windows 原生 API
try:
import win10toast
toaster = win10toast.ToastNotifier()
toaster.show_toast(
title,
message,
icon_path=icon_path,
duration=duration
)
return True
except ImportError:
# 最后的回退:输出到 stderr(会显示在终端)
print(f'\n📢 {title}: {message}', file=sys.stderr)
return False
except Exception as e:
print(f'\n📢 {title}: {message}', file=sys.stderr)
return False
def play_sound(sound_type='success', volume=0.7):
"""播放提示音"""
sound_files = {
'success': 'success.wav',
'warning': 'warning.wav',
'attention': 'attention.wav'
}
sound_file = sound_files.get(sound_type, 'success.wav')
# 获取声音文件路径
script_dir = Path(__file__).parent
sounds_dir = script_dir.parent / 'sounds'
sound_path = sounds_dir / sound_file
try:
# 尝试使用 pygame
import pygame
pygame.mixer.init()
pygame.mixer.music.set_volume(volume)
pygame.mixer.music.load(str(sound_path))
pygame.mixer.music.play()
return True
except ImportError:
# 如果 pygame 不可用,尝试系统 beep
try:
import winsound
if sound_type == 'success':
winsound.Beep(800, 200)
elif sound_type == 'warning':
winsound.Beep(400, 300)
else:
winsound.Beep(600, 400)
return True
except Exception:
# 最后的回退:终端提示
return False
except Exception:
return False
def notify_check_result(check_result):
"""根据检查结果发送通知"""
if check_result.get('passed'):
send_notification(
title='✅ 代码质量检查通过',
message='所有功能已实现,代码规范符合要求',
duration=5
)
play_sound('success')
elif check_result.get('requires_review'):
send_notification(
title='🔔 需要深度审查',
message='自动修复已达上限,请查看详细报告',
duration=15
)
play_sound('attention')
else:
issue_count = check_result.get('issue_count', 0)
send_notification(
title='⚠️ 代码质量检查未通过',
message=f'发现 {issue_count} 个问题需要修复',
duration=10
)
play_sound('warning')
def main():
"""主函数 - 可以独立运行或作为模块导入"""
# 从 stdin 或命令行参数读取
if len(sys.argv) > 1:
# 命令行模式
if sys.argv[1] == 'test':
# 测试通知
send_notification('测试通知', '代码质量保障系统正在运行')
play_sound('success')
elif sys.argv[1] == 'success':
send_notification('✅ 检查通过', '所有功能已实现,代码规范符合要求')
play_sound('success')
elif sys.argv[1] == 'warning':
send_notification('⚠️ 检查未通过', '发现问题需要修复')
play_sound('warning')
elif sys.argv[1] == 'attention':
send_notification('🔔 需要审查', '请查看详细报告')
play_sound('attention')
else:
# 从 stdin 读取 JSON
try:
input_data = json.load(sys.stdin)
notify_check_result(input_data)
except json.JSONDecodeError:
pass
if __name__ == '__main__':
main()
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""
需求追踪器
从对话历史和计划文件中提取需求,生成检查清单
"""
import json
import sys
import os
import re
from pathlib import Path
def load_input():
"""加载 Hook 输入数据"""
try:
return json.load(sys.stdin)
except json.JSONDecodeError:
return {}
def extract_requirements_from_conversation(conversation_text):
"""从对话中提取需求"""
requirements = []
# 需求关键词模式
patterns = {
'功能需求': r'(需要|实现|添加|创建|开发)\s*([^,。;\n]{5,50})',
'技术栈': r'(使用|基于|框架)\s*([^,。;\n]{2,30})',
'约束条件': r'(必须|应该|不能|禁止)\s*([^,。;\n]{5,50})',
}
for category, pattern in patterns.items():
matches = re.findall(pattern, conversation_text)
for match in matches:
if isinstance(match, tuple):
requirements.append({
'category': category,
'description': match[-1].strip(),
'verified': False
})
return requirements
def read_plan_files(project_root):
"""读取项目计划文件"""
plan_files = []
docs_path = Path(project_root) / 'docs' / 'plans'
if docs_path.exists():
for plan_file in docs_path.glob('*.md'):
try:
with open(plan_file, 'r', encoding='utf-8') as f:
content = f.read()
plan_files.append({
'path': str(plan_file),
'content': content
})
except Exception as e:
pass
return plan_files
def parse_plan_to_checklist(plan_content):
"""解析计划文件为检查清单"""
checklist = []
# 提取任务/功能项
lines = plan_content.split('\n')
for line in lines:
line = line.strip()
# 匹配 markdown 列表项
if line.startswith('- ') or line.startswith('* '):
item = line[2:].strip()
# 移除 [ ] 或 [x] 标记
item = re.sub(r'^\[[ x]\]\s*', '', item)
if item:
checklist.append({
'description': item,
'verified': False,
'source': 'plan_file'
})
return checklist
def generate_requirement_checklist(project_root, conversation_context=''):
"""生成需求检查清单"""
checklist = {
'requirements': [],
'source': 'unknown'
}
# 1. 尝试从计划文件读取
plan_files = read_plan_files(project_root)
if plan_files:
for plan in plan_files:
items = parse_plan_to_checklist(plan['content'])
checklist['requirements'].extend(items)
checklist['source'] = 'plan_files'
checklist['plan_files'] = [p['path'] for p in plan_files]
# 2. 如果没有计划文件,从对话提取
if not checklist['requirements'] and conversation_context:
items = extract_requirements_from_conversation(conversation_context)
checklist['requirements'] = items
checklist['source'] = 'conversation'
return checklist
def save_checklist(checklist, task_id, project_root):
"""保存检查清单到临时文件"""
cache_dir = Path(project_root) / '.claude' / 'cache'
cache_dir.mkdir(parents=True, exist_ok=True)
checklist_file = cache_dir / f'requirements_{task_id}.json'
with open(checklist_file, 'w', encoding='utf-8') as f:
json.dump(checklist, f, ensure_ascii=False, indent=2)
return str(checklist_file)
def main():
"""主函数"""
input_data = load_input()
# 获取项目根目录
project_root = input_data.get('projectRoot', os.getcwd())
# 获取对话上下文(如果有)
conversation_context = input_data.get('conversationContext', '')
# 生成检查清单
checklist = generate_requirement_checklist(project_root, conversation_context)
# 保存到缓存
task_id = input_data.get('taskId', 'default')
checklist_file = save_checklist(checklist, task_id, project_root)
# 输出结果
output = {
'checklist_generated': True,
'requirements_count': len(checklist['requirements']),
'source': checklist['source'],
'checklist_file': checklist_file
}
print(json.dumps(output, ensure_ascii=False))
if __name__ == '__main__':
main()
@@ -0,0 +1,2 @@
plyer>=2.1.0
pygame>=2.5.0
+68
View File
@@ -0,0 +1,68 @@
# 声音资源说明
这个目录包含代码质量检查系统的提示音文件。
## 声音文件
### success.wav
- **用途**: 检查通过时播放
- **特征**: 愉悦、轻松、短促
- **建议**: 800Hz 频率,200ms 时长
### warning.wav
- **用途**: 检查未通过需要修复时播放
- **特征**: 警示、引起注意但不刺耳
- **建议**: 400Hz 频率,300ms 时长
### attention.wav
- **用途**: 需要深度审查时播放
- **特征**: 重要、需要立即关注
- **建议**: 600Hz 频率,400ms 时长
## 生成方法
### 方法 1: 使用 Windows 系统声音(默认回退方案)
如果声音文件不存在,系统会自动使用 Windows `winsound.Beep()` 生成简单的提示音。
### 方法 2: 使用在线工具生成
1. 访问 https://www.beepbox.net 或类似的在线音效生成器
2. 创建简单的音效
3. 导出为 WAV 格式
4. 放置到此目录
### 方法 3: 使用 Python 生成
```python
import numpy as np
from scipy.io import wavfile
def generate_beep(frequency, duration_ms, volume=0.5):
sample_rate = 44100
t = np.linspace(0, duration_ms/1000, int(sample_rate * duration_ms/1000))
wave = np.sin(2 * np.pi * frequency * t) * volume
wave = (wave * 32767).astype(np.int16)
wavfile.write('success.wav', sample_rate, wave)
generate_beep(800, 200) # 成功音
generate_beep(400, 300) # 警告音
generate_beep(600, 400) # 注意音
```
### 方法 4: 使用免费音效库
从以下网站下载免费的短音效:
- Freesound.org
- Zapsplat.com
- Mixkit.co
搜索关键词:beep, notification, success, warning, alert
## 注意事项
- 文件大小:建议每个文件 < 50KB
- 格式:WAV(最佳兼容性)
- 采样率:44.1kHz 或 48kHz
- 位深度:16-bit
- 声道:单声道或立体声都可以
## 快速开始
如果没有声音文件,系统仍然可以正常工作,会使用 Windows 系统 Beep 音效作为回退方案。
+105
View File
@@ -0,0 +1,105 @@
@echo off
chcp 65001 >nul
echo.
echo ========================================
echo 代码质量保障系统 - 测试脚本
echo ========================================
echo.
REM 检测 Python
python --version >nul 2>&1
if errorlevel 1 (
echo ❌ Python 未安装
pause
exit /b 1
)
echo ✅ Python 已安装
echo.
REM 检测依赖
echo 📦 检查 Python 依赖...
python -c "import plyer" 2>nul
if errorlevel 1 (
echo ⚠️ plyer 未安装
set "PLYER_OK=0"
) else (
echo ✅ plyer 已安装
set "PLYER_OK=1"
)
python -c "import pygame" 2>nul
if errorlevel 1 (
echo ⚠️ pygame 未安装
set "PYGAME_OK=0"
) else (
echo ✅ pygame 已安装
set "PYGAME_OK=1"
)
echo.
echo ========================================
echo 测试通知功能
echo ========================================
echo.
REM 测试通知
echo 📢 测试桌面通知和声音...
echo (如果没有声音文件,将使用系统提示音)
echo.
REM 获取脚本目录
set "SCRIPT_DIR=%~dp0"
cd /d "%SCRIPT_DIR%"
REM 测试 Hook 通知
echo [1/3] 测试成功提示...
python "hooks\notification-sender.py" success
timeout /t 2 >nul
echo [2/3] 测试警告提示...
python "hooks\notification-sender.py" warning
timeout /t 2 >nul
echo [3/3] 测试注意提示...
python "hooks\notification-sender.py" attention
timeout /t 2 >nul
echo.
echo ✅ 通知测试完成
echo.
REM 测试代码分析器
echo ========================================
echo 测试代码分析功能
echo ========================================
echo.
echo 📊 正在分析当前代码...
python "hooks\code-analyzer.py" .
echo.
echo ========================================
echo 测试结果总结
echo ========================================
echo.
if %PLYER_OK%==1 (
if %PYGAME_OK%==1 (
echo ✅ 所有依赖已安装,系统功能完整
) else (
echo ⚠️ 部分依赖缺失(pygame),通知声音可能不可用
echo 运行: pip install pygame
)
) else (
echo ⚠️ 部分依赖缺失(plyer),桌面通知可能不可用
echo 运行: pip install plyer pygame
)
echo.
echo 📝 下一步:
echo 1. 如果测试通过,运行 deploy.bat 进行部署
echo 2. 部署后重启 Claude Code
echo 3. 使用 /code-quality 命令测试
echo.
pause