wk-code-review について
単一リポジトリの変更を監査するコードレビュー用スキルで、Java と XML ファイルを中心に扱います。計画とチェックポイントを作成し、再開可能なバッチレビューを経て、7 つの観点の結果を重複排除して報告します。
主な機能
- 01Java と XML の変更をレビュー
- 027 つのコード監査観点を確認
- 03全体計画とバッチ計画を作成
- 04進捗チェックポイントから再開
- 05指摘を統合・重複排除して報告
活用シーン
- 01基準ブランチとの差分を監査
- 02大規模な変更を再開可能なバッチでレビュー
- 03修正作業向けの統合レポートを作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ whalezhao/ wk-code-review --skill wk-code-reviewインストール後、Claude Code で/wk-code-reviewを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdreferences/.DS_Storejava-specification_02.mdgit-specification.mderror-code-specification.mdfrontend-backend-conventions.mdjava-specification_01.mdnaming-specification.mdi18n-specification.md詳細
WK コードレビュー Skill
自動モードの判定
確認手順を実行する前に、まず現在の実行モードを判定してください。
-
最新の system-reminder にある
auto mode is activeの識別子を読み取ります -
または、現在の会話コンテキストに
auto_mode、autonomous、continuousなどのキーワードがあるか確認します -
判定できない場合は、**手動モード(デフォルト)**として扱います
-
Auto Mode:ユーザーへの確認手順をすべて省略し、監査を直接実行します
- 確認メッセージを出力せず、ユーザーの入力を待ちません
- Phase 0 ではデフォルトの出力ディレクトリを使用します。優先して
{OUTPUT_DIR}/を使用し、定義されていない場合はデスクトップの~/Desktop/code-review/に保存します - Phase 1.5 では直接確認し、再開またはスキップします
- Phase 2.6 では、各バッチの完了後に自動で次のバッチへ進みます
-
手動モード(デフォルト):手順に厳密に従い、すべての確認ポイントを有効にします
Skill の呼び出し元は、呼び出し時に実行モード(auto_mode=true/false)を宣言する責任があります。
目標
7つの観点を網羅した包括的なコード監査を実行します。
- 規約監査 — 命名、ログ、例外、トランザクション、MyBatis、Spring、並行処理、MySQL、フロントエンドとバックエンドの連携規約
- ビジネスロジック監査 — ビジネスルールの実装、境界条件、エラー処理の完全性を検証します
- 設計の妥当性監査 — アーキテクチャ設計、トランザクション境界、データの一貫性、設計上の選択を評価します
- コードパフォーマンス監査 — コードのパフォーマンス、設計の妥当性、コードのフォールトトレランス、安全策を評価します
- 信頼性監査 — MQ 消費の冪等性、定期タスクの重複実行防止、分散ロック、リソースリーク、Istio/K8s のシナリオを確認します
- クラッシュ後の復旧とロジックの継続性監査 — ステートマシンの完全性、再入可能性、補償メカニズム、分散トランザクションの境界(新たに追加された重点項目)
基本原則
⚠️ 必須要件:監査を実行するかどうかを決める前に、必ず監査計画ファイルを生成してください。
- 監査計画ファイルを
{OUTPUT_DIR}/<branch>-plan.mdに実際に書き込む必要があります- 各Agentは、自身の計画ファイルと規約ファイルを読み込んで監査を実行します
- 各バッチのAgentが完了した後、主計画内のマージ待ち結果ファイル一覧を更新します
- すべてのAgentの結果を最終的な監査レポートにまとめます
アーキテクチャ上の制限:この Skill は単一リポジトリのシナリオのみをサポートします。複数リポジトリ(monorepo 内の複数リポジトリ、または異なるリポジトリにあるサービス)の場合は、この Skill を個別に呼び出すか、CI レイヤーの全体監査ツールを使用してください。
Phase 0:出力ディレクトリの確認
⚠️ 監査を実行する前に、必ず出力ディレクトリを確認してください。以降のすべての手順でこのディレクトリを使用します。
AskUserQuestion ツールを使用してユーザーに尋ねます。
请选择审计报告的输出目录(审计结果将保存至此目录):
| 選択肢 | パス | 説明 |
|---|---|---|
| デフォルト | {OUTPUT_DIR}/ | これまで使用していたディレクトリ |
| 現在のディレクトリ | {現在のgitリポジトリのルートディレクトリ}/code-review/ | コードと同じ階層にあるディレクトリ |
| カスタム | ユーザー入力 | ユーザーが絶対パスを手動で入力 |
- 手動モード:必ずユーザーに尋ね、ユーザーが選択してから続行します
- Auto Mode:デフォルトのパス
{OUTPUT_DIR}/を使用し、確認は行いません
ディレクトリ名の推奨:出力ディレクトリ名には、
{OUTPUT_DIR}/{branch-name}/のようにブランチ名を含めることを推奨します。確認後の記録:
OUTPUT_DIR変数は、この監査セッション全体で有効です。以降のすべての Phase でこの変数を参照し、再度確認することはありません。
Phase 0.5:事前チェック
以下のコマンドを実行してコンテキストを取得します。
# 1. 获取当前分支(如果没有传入分支名,则取当前分支)
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
echo "当前分支: $CURRENT_BRANCH"
# 2. 获取基准分支(优先使用传入的 BASE_BRANCH,否则检测仓库默认分支)
BASE_BRANCH=${BASE_BRANCH:-$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||')}
# 3. 检查差异文件数
git diff --name-only ${BASE_BRANCH}...${BRANCH:-$CURRENT_BRANCH} 2>/dev/null | wc -l
# 4. 获取提交历史(理解需求背景)
git log ${BASE_BRANCH}..${BRANCH:-$CURRENT_BRANCH} --oneline -15
# 5. 获取变更统计
git diff --stat ${BASE_BRANCH}...${BRANCH:-$CURRENT_BRANCH}
差分がない場合:「現在のブランチと ${BASE_BRANCH} に差分はありません」と通知し、監査を終了します。
パラメーターの説明:
${BRANCH}:監査対象のブランチ名(省略可能。デフォルトは現在のブランチ)${BASE_BRANCH}:ベースブランチ名(省略可能。リポジトリのデフォルトブランチを自動検出します。通常は master/main)
Phase 1:主計画ファイルの生成
1.1 変更ファイルの集計
# 获取所有变更的Java和XML文件
# 注意:使用 ${BRANCH:-$CURRENT_BRANCH} 而非 HEAD,确保多批次执行时取到正确分支
git diff --name-only ${BASE_BRANCH}...${BRANCH:-$CURRENT_BRANCH} 2>/dev/null | grep -E '\.(java|xml)$'
1.2 ファイルの選別
監査必須のファイル
- すべての
*.javaファイル(除外規則に該当するものを除く) - すべての
*Mapper.xmlファイル
除外規則
| パターン | 説明 | 監査対象に含めるか |
|---|---|---|
*Test.java / **/test/** | テストクラス | ❌ 除外 |
**/generated/** | 生成コード | ❌ 除外 |
**/target/** | ビルド成果物 | ❌ 除外 |
**/pom.xml | Maven 設定 | ❌ 除外 |
**/resources/META-INF/** | Spring/META-INF 設定 | ❌ 除外 |
**/resources/application*.yml | アプリケーション設定ファイル | ❌ 除外 |
**/resources/application*.properties | アプリケーション設定ファイル | ❌ 除外 |
**/resources/static/** | 静的リソース | ❌ 除外 |
**/resources/templates/** | テンプレートファイル | ❌ 除外 |
**/resources/i18n/** | 国際化リソースファイル | ❌ 除外 |
**/resources/mapper/**/*.xml | MyBatis XML | ✅ 監査対象に含める(SQL インジェクション、文字列連結を確認) |
**/resources/migration/**/*.sql | データベースマイグレーションスクリプト | ✅ 監査対象に含める(SQL の品質、インデックスを確認) |
YAML 設定ファイルについて:今回の変更に
application.yml/application.propertiesが含まれる場合、監査対象には含めません(除外規則に記載済み)。設定の妥当性(コネクションプールのサイズ、タイムアウト設定など)は運用レイヤーに属するため、コード監査の対象外です。
1.3 主計画ファイルの生成
出力先:{OUTPUT_DIR}/<branch-name>-plan.md
Write ツールを使用して主計画ファイルを作成し、以下の内容を含めます。
-
集計情報テーブル
- 変更ファイルの合計数、Java ファイル数、XML ファイル数、監査対象ファイル数
-
監査バッチ一覧
- モジュール/階層ごとにグループ化した、各バッチのファイル一覧
-
実行手順(手順ごとに確認)
-
マージ待ち結果ファイル一覧
- 初期状態は空とし、各バッチの完了後に随時追加します
-
重点確認項目
1.4 各Agentの個別計画ファイルの生成
出力先:{OUTPUT_DIR}/<branch-name>-plan-<バッチ番号>-<バッチ名>.md
注意:バッチ名に
/文字を含めないでください。ファイルシステム上のパスに関する問題を避けるため、-に置き換えてください。
各Agentの計画ファイルには、以下を必ず含めてください。
- 今回のバッチのファイル一覧(完全なパス)
- 要件の背景(コミット履歴の要約)
- 規約ファイル一覧(Agent は rules によって自動的に読み込むため、手動で読み込む必要はありません。必要に応じて、以下の絶対パスを参考にできます)
- 監査観点の説明
- 結果ファイルのパス
1.5 計画の概要を出力して確認を待つ(手動モード)
📋 审计计划已生成
分支:{branch-name}
变更文件:{total-files} 个
应审计:{to-audit-files} 个
审计批次:
批次1:{name} ({n}个文件)
批次2:{name} ({n}个文件)
...
执行步骤:
Step 1: 批次1审计(启动{n1}个Agent)→ 更新待合并列表
Step 2: 批次2审计(启动{n2}个Agent)→ 更新待合并列表
Step 3: 汇总所有结果,生成最终报告
Step 4: 输出摘要
计划文件:
主计划:{OUTPUT_DIR}/{branch-name}-plan.md
各批次:{OUTPUT_DIR}/{branch-name}-plan-*.md
请确认是否按此计划执行审计。
手動モード:ユーザーの確認後にのみ、Phase 2 に進んで監査を実行できます。 Auto Mode:確認を省略し、Phase 1.5 に直接進みます。
Phase 1.5:中断の確認と再開
Phase 2 を実行する前に、未完了の監査がないか確認します。
# 检查是否存在进行中的审计状态文件
STATUS_FILE="{OUTPUT_DIR}/${BRANCH}-status.json"
PLAN_FILE="{OUTPUT_DIR}/${BRANCH}-plan.md"
RESULT_FILES=$(ls {OUTPUT_DIR}/${BRANCH}-result-*.json 2>/dev/null)
# 优先检查 status.json(最可靠的进度来源)
if [ -f "$STATUS_FILE" ]; then
echo "发现历史审计状态文件"
cat "$STATUS_FILE"
# 解析 completed_batches 和 pending_batches 确定断点
elif [ -f "$PLAN_FILE" ]; then
echo "未找到 status.json,但发现主计划文件,视为完全中断"
# 无 status.json 但有 plan.md,从 Phase 1.5 恢复
fi
if [ -n "$RESULT_FILES" ]; then
echo "发现历史结果文件:"
echo "$RESULT_FILES"
fi
再開する場合:
-
完全な中断:主計画は存在するものの、完了した batch がない
- 手動モード:ユーザーに「未完了の監査計画が見つかりました。続行しますか?」と尋ねます
- Auto Mode:Phase 1.5 から自動的に再開し、最初の未完了バッチから開始します
-
一部完了:一部の batch は完了しているものの、すべては完了していない
- status.json の
completed_batchesとpending_batches配列を読み取ります completed_batchesに含まれるバッチをスキップしますpending_batchesの最初のバッチから実行を再開します
- status.json の
-
新規監査:過去の監査ファイルが存在しない
- 新規監査の手順を通常どおり開始します
Phase 2:監査の実行(手順に従って実行)
Step 1-N:バッチ監査
各バッチで、以下の手順を実行します。
2.1 進捗の確認
# 确认本批次尚未完成
BATCH_RESULT="{OUTPUT_DIR}/${BRANCH}-result-${BATCH_ID}-merged.json"
if [ -f "$BATCH_RESULT" ]; then
echo "批次 ${BATCH_ID} 已完成,跳过"
# 若在脚本上下文中:exit 0;若在交互上下文中:continue 到下一批次
fi
2.2 進捗チェックポイントの作成
進捗ファイル {OUTPUT_DIR}/${BRANCH}-status.json に書き込みます。
{
"branch": "{branch-name}",
"timestamp": "{current-time}",
"phase": 2,
"current_batch": {n},
"total_batches": {total},
"completed_batches": [{已完成批次}],
"pending_batches": [{待执行批次}],
"in_progress": true
}
2.3 启动Agent(每批次最多4个并行)
每个Agent执行:
- Read 计划文件
- Read 每个待审计文件的完整内容
- Bash git diff 获取代码变更
- 逐维度逐文件分析,对每个维度明确输出结论(有问题/无问题/不适用)
- 将结果写入JSON临时文件(必须遵守 JSON 安全规则,见本模板末尾「JSON 输出安全规则」章节)
- 使用 Read 工具重新读取JSON文件,确认格式正确
- 使用
python3 -c "import json; json.load(open('文件路径'))"验证JSON合法性,若失败则修复后重新验证
⚠️ 逐维度强制要求:
对批次的每个文件,必须按以下顺序逐维声明:
| 维度 | 必须声明 |
|---|---|
| A. 规范审计 | 有/无问题(子类型见 Agent 计划模板 A 节) |
| B. 业务逻辑 | 有/无问题(子类型见 Agent 计划模板 B 节) |
| C. 方案合理性 | 有/无问题(子类型见 Agent 计划模板 C 节) |
| D. 性能 | 有/无问题(子类型见 Agent 计划模板 D 节) |
| E. 可靠性(Istio/K8s) | 有/无问题(子类型见 Agent 计划模板 E 节) |
| F. 宕机恢复与逻辑接续 | 有/无问题(重点审计,子类型见 Agent 计划模板 F 节) |
| G. 安全审计 | 有/无问题(子类型见 Agent 计划模板 G 节) |
维度审计详细清单:各维度的具体检查项(如 A 节的 MyBatis/日志/异常规范、F 节的 FMEA 追问清单等)见下方「Agent 计划文件模板」→「审计维度」章节。Agent 生成计划文件时需将对应维度内容写入计划。
⚠️ 不得跳维度:每个文件必须对 A-G 七个维度逐一声明结论,不能只输出有问题的维度。
⚠️ F维度特别提醒:宕机恢复审计是本次新增的重点维度。审计时必须追问:
- "如果在这行代码之后JVM宕机,会发生什么?"
- "重启后这条消息会被重新投递吗?业务逻辑能否正确处理?"
- "跨系统的两阶段操作(DB+MQ、DB+OSS、MQ+外部服务)是否有补偿机制?"
Agent异常处理:
- Agent 应在执行过程中每处理 5 个文件后保存一次中间结果
- 如果 Agent 崩溃,下次恢复时应检查中间结果并从断点继续
- 使用结果文件命名约定:
result-<batch>-<agent-id>-checkpoint-{n}.json - 检查点恢复逻辑:重启 Agent 时,检查是否存在
result-<batch>-<agent-id>-checkpoint-*.json,找到最大序号的检查点,读取已完成文件列表,跳过这些文件,从下一个文件开始审计。审计完成后合并所有检查点结果。
2.4 监控进度
- 使用 TaskList 查看任务状态
- 超时时间动态计算:
超时(min) = max(5, min(文件数 / 2, 20))(最少5分钟,最多20分钟) - 每 1 min 检查一次是否有 Agent 超时或异常
2.5 合并批次结果
本批次所有 Agent 完成后:
-
JSON 合法性校验与修复(在去重合并之前,必须先确保所有 Agent 结果文件格式正确)
- 对每个 Agent 的结果文件执行
python3 -c "import json; json.load(open('文件路径'))"校验 - 若校验通过:进入去重合并流程
- 若校验失败:使用以下修复流程
-
用 Bash 执行
python3脚本定位损坏位置:python3 -c " import json, sys try: json.load(open('${RESULT_FILE}')) print('JSON_VALID') except json.JSONDecodeError as e: print(f'JSON_ERROR: line={e.lineno}, col={e.colno}, msg={e.msg}') " -
用 Read 工具读取文件,定位损坏行附近的字段
-
常见损坏模式及修复方法:
损坏模式 原因 修复方法 字段值中出现了未配对的双引号 "问题代码或描述中的双引号未转义将字段值中的双引号替换为单引号或 \"文件中出现了实际的换行符(非 \n字面量)描述或宕机后果字段包含实际换行将实际换行替换为 \n字面量\\后紧跟非转义字符反斜杠未双重转义 补充为 \\\\字段值末尾缺少引号 引号被内容中的 "提前关闭找到并转义内容中多余的 " -
修复后重新执行校验,直到通过
-
若同一文件修复 3 次仍未通过,标记该 Agent 结果为异常,按 场景4:Agent 返回空结果 处理
-
- 对每个 Agent 的结果文件执行
-
批次内去重(同一 Agent 内)
- 按
文件路径 + 行号 + 维度 + 问题类型去重 - 保留严重程度最高的问题(CRITICAL > WARNING > SUGGESTION)
- 按
-
批次间去重(同一批次不同 Agent 间)
- 读取该批次所有 Agent 的结果文件
- 按
文件路径 + 行号 + 维度 + 问题类型去重 - 同一个问题多个 Agent 发现时,保留 CRITICAL > WARNING > SUGGESTION
-
合并到批次结果文件
- 写入
{OUTPUT_DIR}/${BRANCH}-result-${BATCH_ID}-merged.json - 写入后必须再次执行
python3JSON 校验,确认合并结果文件合法
- 写入
-
立即更新进度检查点(必须在合并文件写入后立即执行,顺序不可颠倒)
{ "...": "...", "completed_batches": [..., {n}], "pending_batches": [{剩余批次}], "last_completed_at": "{timestamp}" }⚠️ 顺序保证:步骤 3(合并文件写入)和步骤 4(status 更新)必须是原子操作。若 status 更新失败,下次恢复时步骤 2.1 会检测到 merged.json 已存在并跳过,status.json 的
pending_batches不准确但无害。
⚠️ 注意:跨批次的全局去重统一在 Phase 3 执行,此处仅处理批次内和批次间去重。
2.6 更新主计划中的待合并列表
每批次完成并合并后:
- 更新主计划的待合并列表
- 追加本批次的合并结果文件路径
- 标记该批次为 ✅ 完成
手动模式:输出确认提示
✅ 批次{n}审计完成(共 {file-count} 个文件,{problem-count} 个问题)
本批次结果文件:
- {OUTPUT_DIR}/{batch-name}-merged.json
已更新主计划待合并列表。
共 {total-n} 个结果文件待汇总。
是否继续下一批次?
Auto Mode:自动继续下一批次,不等待确认。
2.7 异常恢复策略
场景1:单个Agent失败
- 记录失败 Agent 的文件列表
- 启动备用 Agent 重新审计这些文件
- 最多重试 2 次
场景2:整批次超时
- 将该批次分解为更小的子批次(每个 3 文件)
- 重新启动,每个子批次用 1 个 Agent
场景3:主进程中断
- 下次恢复时自动检测进度检查点
- 从上次未完成的批次开始
场景4:Agent 返回空结果
- Agent 返回了结果但问题列表为空,视为异常
- 检查 Agent 是否正确读取了所有文件内容
- 启动备用 Agent 重新审计该批次所有文件
- 如果连续2次空结果,则报告该批次审计异常,需人工介入
2.8 循环执行直到所有批次完成
重复 Step 1-N 直到所有批次完成
更新进度检查点为:
{
"...": "...",
"phase": 3,
"in_progress": false,
"completed_at": "{timestamp}"
}
Phase 3:汇总结果
3.1 执行全局去重脚本(关键步骤)
⚠️ 必须在生成报告前执行此步骤,否则会导致 KeyError。
- 使用 Bash 执行 Python 脚本(见下方 Phase 3.2)
- 脚本会:
- 收集所有批次结果文件(
*-result-*-merged.json) - 统一字段名(
file/文件/path→文件) - 全局去重
- 按维度权重排序
- 分配 ISS-{序号} ID
- 生成
{OUTPUT_DIR}/{BRANCH}-result-all.json
- 收集所有批次结果文件(
3.2 全局去重 Python 脚本
必须执行此脚本:
cd {OUTPUT_DIR}
python3 << 'PYTHON_EOF'
import json
import glob
from collections import Counter
BRANCH = "{BRANCH}"
# 收集所有批次结果文件
merged_files = glob.glob(f"{BRANCH}-result-*-merged.json")
if not merged_files:
print(f"未找到: {BRANCH}-result-*-merged.json")
exit(1)
all_issues = []
for f in merged_files:
with open(f, 'r', encoding='utf-8') as fp:
data = json.load(fp)
if isinstance(data, list):
all_issues.extend(data)
else:
all_issues.extend(data.get("问题列表", data.get("issues", [])))
print(f"收集问题: {len(all_issues)} 个")
# 字段名标准化
for p in all_issues:
p["文件"] = p.get("文件") or p.get("file") or p.get("path") or ""
p["行号"] = str(p.get("行号") or p.get("line") or "")
p["维度"] = p.get("维度") or p.get("dimension") or ""
p["类型"] = p.get("类型") or p.get("type") or ""
p["严重程度"] = p.get("严重程度") or p.get("severity") or "WARNING"
# 全局去重
seen = set()
deduped = []
for p in all_issues:
key = (p["文件"], p["行号"], p["维度"], p["类型"])
if key not in seen:
seen.add(key)
deduped.append(p)
print(f"去重后: {len(deduped)} 个")
# 统计涉及文件清单(按问题数降序,全部列出,不得截断)
SEV_ORDER = {"CRITICAL": 0, "WARNING": 1, "SUGGESTION": 2}
file_stats = {}
for p in deduped:
f = p["文件"]
if f not in file_stats:
file_stats[f] = {"count": 0, "severities": []}
file_stats[f]["count"] += 1
file_stats[f]["severities"].append(p.get("严重程度", "WARNING"))
# 计算每个文件的最高严重程度
file_list = []
for f, stats in file_stats.items():
# 取最高严重程度
min_sev = min(stats["severities"], key=lambda s: SEV_ORDER.get(s, 1))
file_list.append((f, stats["count"], min_sev))
# 按问题数降序
file_list.sort(key=lambda x: (-x[1], SEV_ORDER.get(x[2], 1)))
all_files_sorted = file_list
print(f"涉及文件: {len(all_files_sorted)} 个")
# 排序
DIM_ORDER = {"G": 0, "F": 1, "E": 2, "B": 3, "A": 4, "C": 5, "D": 6}
deduped.sort(key=lambda p: (
next((v for k, v in DIM_ORDER.items() if k in p.get("维度", "")), 7),
SEV_ORDER.get(p.get("严重程度", "WARNING"), 1),
p.get("文件", "")
))
# 分配ID
for i, p in enumerate(deduped, 1):
p["id"] = f"ISS-{i:03d}"
# 保存
result_all = {
"问题列表": deduped,
"文件清单": [{"文件": f, "问题数": c, "最高严重程度": s} for f, c, s in all_files_sorted]
}
with open(f"{BRANCH}-result-all.json", 'w', encoding='utf-8') as fp:
json.dump(result_all, fp, ensure_ascii=False, indent=2)
print(f"保存到: {BRANCH}-result-all.json")
# 统计
sev = Counter(p.get("严重程度") for p in deduped)
print(f"总问题数: {len(deduped)}")
print(f"CRITICAL: {sev.get('CRITICAL', 0)}")
print(f"WARNING: {sev.get('WARNING', 0)}")
print(f"SUGGESTION: {sev.get('SUGGESTION', 0)}")
PYTHON_EOF
3.3 生成最终报告
⚠️ 前置步骤:必须先执行 Phase 3.2 的 Python 脚本生成
{OUTPUT_DIR}/{BRANCH}-result-all.json,然后从此文件读取已排序、去重、分配ID的问题列表。
⚠️ 强制要求:JSON 中的所有数据必须完整写入 .md 报告,不得遗漏任何一个问题。
result-all.json是中间产物,在 Phase 3.6 会被清理删除。.md报告是唯一最终产物,也是下游review-bug-fixSkill 的唯一数据源。如果 JSON 中有问题没有写入 .md,该问题将永久丢失,无法恢复。具体要求:
问题列表中的每一条问题,都必须出现在 .md 报告对应维度章节的表格中文件清单中的每一个文件,都必须出现在 .md 报告的"涉及文件清单"表格中- 如果 Write 工具因内容过长无法一次性写入,必须分多次写入,直到全部问题写完
- 分次写入策略:以维度章节(3.3.2~3.3.8)为天然分界点,每次 Write 至少完整写入一个维度章节(含该维度所有文件的所有问题),不得在表格中间断开。如需进一步拆分,按文件分组边界切分,确保每个文件的表格完整
- 写完后执行 Phase 3.4 校验,确认 .md 中的 ISS 编号数量与 JSON 问题数完全一致
使用 Write 工具创建 {OUTPUT_DIR}/<branch-name>.md
报告按以下十一个部分组织,每个审计维度独立一章,章内先按严重程度排序,再按文件分组。同一文件的问题归入同一个文件节点下。全部问题必须从 {OUTPUT_DIR}/{BRANCH}-result-all.json 读取。
📐 维度章节标准化模板:3.3.2~3.3.8 七个维度章节均遵循统一模板:
- 维度说明 → 2. 按文件分组的问题表格(含 ID/行号/子类型/描述/问题代码/修复建议列;F 维度额外含宕机后果列)→ 3. 本维度子类型分类表 → 4. 无问题时输出 "✅ 未发现" 声明
各维度仅子类型和表格列数(F 维度 7 列,其余 6 列)不同,结构完全一致。
⚠️ 问题编号规则:全局去重后,按维度权重从高到低(G→F→E→B→A→C→D)、同维度内按严重程度(CRITICAL→WARNING→SUGGESTION)、同严重程度内按文件路径排序,为每个问题分配唯一ID:
ISS-{3位序号}(如 ISS-001, ISS-002)。此ID用于下游 review-bug-fix 追踪,必须在报告表格和JSON中一致出现。
3.3.1 问题统计总览
按严重程度:
| 严重程度 | 数量 |
|---|---|
| 🔴 CRITICAL | {n} |
| 🟡 WARNING | {n} |
| 🟢 SUGGESTION | {n} |
按维度(全局去重后):
| 维度 | CRITICAL | WARNING | SUGGESTION | 权重 |
|---|---|---|---|---|
| A. 规范审计 | {n} | {n} | {n} | ×1.5 |
| B. 业务逻辑 | {n} | {n} | {n} | ×1.5 |
| C. 方案合理性 | {n} | {n} | {n} | ×1 |
| D. 性能 | {n} | {n} | {n} | ×1 |
| E. 可靠性(Istio/K8s) | {n} | {n} | {n} | ×2 |
| F. 宕机恢复与逻辑接续 | {n} | {n} | {n} | ×2.5 |
| G. 安全审计 | {n} | {n} | {n} | ×3 |
涉及文件清单(出现问题的所有文件,去重,按问题数降序):
⚠️ 强制要求:此表格必须列出所有出现问题的文件,不得遗漏,不得截断。从
{BRANCH}-result-all.json的文件清单字段读取数据后填入。
生成步骤:
- 读取
{OUTPUT_DIR}/{BRANCH}-result-all.json的文件清单字段 - 按以下格式生成表格,每行对应一个文件:
- 第一列:文件路径(使用反引号包裹,便于复制)
- 第二列:问题数
- 第三列:该文件所有问题中的最高严重程度
示例(真实数据):
| 文件 | 问题数 | 最高严重程度 |
|---|---|---|
cn/cisdigital/datakits/di/task/biz/service/TaskServiceImpl.java | 5 | WARNING |
cn/cisdigital/datakits/di/task/biz/repository/mapper/TaskMapper.xml | 3 | CRITICAL |
| ... | ... | ... |
若 文件清单 字段为空,报告生成失败,必须修复 Phase 3.2 的 Python 脚本。此表格填写完成后,result-all.json 的使命已完成,将在 Phase 3.6 清理中删除。
3.3.2 A. 规范审计问题(按类分组)
维度说明:覆盖命名规范、日志规范、异常规范、事务规范、MyBatis规范、并发规范、i18n规范、包命名规范、枚举规范、循环规范、API交互规范。
排序规则:维度内先 CRITICAL → WARNING → SUGGESTION,同一严重程度内按文件分组。
### {类名A.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {n} | {日志规范/异常规范/...} | {描述} | `{问题代码}` | {修复建议} |
| ISS-{nnn} | {n} | {...} | {...} | `{...}` | {...} |
### {类名B.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... |
子类型分类:
| 子类型 | 说明 |
|---|---|
命名规范 | 类名/方法名/变量名/包名违反命名约定 |
日志规范 | 日志使用字符串拼接、未使用占位符{}、debug/info缺少条件判断 |
异常规范 | 使用RuntimeException/throw new Exception、未使用ErrorCode枚举 |
事务规范 | @Transactional加在非public方法、事务范围包含网络调用 |
MyBatis规范 | XML中${}拼接、OGNL表达式调用静态方法、LIMIT/OFFSET拼接 |
并发规范 | ThreadLocal未在finally中remove、DateTimeFormatter重复创建 |
循环规范 | 循环内单条insert/update/delete |
i18n规范 | 硬编码国际化文本、使用非dot.case格式的key |
枚举规范 | 枚举未实现BizEnum、使用ordinal比较 |
API交互规范 | Long未序列化为String、时间未使用毫秒时间戳 |
如本维度无问题:
### A. 规范审计
✅ 本次变更未发现规范审计问题。
3.3.3 B. 业务逻辑问题(按类分组)
维度说明:验证业务规则实现、边界条件处理、错误处理完整性、数据一致性。
### {类名A.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {n} | {需求覆盖/边界条件/null检查/数据一致性} | {描述} | `{问题代码}` | {修复建议} |
### {类名B.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... |
子类型分类:
| 子类型 | 说明 |
|---|---|
需求覆盖 | 代码未完整实现需求中的业务规则 |
边界条件 | 数组越界、数值边界(最大值/最小值)、空指针风险 |
null检查 | 入参未校验、返回值未判空、级联对象访问未判空 |
数据一致性 | 并发修改未加锁、分布式场景数据不一致 |
如本维度无问题:
### B. 业务逻辑
✅ 本次变更未发现业务逻辑问题。
3.3.4 C. 方案合理性(按类分组)
维度说明:评估架构设计、N+1查询、重复代码、过度设计。
### {类名A.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {n} | {N+1查询/重复代码/过度设计/事务边界} | {描述} | `{问题代码}` | {修复建议} |
### {类名B.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... |
子类型分类:
| 子类型 | 说明 |
|---|---|
N+1查询 | 循环内执行单条SQL查询 |
重复代码 | 相同逻辑在不同类中重复实现,未抽取复用 |
过度设计 | 不必要的抽象、多层包装导致可读性下降 |
事务边界 | 长事务、跨网络调用的操作放在事务内 |
如本维度无问题:
### C. 方案合理性
✅ 本次变更未发现方案合理性问题。
3.3.5 D. 性能问题(按类分组)
维度说明:评估分页限制、批量操作、异步超时、大数据量处理、慢查询。
### {类名A.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {n} | {分页限制/批量操作/异步超时/大数据量/慢查询} | {描述} | `{问题代码}` | {修复建议} |
### {类名B.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... |
子类型分类:
| 子类型 | 说明 |
|---|---|
分页限制 | 未限制最大页数、内存溢出风险 |
批量操作 | 应批量但单条处理(insert/update/delete) |
异步超时 | @Async方法未设置超时、线程池未监控 |
大数据量 | 未使用流式处理、一次性加载全量数据 |
慢查询 | 未建索引、未利用索引、全表扫描 |
如本维度无问题:
### D. 性能
✅ 本次变更未发现性能问题。
3.3.6 E. 可靠性问题 - Istio/K8s 场景(按类分组)
维度说明:MQ消费幂等、定时任务防重、分布式锁、资源泄漏、Pod重启后业务连续性。
### {类名A.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {n} | {幂等性/状态外化/分布式锁/资源泄漏/降级兜底} | {描述} | `{问题代码}` | {修复建议} |
### {类名B.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... |
子类型分类:
| 子类型 | 说明 |
|---|---|
幂等性 | MQ消费/Istio重试导致重复执行无幂等保护 |
状态外化 | 业务状态存储在内存而非DB/Redis,Pod重启后丢失 |
分布式锁 | 锁未设置超时、锁未绑定唯一标识 |
资源泄漏 | DB连接/IO/线程池未在finally/try-with-resources释放 |
降级兜底 | 非核心依赖故障时核心业务无兜底直接失败 |
如本维度无问题:
### E. 可靠性
✅ 本次变更未发现可靠性问题。
3.3.7 F. 宕机恢复与逻辑接续问题(按类分组)
维度说明:状态机完整性、可重入性、补偿机制、分布式事务边界、故障模式分析(FMEA)。
⚠️ 重点维度:必须通过故障模式分析(Failure Mode Analysis)追问:
- "如果在这行代码之后JVM宕机,会发生什么?"
- "重启后这条消息会被重新投递吗?业务逻辑能否正确处理?"
- "跨系统的两阶段操作(DB+MQ、DB+OSS、MQ+外部服务)是否有补偿机制?"
### {类名A.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 宕机后果 | 修复建议 |
|---|---|---|---|---|---|---|
| ISS-{nnn} | {n} | {状态机完整性/可重入性/补偿机制/分布式事务/补偿任务} | {描述} | `{问题代码}` | {如果宕机会发生什么} | {修复建议} |
### {类名B.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 宕机后果 | 修复建议 |
|---|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... | ... |
子类型分类:
| 子类型 | 说明 |
|---|---|
状态机完整性 | 状态流转无闭环、中间状态无超时恢复机制、状态变更和下游操作顺序错误 |
可重入性 | 消息重推时状态检查跳过但后续操作丢失、PROCESSING状态无最大处理时长 |
补偿机制 | 两阶段操作(DB+MQ/DB+OSS)第二步失败无补偿、资源泄漏(OSS分片/临时文件) |
分布式事务 | 事务中调用外部服务、本地事务成功但外部调用失败 |
补偿任务 | 无补偿定时任务扫描"卡死"状态、补偿任务无防重复执行保护 |
宕机后果列(必填):简要描述"如果在这行代码后宕机,会发生什么"。
如本维度无问题:
### F. 宕机恢复与逻辑接续
✅ 本次变更未发现宕机恢复与逻辑接续问题。
3.3.8 G. 安全审计问题(按类分组)
维度说明:SQL注入、XSS、命令注入、敏感信息泄露、权限校验缺失、越权风险、日志脱敏。
### {类名A.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {n} | {SQL注入/XSS/命令注入/敏感信息/权限校验/越权风险/日志脱敏} | {描述} | `{问题代码}` | {修复建议} |
### {类名B.java}
| ID | 行号 | 子类型 | 问题描述 | 问题代码 | 修复建议 |
|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... |
子类型分类:
| 子类型 | 说明 |
|---|---|
SQL注入 | 动态SQL拼接用户输入、MyBatis XML使用${}直接代入用户参数 |
XSS | 未对用户输入进行HTML转义即输出到响应 |
命令注入 | 用户输入拼接到系统命令执行 |
敏感信息 | 硬编码密码/密钥/Token/AWS凭证、密码在日志中打印 |
权限校验 | 接口缺少权限检查、直接通过参数ID访问他人数据 |
越权风险 | 数据归属权未校验、水平越权/垂直越权 |
日志脱敏 | 日志打印手机号/身份证/银行卡等敏感字段 |
如本维度无问题:
### G. 安全审计
✅ 本次变更未发现安全审计问题。
3.3.9 修复优先级总览
🔴 CRITICAL(必须优先修复,按维度权重从高到低):
| ID | 文件 | 行号 | 维度 | 问题描述 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {文件} | {n} | {维度} | {描述} | {建议} |
🟡 WARNING(按维度权重从高到低):
| ID | 文件 | 行号 | 维度 | 问题描述 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {文件} | {n} | {维度} | {描述} | {建议} |
🟢 SUGGESTION(可计划修复):
| ID | 文件 | 行号 | 维度 | 问题描述 | 修复建议 |
|---|---|---|---|---|---|
| ISS-{nnn} | {文件} | {n} | {维度} | {描述} | {建议} |
3.3.10 审计结论
加权 WARNING 分数计算:
| 维度 | WARNING数 | 权重 | 小计 |
|---|---|---|---|
| A. 规范审计 | {n} | ×1.5 | {n} |
| B. 业务逻辑 | {n} | ×1.5 | {n} |
| C. 方案合理性 | {n} | ×1 | {n} |
| D. 性能 | {n} | ×1 | {n} |
| E. 可靠性(Istio/K8s) | {n} | ×2 | {n} |
| F. 宕机恢复与逻辑接续 | {n} | ×2.5 | {n} |
| G. 安全审计 | {n} | ×3 | {n} |
| 合计 | {total} | - | {score} |
判定结果:
| 条件 | 结论 |
|---|---|
| 任何 🔴 CRITICAL × 安全/可靠性维度 | 阻塞合并 |
| 任何 🔴 CRITICAL | 需整改 |
| 加权 WARNING 分数 ≥ 3 | 需整改 |
| 加权 WARNING 分数 < 3 | 通过 |
本次审计加权 WARNING 分数:{score} 审计结论:{通过 / 需整改 / 阻塞合并}
本次审计综合评价: {简要说明本次变更的整体质量,突出最需要关注的问题。}
3.4 报告完整性校验(强制)
⚠️ 报告生成后必须执行此校验,确保
.md报告包含result-all.json中的全部问题,不得遗漏。
校验步骤:
-
问题数校验:统计
.md报告中出现的ISS-编号数量,与result-all.json的问题列表数组长度对比,两者必须相等# 统计 .md 报告中的 ISS 编号数量 REPORT_COUNT=$(grep -c 'ISS-[0-9]\{3\}' "{OUTPUT_DIR}/{BRANCH}.md") # 统计 JSON 中的问题数量 JSON_COUNT=$(python3 -c "import json; print(len(json.load(open('{OUTPUT_DIR}/{BRANCH}-result-all.json')).get('问题列表', [])))") echo "报告问题数: ${REPORT_COUNT}, JSON问题数: ${JSON_COUNT}" if [ "${REPORT_COUNT}" -ne "${JSON_COUNT}" ]; then echo "⚠️ 警告: 报告(${REPORT_COUNT})与JSON(${JSON_COUNT})问题数不一致,存在遗漏!" fi -
文件清单校验:
.md报告中"涉及文件清单"的行数,与result-all.json的文件清单数组长度对比,两者必须相等 -
维度覆盖校验:确认
.md报告中 3.3.2~3.3.8 七个维度章节都存在(即使无问题也要有"✅ 未发现"的声明)。⚠️ 空维度处理:读取
result-all.json的问题列表后,按维度字段分组。若某维度在 JSON 中无任何问题,报告中仍须写入该维度的"✅ 未发现"声明。不能因为 JSON 无数据就跳过该维度章节。 -
ID连续性校验:确认
.md报告中所有ISS-编号从ISS-001开始连续无断号
若校验不通过,必须补充报告中遗漏的问题,直到全部通过。
3.5 审计结论判定标准(参考汇总)
说明:本节为审计结论判定规则的汇总参考。报告中的实际判定结果见 3.3.10 审计结论章节。两处规则一致,此处便于快速查阅。
根据问题严重程度 × 维度交叉判定,而非简单计数:
维度权重(影响越大权重越高)
| 维度 | 权重 | 说明 |
|---|---|---|
| 安全审计(SQL注入/XSS/权限) | ×3 | 直接影响系统安全 |
| 宕机恢复与逻辑接续(状态机/补偿/SAGA) | ×2.5 | 影响故障后业务正确接续,数据丢失风险 |
| 可靠性(幂等/状态外化/事务/Istio) | ×2 | 影响 Pod 重启后业务连续性 |
| 规范审计(异常/日志/并发) | ×1.5 | 代码健壮性 |
| 业务逻辑(边界/null) | ×1.5 | 功能正确性 |
| 性能(分页/批量) | ×1 | 运行时性能 |
| 方案合理性(N+1/重复代码) | ×1 | 长期可维护性 |
判定规则
| 条件 | 结论 | 说明 |
|---|---|---|
| 任何 CRITICAL × 安全/可靠性 问题 | 阻塞合并 | 必须修复 |
| 任何 CRITICAL 问题 | 需整改 | 影响功能/安全,需修复 |
| 加权 WARNING 分数 ≥ 3 | 需整改 | 多个问题累积 |
| 加权 WARNING 分数 < 3 | 通过 | 仅低影响建议 |
加权 WARNING 计算示例:
- 1个安全 WARNING(×3)= 3 → 需整改
- 2个规范 WARNING(×1.5)= 3 → 需整改
- 3个性能建议(SUGGESTION ×0.5)= 1.5 → 通过
维度特殊规则
- 安全维度:1个 CRITICAL 安全问题直接阻塞,无论其他维度
- 宕机恢复维度:状态机不完整(无恢复路径)、无补偿机制的跨系统两阶段操作、无法重入的消息处理 → 直接阻塞
- 可靠性维度:Pod 重启场景下的问题优先处理,不接受降级兜底缺失
- 规范维度:仅在循环内单条 insert/delete、吞异常(无兜底)时升级为 CRITICAL
3.6 清理中间文件
汇总完成后,删除所有中间结果文件,只保留最终报告:
# =============================================
# Phase 3.6 清理 — 必须全部执行
# =============================================
AUDIT_DIR="{OUTPUT_DIR}"
BRANCH_NAME="${BRANCH}"
# 1. 清理 OUTPUT_DIR 内的所有中间文件
echo "清理 OUTPUT_DIR: ${AUDIT_DIR}"
rm -f "${AUDIT_DIR}/${BRANCH_NAME}-result-"*-merged.json
rm -f "${AUDIT_DIR}/${BRANCH_NAME}-result-"*checkpoint*.json
rm -f "${AUDIT_DIR}/${BRANCH_NAME}-result-all.json"
rm -f "${AUDIT_DIR}/${BRANCH_NAME}-status.json"
# 2. 清理主计划文件(与最终报告同目录,需显式删除)
rm -f "${AUDIT_DIR}/${BRANCH_NAME}-plan.md"
echo "已删除: ${AUDIT_DIR}/${BRANCH_NAME}-plan.md"
# 3. 清理 Agent 计划文件(批次级计划)
rm -f "${AUDIT_DIR}/${BRANCH_NAME}-plan-"*.md
echo "已删除: ${AUDIT_DIR}/${BRANCH_NAME}-plan-*.md"
# 4. 清理 Agent 运行目录中产生的 references 文件夹(由 Agent 读取规范文件时创建)
if [ -d "./references" ]; then
REF_COUNT=$(find ./references -type f 2>/dev/null | wc -l)
if [ "$REF_COUNT" -eq 0 ]; then
rmdir ./references 2>/dev/null && echo "已删除空目录: ./references" || true
fi
fi
echo "清理完成"
清理说明:
result-all.json是汇总阶段的中间产物(用于去重、排序、分配ID),报告生成后已无用,一并清理.md报告是唯一产物,包含全部问题和文件清单,下游 Skill 直接读取.md即可
清理后保留的文件:
{OUTPUT_DIR}/{branch-name}.md # ✅ 最终审计报告(唯一产物)
Phase 4:输出摘要
✅ 代码审计完成
分支:{branch-name} | 基准:{base-branch}
变更文件:{total-files} 个 | 审计:{audited-files} 个
审计批次:{batch-count} 批次
问题统计:
🔴 严重:{critical} | 🟡 中等:{warning} | 🟢 建议:{suggestion}
审计结论:{通过 / 需整改 / 阻塞合并}
详细报告:{OUTPUT_DIR}/{branch-name}.md
问题追踪ID:ISS-001 ~ ISS-{total-issues}
⚠️ 新增输出:审计报告中的每个问题已分配唯一
ISS-{序号}ID,可用于下游review-bug-fixSkill 追踪。
自检清单
- 主计划文件已生成
{OUTPUT_DIR}/<branch>-plan.md - 每个批次的计划文件已生成
{OUTPUT_DIR}/<branch>-plan-*.md - 手动模式下用户已确认审计计划
- 每批次Agent完成后已更新待合并列表
- 每个Agent的JSON结果文件已通过
python3合法性校验(Phase 2.5 步骤0) - 全局合并前已做字段名标准化(
file→文件,兜底空值) - 全局去重已完成(批次间无重复问题)
- 全局问题ID已分配(
ISS-{序号},按维度权重从高到低排序) - 涉及文件清单已生成(从
{BRANCH}-result-all.json的文件清单字段读取,所有出现问题文件完整列出,表格完整无占位符) - JSON 全部数据已写入 .md 报告(
result-all.json中的每一条问题和每一个文件都已写入 .md,无遗漏。.md 是唯一最终产物,JSON 清理后不可恢复) - 报告完整性校验已通过(问题数、文件数、维度覆盖、ID连续性,Phase 3.4)
- 最终报告已写入
{OUTPUT_DIR}/<branch-name>.md - 报告按维度分章节(3.3.2~3.3.8),各章节内按文件分组,维度内按 CRITICAL→WARNING→SUGGESTION 排序
- 报告各维度表格包含 ID 列(大部分6列:ID/行号/子类型/描述/问题代码/修复建议;F维度7列额外含宕机后果)
- F维度每个问题的"宕机后果"列已填写(其他维度填
-) - F维度(宕机恢复与逻辑接续)审计已完成,特别是Listener/导出服务等关键文件的故障模式分析
- 摘要已输出到对话中
- 审计结论已判定并输出(含加权WARNING分数计算过程)
- 中间文件已清理(Phase 3.6 清理步骤已执行,仅保留最终报告
{branch-name}.md)
Agent计划文件模板
每个批次的计划文件应包含以下内容:
# 审计计划 - 批次{n}
## 批次信息
- 批次名称:{name}
- 批次ID:{batch-id}
- 审计文件数:{count}
- 计划文件:{path}
- 结果文件:{OUTPUT_DIR}/{branch-name}-result-{批次ID}.json
## 需求背景
{提交历史摘要}
## 本批次文件列表
{完整文件路径列表}
## 规范文件(Agent 通过 rules 自动加载,无需手动读取。以下为参考路径)
- /Users/han/.agents/skills/wk-code-review/references/java-specification_01.md
- /Users/han/.agents/skills/wk-code-review/references/java-specification_02.md
- /Users/han/.agents/skills/wk-code-review/references/error-code-specification.md
- /Users/han/.agents/skills/wk-code-review/references/frontend-backend-conventions.md
- /Users/han/.agents/skills/wk-code-review/references/naming-specification.md
- /Users/han/.agents/skills/wk-code-review/references/i18n-specification.md
## 审计维度
### A. 规范审计
- **MyBatis规范**:
- XML中禁止使用 `${}` 直接拼接(SQL注入风险)
- XML中禁止使用 `${@...@}` OGNL表达式调用静态方法
- XML中禁止使用 `+` 拼接字符串
- LIMIT/OFFSET必须使用参数绑定,禁止拼接
- **异常规范**:必须使用ErrorCode枚举,禁止RuntimeException/throw new Exception
- **日志规范**:使用占位符`{}`,禁止字符串`+`拼接;debug/info级别日志需条件判断
- **并发规范**:ThreadLocal需在finally中remove;DateTimeFormatter需复用实例
- **事务规范**:@Transactional注解必须在public方法上
- **循环规范**:禁止循环内单条insert/update/delete,必须批量操作
- **i18n规范**:国际化key格式为`dot.case`
- **包命名规范**:使用`dot.case`,遵循`cn.<company>.<product>[.<domain>].<service>[.<layer>][.<business>][.<mvc>]`
- **枚举规范**:枚举类实现BizEnum;messageKey使用国际化KEY;禁止ordinal比较
- **前后端交互**:Long类型序列化为String;时间使用时间戳毫秒;禁止RESTful路径参数
### B. 业务逻辑审计
- 需求覆盖度:代码是否完整实现需求
- 边界值处理:空指针、数组越界、边界数值
- null检查:入参校验、返回值处理
- 数据一致性:事务边界、并发数据一致
### C. 方案合理性审计
- N+1查询:循环内查询数据库
- 重复代码:相同逻辑是否抽取复用
- 过度设计:是否有不必要的抽象
### D. 性能审计
- 分页限制:是否限制最大页数
- 批量操作:是否使用批量insert/update
- 异步超时:@Async方法是否设置超时
- 大数据量:是否考虑流式处理
### E. 可靠性审计
#### E1. 服务宜机能力(Istio + K8s 场景)
> **⚠️ 背景**:系统使用 Istio + Kubernetes 部署,流量治理由 Istio 接管。
- 是否配置了 healthCheck / readinessProbe / livenessProbe(K8s 层)
- 启动探针是否通过(Pod Ready 之前不会被 Istio 路由流量)
- 是否存在启动时预加载数据到内存(Pod 重启后数据丢失)
#### E2. Pod 重启 / 异常恢复(Istio 自动流量切换)
> **核心问题**:Pod 被 Kill 或异常退出后,Istio 会自动将流量切换到其他实例。业务逻辑能否无缝接续?
- **MQ 消息可靠性**:消费端是否在处理完成后才 ACK;是否有死信队列;消费端是否实现幂等
- **定时任务可靠性**:是否持久化执行进度;多实例是否使用分布式锁;任务失败是否有补偿
- **缓存可靠性**:是否存在缓存击穿;缓存故障时是否有降级兜底
- **分布式锁可靠性**:锁是否设置了合理的超时时间;锁是否绑定唯一标识
#### E3. 异常恢复与容错
> **⚠️ 背景**:Istio 管理熔断/重试/超时/限流。应用层审计聚焦 Pod 重启/异常时业务逻辑能否继续。
- **幂等性保障**:MQ 消费端幂等;对外 HTTP/Feign 调用幂等;重试场景数据库操作有唯一约束或状态机校验
- **降级兜底逻辑**:远程服务不可用时返回兜底数据;非核心依赖故障时核心业务可降级
- **状态外部化**:业务状态存储在 DB/Redis 而非内存;定时任务持久化执行进度
- **数据一致性**:长事务拆分;分布式事务使用 Seata TCC;补偿事务/消息表用于最终一致性
- **资源泄漏防护**:DB 连接使用 try-with-resources;线程池在 Bean 初始化时创建
- **并发控制**:多实例定时任务使用分布式锁;分布式锁设置超时
#### E4. 数据一致性
- **事务策略**:长事务拆分为短事务;分布式事务使用 XA/TCC/SAGA;事务回滚完整
- **数据变更兜底**:危险操作(批量删除/更新)有人工确认或二次校验
#### E5. 兜底与防护完整性
- **禁止吞没异常**:catch 块不能为空或只打印日志不处理
- **资源释放**:IO/DB连接/线程池使用 try-with-resources 或 finally 释放
- **日志中断点**:关键操作有日志记录
- **幂等性保障**:MQ 消费/重试/并发场景下保证幂等
### F. 宕机恢复与逻辑接续审计(重点维度)
> **⚠️ 核心问题**:JVM在处理业务逻辑的过程中宕机,重启后业务能否正确接续?必须通过**故障模式分析(FMEA)**来审计。
#### F1. 状态机完整性审计
**核心问题**:对每个状态变更节点,问"如果在这行代码之后宕机,会发生什么?"
审计要点:状态流转是否形成闭环;状态变更是否原子化;是否有"卡死"状态
审计检查项:状态变更前是否有checklist;状态变更和下游操作顺序是否正确;是否存在两步操作但只检查一个状态;是否有超时机制恢复"卡死"状态
#### F2. 可重入性审计(幂等消息处理)
**核心问题**:消息被重复投递,业务逻辑能否正确处理?
审计要点:状态检查是否接受所有合法重入状态;是否实现检查-执行-再检查幂等模式
审计检查项:状态检查是否验证当前持有者;PROCESSING状态是否有最大处理时长;是否存在状态被更新但未完成导致无法重入
#### F3. 补偿机制审计
**核心问题**:跨系统两阶段操作(DB+MQ、DB+OSS、MQ+外部服务),第二步失败后是否有补偿?
审计检查项:两阶段操作是否有补偿事务;失败后补偿操作是否有幂等保护;补偿失败是否有告警;是否存在资源泄漏风险
#### F4. 分布式事务边界审计
**核心问题**:跨数据库/跨服务的操作,是否有正确的事务边界?
审计检查项:事务是否只包含DB操作;跨服务操作是否使用最终一致性方案;是否存在本地事务成功外部调用失败的场景
#### F5. 宕机恢复与补偿任务审计
**核心问题**:是否有定时任务扫描"卡死"状态并恢复?
审计检查项:PROCESSING/中间状态是否有最大处理时长限制;是否有补偿/恢复定时任务;补偿任务是否使用分布式锁
#### F6. 故障模式分析(FMEA)追问清单
**消息消费类**:消息重复投递时状态检查是否会跳过?如果在更新状态为PROCESSING之后宕机重启后消息重推会被跳过吗?ACK在成功之后还是之前?失败消息是否有DLQ?
**导出/异步任务类**:状态变更和消息发送的顺序?在更新数据库之后发送消息之前宕机怎么办?文件上传成功后通知外部失败如何处理?是否有补偿定时任务?
**分片上传类**:分片上传成功但合并通知失败会产生垃圾碎片吗?有没有清理补偿机制?
**多阶段状态机类**:每个状态变更是否有超时机制?超时后如何恢复?恢复后能否正确接续?
### G. 安全审计
- **注入攻击**:SQL注入、XSS、命令注入
- **敏感信息**:硬编码密码/密钥/Token
- **权限校验**:接口是否缺少权限检查
- **越权风险**:数据访问是否校验所属权
- **日志脱敏**:日志是否打印敏感字段(手机号、身份证、密码)
## 执行步骤
> **⚠️ 必须按顺序执行,每一步完成前不要进入下一步**
### 严重程度判定标准(各维度通用)
| 严重程度 | 判定规则 |
|---|---|
| **CRITICAL** | 违反规范,且在特定运行时场景下**必然**导致功能错误、数据丢失或安全问题 |
| **WARNING** | 违反规范,在常见运行时场景下**可能**导致问题,或存在一定风险 |
| **SUGGESTION** | 违反规范,但当前上下文风险极低,属于优化建议 |
> **同一问题可能因上下文不同而判不同级别**。例如:日志字符串拼接在核心业务流程中判 WARNING,在简单的工具类中判 SUGGESTION。
1. **读取规范文件**:使用 Read 工具读取上述 6 个参考规范文件,理解审计标准
2. **读取计划文件**:使用 Read 工具读取本计划文件,了解本次批次的文件列表和审计范围
3. **读取文件内容**:使用 Read 工具逐一读取每个需要审计的 Java/XML 文件的完整内容
> **必须读取文件内容后才能进行分析,不能仅靠 git diff 的变更片段判断问题**
> git diff 只显示变更的部分,完整判断需要结合文件的上下文
4. **执行 git diff**:获取代码变更对比,了解本次提交改了什么:
```bash
git diff ${BASE_BRANCH}...${BRANCH} -- {文件路径1} {文件路径2} ...
⚠️ 使用
${BRANCH}而非HEAD,确保多批次执行时取到正确分支差异。
- 按审计维度(A-G)逐文件分析:
- 对每个文件,结合文件内容和 diff,逐一检查是否符合规范
- 检查每个问题必须包含:文件路径、行号、严重程度、维度、类型、描述、问题代码、修复建议
- 特别注意:
问题代码、描述、宕机后果、修复建议字段中若包含特殊字符(双引号"、反斜杠\、换行符),必须转义后才能写入 JSON(参见下方 JSON 安全规则)
- 写入结果文件:将结果按指定 JSON 格式写入结果文件
⚠️ JSON 安全强制规则:
问题代码字段:只保留关键行(≤150字符),优先将代码中的双引号替换为单引号("x"→'x'),避免\"转义;反斜杠需双重转义(\→\\)描述、宕机后果、修复建议:禁止出现未转义的双引号,禁止包含实际换行符(用\n字面量表示)- 引用代码时用反引号
`code`包裹,禁止用双引号
- 写入后立即自检:
- 用 Read 工具重新读取写入的 JSON 文件,核对内容完整
- 执行
python3 -c "import json; json.load(open('文件路径'))"验证合法性 - 若验证失败:按上方 JSON 安全规则修复对应字段,重新写入,直到验证通过
- 结果文件路径:
{OUTPUT_DIR}/{branch-name}-result-{批次ID}.json
输出要求
将结果写入JSON文件,格式:
{
"批次": "{name}",
"批次ID": "{batch-id}",
"文件总数": {count},
"问题列表": [
{
"id": "ISS-{由Python脚本统一分配,Agent无需填写}",
"严重程度": "CRITICAL|WARNING|SUGGESTION",
"文件": "文件路径",
"行号": "行号",
"维度": "A. 规范审计|B. 业务逻辑|C. 方案合理性|D. 性能|E. 可靠性|F. 宕机恢复与逻辑接续|G. 安全审计",
"类型": "问题类型(子类型,如:日志规范/null检查/N+1查询等)",
"描述": "问题描述",
"问题代码": "代码片段",
"宕机后果": "如果在这行代码后宕机会发生什么(F维度必填,其他维度填\"-\")",
"修复建议": "修复建议"
}
]
}
⚠️ 新增
id字段:id字段由主进程在 Phase 3.2 Python 脚本中统一分配(ISS-{序号}),Agent 无需填写。Agent 输出的id值将被脚本覆写。
⚠️ JSON 输出安全规则(强制遵守,否则最终合并必然失败):
以下规则是为了防止子代理输出的 JSON 字段(如
问题代码、描述、宕机后果、修复建议)中包含的特殊字符(双引号、反斜杠、换行符)破坏 JSON 结构。必须严格执行。
| 特殊字符 | 转义方式 | 示例 |
|---|---|---|
\(反斜杠) | \\ | C:\data → C:\\data |
"(双引号) | \" | "test" → \"test\" |
| 实际换行符 | \n(字面量) | 实际换行 → \n |
| 制表符 | \t | 实际 tab → \t |
转义顺序(必须按此顺序):
\→\\"→\"- 换行符 →
\n
代码片段(问题代码字段)处理规则:
- 只保留关键的一行代码,不超过 150 字符;超出部分用
...截断 - 优先将代码中的双引号替换为单引号再嵌入 JSON(
"name"→'name'),避免转义 - 代码中若含大量双引号无法替换,再使用
\"转义 - 反斜杠在正则表达式中需双重转义:
\d→ JSON 中写\\d
描述文本(描述、宕机后果、修复建议字段)处理规则:
- 引用代码片段时用反引号(
`code`)包裹,禁止用双引号包裹代码 - 文本内换行用
\n字面量表示,禁止包含实际换行符 - 禁止在文本字段中出现未转义的双引号
正确示例:
{
"问题描述": "logger.debug使用了字符串拼接,应使用占位符",
"问题代码": "logger.debug('Processing id: ' + id);",
"宕机后果": "日志输出可能因格式化错误而丢失关键信息",
"修复建议": "改为 logger.debug('Processing id: {}', id);"
}
错误示例(会导致JSON损坏):
{
"问题描述": "logger.debug("Processing id: " + id) 使用了字符串拼接",
"问题代码": "logger.debug("Processing id: " + id); // 内层双引号未转义,会破坏JSON
"宕机后果": "宕机后
任务状态丢失",
"修复建议": "改为 logger.debug("Processing id: {}", id);"
}
写后自检流程(强制执行):
- 用 Write 工具写入 JSON 文件
- 立即用 Read 工具重新读取该文件,核对内容是否完整
- 用 Bash 执行
python3 -c "import json; json.load(open('文件路径'))"验证合法性 - 若验证失败:用 Bash
python3 -c "import json; print(json.dumps(json.load(open('文件路径').read().replace('破坏的字符','正确的转义'))))"定位错误字段,重新 Write 该字段的修复值,重复步骤 2-4 直到通过
主计划文件模板
# 代码审计计划
> 分支:{branch-name}
> 生成时间:{timestamp}
> 基准分支:{base-branch}
---
## 统计信息
| 项目 | 值 |
|---|---|
| 变更文件总数 | {total-files} |
| Java文件 | {java-files} |
| XML文件 | {xml-files} |
| 应审计文件数 | {to-audit-files} |
| 审计批次 | {batch-count} |
---
## 审计批次清单
### 批次{n}:{name}
- 批次ID:{batch-id}
- 文件数:{count}
- 计划文件:{OUTPUT_DIR}/{branch-name}-plan-{batch-id}.md
...(继续列出所有批次)
---
## 执行步骤
- [ ] Step 1: 批次1审计
- [ ] Step 2: 批次2审计
- [ ] Step 3: 汇总结果,生成报告
---
## 待合并结果文件列表
(每批次完成后动态追加)
---
## 重点关注项
1. 新增的核心业务文件
2. 涉及安全的文件
3. 涉及并发/事务的文件
4. Mapper XML文件(SQL注入风险)
示例对话
| 用户输入 | 处理方式 |
|---|---|
对这个分支进行代码审计 | 预检查 → 生成主计划 → 用户确认 → 分批次执行 → 更新待合并列表 → 汇总报告 |
代码审计 feature/1.4.0/xxx/489822 | 同上,针对指定分支 |
wk-code-review feature/xxx | 同上 |