mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
- Introduced architecture rules to detect circular dependencies, god classes, layer violations, and mixed concerns. - Added correctness rules focusing on null checks, empty catch blocks, unreachable code, and type coercion. - Implemented performance rules addressing nested loops, synchronous I/O, memory leaks, and unnecessary re-renders in React. - Created readability rules to improve function length, variable naming, deep nesting, magic numbers, and commented code. - Established security rules to identify XSS risks, hardcoded secrets, SQL injection vulnerabilities, and insecure random generation. - Developed testing rules to enhance test quality, coverage, and maintainability, including missing assertions and error path testing. - Documented the structure and schema for rule files in the index.md for better understanding and usage.
303 lines
7.9 KiB
Markdown
303 lines
7.9 KiB
Markdown
# Action: Deep Review
|
|
|
|
深入审查指定维度的代码质量。
|
|
|
|
## Purpose
|
|
|
|
针对单个维度进行深入审查:
|
|
- 逐文件检查
|
|
- 记录发现的问题
|
|
- 提供具体的修复建议
|
|
|
|
## Preconditions
|
|
|
|
- [ ] state.status === 'running'
|
|
- [ ] state.scan_completed === true
|
|
- [ ] 存在未审查的维度
|
|
|
|
## Dimension Focus Areas
|
|
|
|
### Correctness (正确性)
|
|
- 逻辑错误和边界条件
|
|
- Null/undefined 处理
|
|
- 错误处理完整性
|
|
- 类型安全
|
|
- 资源泄漏
|
|
|
|
### Readability (可读性)
|
|
- 命名规范
|
|
- 函数长度和复杂度
|
|
- 代码重复
|
|
- 注释质量
|
|
- 代码组织
|
|
|
|
### Performance (性能)
|
|
- 算法复杂度
|
|
- 不必要的计算
|
|
- 内存使用
|
|
- I/O 效率
|
|
- 缓存策略
|
|
|
|
### Security (安全性)
|
|
- 注入风险 (SQL, XSS, Command)
|
|
- 认证和授权
|
|
- 敏感数据处理
|
|
- 加密使用
|
|
- 依赖安全
|
|
|
|
### Testing (测试)
|
|
- 测试覆盖率
|
|
- 边界条件测试
|
|
- 错误路径测试
|
|
- 测试可维护性
|
|
- Mock 使用
|
|
|
|
### Architecture (架构)
|
|
- 分层结构
|
|
- 依赖方向
|
|
- 单一职责
|
|
- 接口设计
|
|
- 扩展性
|
|
|
|
## Execution
|
|
|
|
```javascript
|
|
async function execute(state, workDir, currentDimension) {
|
|
const context = state.context;
|
|
const dimension = currentDimension;
|
|
const findings = [];
|
|
|
|
// 从外部 JSON 文件加载规则
|
|
const rulesConfig = loadRulesConfig(dimension, workDir);
|
|
const rules = rulesConfig.rules || [];
|
|
const prefix = rulesConfig.prefix || getDimensionPrefix(dimension);
|
|
|
|
// 优先审查高风险区域
|
|
const filesToReview = state.scan_summary?.risk_areas
|
|
?.map(r => r.file)
|
|
?.filter(f => context.files.includes(f)) || context.files;
|
|
|
|
const filesToCheck = [...new Set([
|
|
...filesToReview.slice(0, 20),
|
|
...context.files.slice(0, 30)
|
|
])].slice(0, 50); // 最多50个文件
|
|
|
|
let findingCounter = 1;
|
|
|
|
for (const file of filesToCheck) {
|
|
try {
|
|
const content = Read(file);
|
|
const lines = content.split('\n');
|
|
|
|
// 应用外部规则文件中的规则
|
|
for (const rule of rules) {
|
|
const matches = detectByPattern(content, lines, file, rule);
|
|
for (const match of matches) {
|
|
findings.push({
|
|
id: `${prefix}-${String(findingCounter++).padStart(3, '0')}`,
|
|
severity: rule.severity || match.severity,
|
|
dimension: dimension,
|
|
category: rule.category,
|
|
file: file,
|
|
line: match.line,
|
|
code_snippet: match.snippet,
|
|
description: rule.description,
|
|
recommendation: rule.recommendation,
|
|
fix_example: rule.fixExample
|
|
});
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// 跳过无法读取的文件
|
|
}
|
|
}
|
|
|
|
// 保存维度发现
|
|
Write(`${workDir}/findings/${dimension}.json`, JSON.stringify(findings, null, 2));
|
|
|
|
return {
|
|
stateUpdates: {
|
|
reviewed_dimensions: [...(state.reviewed_dimensions || []), dimension],
|
|
current_dimension: null,
|
|
[`findings.${dimension}`]: findings
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 从外部 JSON 文件加载规则配置
|
|
* 规则文件位于 specs/rules/{dimension}-rules.json
|
|
* @param {string} dimension - 维度名称 (correctness, security, etc.)
|
|
* @param {string} workDir - 工作目录 (用于日志记录)
|
|
* @returns {object} 规则配置对象,包含 rules 数组和 prefix
|
|
*/
|
|
function loadRulesConfig(dimension, workDir) {
|
|
// 规则文件路径:相对于 skill 目录
|
|
const rulesPath = `specs/rules/${dimension}-rules.json`;
|
|
|
|
try {
|
|
const rulesFile = Read(rulesPath);
|
|
const rulesConfig = JSON.parse(rulesFile);
|
|
return rulesConfig;
|
|
} catch (e) {
|
|
console.warn(`Failed to load rules for ${dimension}: ${e.message}`);
|
|
// 返回空规则配置,保持向后兼容
|
|
return { rules: [], prefix: getDimensionPrefix(dimension) };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 根据规则的 patternType 检测代码问题
|
|
* 支持的 patternType: regex, includes
|
|
* @param {string} content - 文件内容
|
|
* @param {string[]} lines - 按行分割的内容
|
|
* @param {string} file - 文件路径
|
|
* @param {object} rule - 规则配置对象
|
|
* @returns {Array} 匹配结果数组
|
|
*/
|
|
function detectByPattern(content, lines, file, rule) {
|
|
const matches = [];
|
|
const { pattern, patternType, negativePatterns, caseInsensitive } = rule;
|
|
|
|
if (!pattern) return matches;
|
|
|
|
switch (patternType) {
|
|
case 'regex':
|
|
return detectByRegex(content, lines, pattern, negativePatterns, caseInsensitive);
|
|
|
|
case 'includes':
|
|
return detectByIncludes(content, lines, pattern, negativePatterns);
|
|
|
|
default:
|
|
// 默认使用 includes 模式
|
|
return detectByIncludes(content, lines, pattern, negativePatterns);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 使用正则表达式检测代码问题
|
|
* @param {string} content - 文件完整内容
|
|
* @param {string[]} lines - 按行分割的内容
|
|
* @param {string} pattern - 正则表达式模式
|
|
* @param {string[]} negativePatterns - 排除模式列表
|
|
* @param {boolean} caseInsensitive - 是否忽略大小写
|
|
* @returns {Array} 匹配结果数组
|
|
*/
|
|
function detectByRegex(content, lines, pattern, negativePatterns, caseInsensitive) {
|
|
const matches = [];
|
|
const flags = caseInsensitive ? 'gi' : 'g';
|
|
|
|
try {
|
|
const regex = new RegExp(pattern, flags);
|
|
let match;
|
|
|
|
while ((match = regex.exec(content)) !== null) {
|
|
const lineNum = content.substring(0, match.index).split('\n').length;
|
|
const lineContent = lines[lineNum - 1] || '';
|
|
|
|
// 检查排除模式 - 如果行内容匹配任一排除模式则跳过
|
|
if (negativePatterns && negativePatterns.length > 0) {
|
|
const shouldExclude = negativePatterns.some(np => {
|
|
try {
|
|
return new RegExp(np).test(lineContent);
|
|
} catch {
|
|
return lineContent.includes(np);
|
|
}
|
|
});
|
|
if (shouldExclude) continue;
|
|
}
|
|
|
|
matches.push({
|
|
line: lineNum,
|
|
snippet: lineContent.trim().substring(0, 100),
|
|
matchedText: match[0]
|
|
});
|
|
}
|
|
} catch (e) {
|
|
console.warn(`Invalid regex pattern: ${pattern}`);
|
|
}
|
|
|
|
return matches;
|
|
}
|
|
|
|
/**
|
|
* 使用字符串包含检测代码问题
|
|
* @param {string} content - 文件完整内容 (未使用但保持接口一致)
|
|
* @param {string[]} lines - 按行分割的内容
|
|
* @param {string} pattern - 要查找的字符串
|
|
* @param {string[]} negativePatterns - 排除模式列表
|
|
* @returns {Array} 匹配结果数组
|
|
*/
|
|
function detectByIncludes(content, lines, pattern, negativePatterns) {
|
|
const matches = [];
|
|
|
|
lines.forEach((line, i) => {
|
|
if (line.includes(pattern)) {
|
|
// 检查排除模式 - 如果行内容包含任一排除字符串则跳过
|
|
if (negativePatterns && negativePatterns.length > 0) {
|
|
const shouldExclude = negativePatterns.some(np => line.includes(np));
|
|
if (shouldExclude) return;
|
|
}
|
|
|
|
matches.push({
|
|
line: i + 1,
|
|
snippet: line.trim().substring(0, 100),
|
|
matchedText: pattern
|
|
});
|
|
}
|
|
});
|
|
|
|
return matches;
|
|
}
|
|
|
|
/**
|
|
* 获取维度前缀(作为规则文件不存在时的备用)
|
|
* @param {string} dimension - 维度名称
|
|
* @returns {string} 4字符前缀
|
|
*/
|
|
function getDimensionPrefix(dimension) {
|
|
const prefixes = {
|
|
correctness: 'CORR',
|
|
readability: 'READ',
|
|
performance: 'PERF',
|
|
security: 'SEC',
|
|
testing: 'TEST',
|
|
architecture: 'ARCH'
|
|
};
|
|
return prefixes[dimension] || 'MISC';
|
|
}
|
|
```
|
|
|
|
## State Updates
|
|
|
|
```javascript
|
|
return {
|
|
stateUpdates: {
|
|
reviewed_dimensions: [...state.reviewed_dimensions, currentDimension],
|
|
current_dimension: null,
|
|
findings: {
|
|
...state.findings,
|
|
[currentDimension]: newFindings
|
|
}
|
|
}
|
|
};
|
|
```
|
|
|
|
## Output
|
|
|
|
- **File**: `findings/{dimension}.json`
|
|
- **Location**: `${workDir}/findings/`
|
|
- **Format**: JSON array of Finding objects
|
|
|
|
## Error Handling
|
|
|
|
| Error Type | Recovery |
|
|
|------------|----------|
|
|
| 文件读取失败 | 跳过该文件,记录警告 |
|
|
| 规则执行错误 | 跳过该规则,继续其他规则 |
|
|
|
|
## Next Actions
|
|
|
|
- 还有未审查维度: 继续 action-deep-review
|
|
- 所有维度完成: action-generate-report
|