开发code-quality
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"enabledPlugins": {
|
||||
"superpowers@claude-plugins-official": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"mcp__web-search-prime__webSearchPrime",
|
||||
"mcp__web-reader__webReader",
|
||||
"Bash(tree:*)",
|
||||
"Bash(powershell:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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 音效作为回退方案。
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user