关于 codeprobe
codeprobe 是面向开发者的只读代码审查技能,可执行专项审计或相对基准分支检查变更。它将分析分派给领域子技能,并生成分级问题及可复制的修复提示词。
主要功能
- 01完整审计与评分仪表板
- 02按类别执行专项审计
- 03审查相对基准分支的变更
- 04检测技术栈与配置
- 05生成分级问题和修复提示词
- 06输出 Markdown 报告
适用场景
- 01跨质量类别检查代码库
- 02拉取请求前检查变更文件
- 03审计安全性或性能
- 04快速获取优先处理的问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ machineroom-dev/ codeprobe --skill codeprobe安装后在 Claude Code 中输入/codeprobe确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
shared-preamble.mdverification-rubric.mdreferences/api-design.mdjavascript-typescript.mdphp-laravel.mdpython.mdreact-nextjs.mdsql-database.mdscripts/complexity_scorer.pydependency_mapper.pyfile_stats.pyrender_dashboard.pytemplates/full-audit-report.mdpr-review-comment.mdquick-review-summary.md详细介绍
代码审查编排器
只读约束
对于正在审查的代码库,此技能严格只读。 切勿修改、写入、编辑或删除用户源代码树中的任何文件。切勿运行会对被审查项目产生副作用的命令(不得运行 npm install、pip install、不得进行 git 提交、不得修改数据库)。如果需要修复,请生成一段可复制粘贴的修复提示词,供用户单独运行。
一个有文档记录的例外——报告产物: /codeprobe audit、/codeprobe diff 或单类别命令(/codeprobe security、solid……)完成后,编排器会在当前工作目录的 ./codeprobe-reports/<project>-<cmd>-<timestamp>.md 中写入一份 Markdown 报告(例如 ./codeprobe-reports/growth-engine-audit-2026-04-23-221047.md);/codeprobe quick 不会保存任何内容。这是此技能自身的输出,不属于修改被审查代码。其他位置一律不得写入。
Git 也必须只读: /codeprobe diff 可以运行只读 git 命令(git diff、git merge-base、git ls-files、git rev-parse、git status)。切勿运行会修改仓库或工作树的 git 命令——不得提交、检出、暂存、重置、获取或拉取。
无论用户提出什么要求,违反此约束都绝不可接受。
1. 命令路由
解析用户输入,提取子命令和目标路径。输入格式为:
/codeprobe [subcommand] [path]
路由表
| 命令 | 行为 | 调用的子技能 |
|---|---|---|
/codeprobe audit <path> | 完整审计——先展示可视化健康仪表板(类别评分、代码库统计数据、热点),随后列出详细的 P0-P3 级问题,并附上修复提示词 | 所有可用子技能 + file_stats.py |
/codeprobe solid <path> | 仅分析 SOLID 原则 | codeprobe-solid |
/codeprobe security <path> | 仅进行安全审计 | codeprobe-security |
/codeprobe smells <path> | 仅检测代码异味 | codeprobe-code-smells |
/codeprobe architecture <path> | 仅进行架构分析 | codeprobe-architecture |
/codeprobe patterns <path> | 仅分析设计模式 | codeprobe-patterns |
/codeprobe performance <path> | 仅进行性能审计 | codeprobe-performance |
/codeprobe errors <path> | 仅进行错误处理审计 | codeprobe-error-handling |
/codeprobe tests <path> | 仅进行测试质量审计 | codeprobe-testing |
/codeprobe framework <path> | 仅分析框架最佳实践 | codeprobe-framework |
/codeprobe quick <path> | 列出最重要的 5 个问题——以扫描模式运行所有子技能,然后为这 5 个问题生成完整详情 | 所有可用子技能 |
/codeprobe diff [base] | 以 PR 审查的方式,对比基准分支与已更改文件(默认值:main,回退至 master)——参见第 4A 节 | 所有 9 个子技能,仅审查已更改文件 |
默认行为
- 未提供子命令:询问用户想要执行什么,并列出可用命令。
- 未提供路径:使用当前工作目录。
- 未知子命令:说明这不是 codeprobe 命令,并列出上面的路由表。
2. 自动检测技术栈
在路由到任何子技能之前,检测目标路径下的技术栈。这有助于确定要加载哪些参考指南并传递给子技能。
检测流程
- 使用 Glob 扫描目标路径中的文件扩展名(递归扫描,深度适中)。
- 应用以下检测规则——可同时匹配多个技术栈:
| 信号 | 检测到的技术栈 | 要加载的参考文件 |
|---|---|---|
.php 文件 | PHP / Laravel | references/php-laravel.md |
.js、.ts、.jsx、.tsx 文件 | JavaScript / TypeScript | references/javascript-typescript.md |
.py 文件 | Python | references/python.md |
.jsx、.tsx 文件 + 存在 next.config.* | React / Next.js | references/react-nextjs.md |
.sql 文件或 migrations/ 目录 | SQL / 数据库 | references/sql-database.md |
routes/ 目录或 API 路由模式 | API 设计 | references/api-design.md |
- 对每个检测到的技术栈,确认对应的参考文件存在。如果不存在,则静默跳过。
- 收集所有适用参考文件的绝对路径,以传递给子技能。不要将参考文件内容读入协调器自身的上下文——子代理会直接读取与其领域相关的参考文件,从而使每个上下文窗口保持精简。
参考文件解析
参考文件位于此技能自身目录中的 references/ 目录。请根据此 SKILL.md 文件的位置解析路径,而非用户的项目,并在传递给子代理(其工作目录为用户项目)之前将其转换为绝对路径:
{this-skill's-directory}/references/{reference-file}.md
如果参考文件不存在,则继续处理。切勿因缺少参考文件而中止审查。
3. 配置加载
检查项目根目录(目标路径或其祖先目录)中是否存在 .codeprobe-config.json 文件。
配置架构
{
"severity_overrides": {
"long_method_loc": 50,
"large_class_loc": 500,
"deep_nesting_max": 4,
"max_constructor_deps": 6
},
"skip_categories": ["codeprobe-testing"],
"skip_rules": ["SPEC-GEN-001"],
"framework": "laravel",
"extra_references": [],
"report_format": "markdown",
"verify": true
}
配置行为
- 如果不存在:应用所有默认值。不报错。
severity_overrides:传递给子技能,以便它们相应调整阈值。skip_categories:不要调用列出的子技能,即使处于audit或quick模式也是如此。skip_rules:传递给子技能,使其抑制 ID 匹配的发现项。framework:如果已设置,则跳过该框架的自动检测,并强制加载对应的参考文件。其他自动检测仍照常进行。extra_references:要加载并传递给子技能的其他参考文件路径。report_format:输出格式偏好(默认为:markdown)。verify:默认为true。当设为false时,完全跳过验证环节(第 4B 节),并省略仪表板中的“验证未通过”行和报告章节。
4. 子技能执行
上下文准备(在任何子技能运行前执行一次)
在调用任何子技能之前,编排器会准备共享上下文。编排器不会自行读取源文件内容——每个子 Agent 都会读取其所属领域所需的文件。这样可以让编排器保持精简的上下文,并避免在每个 Agent 的提示词中重复整个代码库。
-
读取共享前言:从
shared-preamble.md(位于此技能目录中)读取。该文件包含所有子技能共用的输出约定、执行模式和约束。 -
为目标路径构建文件清单:
- 首选:运行
python3 scripts/file_stats.py <target_path>一次(相对于此 SKILL.md 解析脚本路径),并根据其逐文件输出生成清单。 - 后备方案(Python 3 不可用时):使用 Glob 查找源文件(
.ts、.tsx、.js、.jsx、.py、.php、.vue、.sql、.css、.scss)和配置文件,例如next.config.*、package.json、composer.json、requirements.txt、.env.example,再使用wc -l获取行数。 - **排除项(两种路径均适用):**跳过
node_modules、vendor、.git、__pycache__、.next、dist、build、.venv、venv、env和codeprobe-reports/——与捆绑脚本中的 SKIP_DIRS 保持一致。 - 清单应逐行列出
{filepath} ({LOC} lines),并附上检测到的技术栈。
- 首选:运行
-
收集参考文件路径(已在第 2 节的技术栈检测期间解析)。仅提供路径,不提供内容。
-
解析每个子技能的 SKILL.md 路径。 子技能位于同级目录中:相对于此 SKILL.md 的位置解析
../codeprobe-{name}/SKILL.md,并记录其绝对路径。不要自行读取子技能文件,也不要内联其内容:每个子 Agent 都会读取自己的文件(调用协议步骤 2)。每种模式(包括scan/quick)下,都必须在=== SUB-SKILL: … ===标记块中传递该路径——切勿依赖子 Agent 根据名称解析子技能,因为该 Agent 可能没有注册此技能。
Bash 使用规范。 每次 Bash 调用只能执行一个命令:一个 python3 …、一个 mkdir -p …、一个 wc -l … 或一个 date …。绝不使用 &&、; 或管道将命令串联起来执行循环;绝不设置 shell 变量;绝不使用 Bash 读取文件(cat、head、for … cat)——请使用 Read 工具。受限环境每次只允许一种 Bash 命令模式,因此整条串联命令会被一并拒绝;拒绝操作绝不能改变子 Agent 收到的内容。
调用协议
对于要运行的每项子技能,启动一个 Agent,并在提示词中包含:
- 共享前言路径——
shared-preamble.md的绝对路径,并附上:“先使用 Read 工具读取此文件。它规定了你的输出契约、执行模式和只读约束。”同时将前言中的只读约束句子原样复制到提示词中,确保即使在读取文件之前,该约束也同样有效。 - 子技能标记块,注明子技能名称及其
SKILL.md的绝对路径:
切勿在提示词中用概述、缩写或转述来代替路径——转述会悄然遗漏规则。如果 Agent 回复=== SUB-SKILL: codeprobe-{name} === Read the file at {absolute path of ../codeprobe-{name}/SKILL.md} with the Read tool before doing anything else. It is the sub-skill you are executing: its detection tables are the product, and every rule in it applies. Ignore its Standalone Mode section — the orchestrator has already provided everything it would load. If the Read fails, stop and reply with exactly `SUB-SKILL UNREADABLE: {path}` and nothing else. === END SUB-SKILL ===SUB-SKILL UNREADABLE,请自行读取该文件,然后只重新启动该 Agent 一次,并在相同标记之间原样内联文件内容(去除 frontmatter);只有在这种情况下才能内联内容。 - 模式——
full或scan。 - 文件清单——路径、行数和检测到的技术栈。指示 Agent:“使用 Read/Grep/Glob 检查与你的检测表相关的文件。不要盲目读取每个文件——应针对你的领域选择目标文件。”
- 参考文件路径——适用参考指南的绝对路径,并附上:“在最终确定严重性和修复提示词之前,先阅读与发现结果相关的参考资料。”
- 配置覆盖项——
.codeprobe-config.json中的严重性覆盖项和跳过规则。 - 目标路径——让子技能知道项目根目录,以便进行针对性查找。
- 适用时提供子技能专属的预计算脚本输出:
- 对于
codeprobe-architecture:启动 Agent 之前,通过 Bash 运行python3 scripts/dependency_mapper.py <target_path>并捕获 JSON 输出。将其作为额外的上下文块传入,标记为=== DEPENDENCY_GRAPH === ... === END DEPENDENCY_GRAPH ===。子技能将其作为循环依赖检测的事实依据。如果 Python 3 不可用或脚本运行失败,则省略此上下文块——子技能会改用基于 LLM 的导入关系追踪。 - 对于
codeprobe-performance:如果scripts/complexity_scorer.py的输出可用(可选),则将其作为=== COMPLEXITY_SCORES === ... === END COMPLEXITY_SCORES ===传入。
- 对于
- Bash 使用规范,一行:“每次 Bash 调用只能包含一条命令——绝不使用
&&、;、循环或 shell 变量;使用 Read 读取文件。”
子技能自己的 SKILL.md 只包含其领域专属的检测逻辑。所有其他共享上下文(输出格式、模式、文件清单、参考路径、预计算脚本数据)均由编排器的提示词提供;子 Agent 会自行读取源文件。
收集发现结果,格式须符合标准输出契约(第 5 节)。
执行模式
| 模式 | 使用场景 | 行为 |
|---|---|---|
full | /codeprobe audit、/codeprobe diff、/codeprobe solid 等 | 执行完整分析,返回所有发现结果 |
scan | /codeprobe quick | 执行相同的完整分析,但仅返回各类别的严重性计数 + 前 5 个候选发现结果,并包含所有输出契约字段(分析成本完全相同——扫描模式只精简输出,让编排器能够跨类别对候选结果排序,而无需进行第二轮分析) |
执行顺序
- **并行执行:**各子技能 Agent 相互独立——只有在所有子技能都返回后,才进行去重和评分。一次性在同一条消息中并行启动所有适用的子技能 Agent;不要逐个启动。下方固定的类别顺序仅用于呈现报告,不代表执行顺序。(例外:Claude.ai 降级模式见第 9 节,由于没有可用的子 Agent,需按顺序执行。)
- **启动前:**通过
scripts/dependency_mapper.py预先计算依赖关系图(适用于codeprobe-architecture的调用协议步骤 8),并运行scripts/file_stats.py获取清单和代码库统计信息(若无法使用 Python 3,则跳过并妥善处理)。 /codeprobe audit:以full模式启动全部 9 个子技能。呈现顺序:codeprobe-security、codeprobe-error-handling、codeprobe-solid、codeprobe-architecture、codeprobe-patterns、codeprobe-performance、codeprobe-code-smells、codeprobe-testing、codeprobe-framework。收集所有发现。运行验证流程(第 4B 节)。执行去重(第 7A 节)。根据严重程度计数计算类别评分。汇总各文件的发现,并按被标记的不同类别数排序,确定热点文件。/codeprobe quick:以scan模式并行启动全部 9 个子技能。收集每个子技能排名前 5 的候选项(已包含完整的输出契约细节)。按严重程度(critical > major > minor > suggestion)对所有候选项排序;若严重程度相同,则按类别权重排序(第 7 节)。将暂定排名前 8 的候选项送入验证流程(第 4B 节),然后呈现验证后保留的前 5 项。仅执行一轮,不重新运行。
可用的子技能
codeprobe-security— 安全漏洞检测codeprobe-error-handling— 错误处理与韧性codeprobe-solid— SOLID 原则分析codeprobe-architecture— 架构分析codeprobe-patterns— 设计模式顾问codeprobe-performance— 性能与可扩展性codeprobe-code-smells— 代码异味检测codeprobe-testing— 测试质量与覆盖率codeprobe-framework— 框架专属最佳实践
4A. 差异审查(/codeprobe diff [base])
PR 风格审查:仅分析相对于基准分支的变更,让审查工作聚焦于即将合并的代码。
前置条件
- 需要 Git 仓库:通过
git rev-parse --is-inside-work-tree检查。如果当前目录不在 Git 仓库中,告知用户差异审查需要 Git,并建议改用/codeprobe audit。 - Git 操作严格只读(见上文的只读限制)。
基准解析
- 如果用户提供了基准引用,则使用该引用(通过
git rev-parse --verify <base>验证)。 - 否则依次尝试
main和master。 - 如果都无法解析,则询问用户要与哪个基准进行比较。
收集变更文件
- 计算合并基点:单独运行
git merge-base <base> HEAD作为一次 Bash 调用,并将输出的 SHA(下文记为<MB>)替换到后续命令中——不要使用 shell 变量(遵循 Bash 规范,第 4 节)。与合并基点比较,而非基准分支顶端提交,这样只会审查当前分支的变更;即使基准分支已更新,也与 PR 差异视图保持一致。 - 变更文件:
git diff --name-status <MB>(这会包含未提交的工作区变更,这是预期行为——审查即将提交的内容)。排除已删除文件(状态D)。 - 未跟踪文件:
git ls-files --others --exclude-standard。 - 将两个列表都筛选为清单所用的源代码/配置文件扩展名(第 4 节),并应用相同的目录排除规则。
- 每个文件的变更行范围:从
git diff -U0 <MB> -- <file>的@@分块标题中解析新文件一侧的行范围。未跟踪文件视为全部变更。 - 如果最终列表为空,则报告“与
<base>相比,没有可审查的变更”并停止——未经用户请求,不要改为执行完整审计。
执行
运行标准流程(第 2–4 节),并作如下调整:
- 文件清单中仅包含已更改或未跟踪的文件,并为每个文件标注更改的行范围。
- 以
full模式并行启动全部 9 个子技能。为每个 Agent 提示词添加:“这是一次差异审查。每条发现都必须以清单中的某个文件为依据,并优先关注已标注的更改行。可以读取周边或相关文件以了解上下文,但不要报告未更改文件中的发现。” - 依赖图(
dependency_mapper.py)仍在整个项目范围内运行——更改的导入可能与未更改文件共同形成循环。 - 按照常规流程进行去重(第 7A 节)和评分(第 7 节),但仅针对差异发现进行计算。跳过热点计算和代码库统计——它们描述的是整个代码库的健康状况,而非差异。
渲染
参见第 8 节(/codeprobe diff 小节)——差异输出使用 templates/pr-review-comment.md。验证流程(第 4B 节)在去重前对差异发现运行;被拒绝的数量填入汇总表的“经验证拒绝”行。
4B. 验证流程
每个子技能 Agent 返回结果后,且在去重(第 7A 节)之前,使用独立的验证 Agent 重新检查每条 Critical 和 Major 级别的发现。验证 Agent 的任务是对抗性质的:找出该发现不成立的原因,而不是复述它。如果 .codeprobe-config.json 设置了 "verify": false,则跳过整个章节。
运行时机
/codeprobe audit、/codeprobe diff和每个单类别命令(security、solid等):所有子技能 Agent 返回后运行一次。/codeprobe quick:对扫描模式汇总候选项排序后运行(第 4 节“执行顺序”)。只验证临时排名前 8 中的 Critical 和 Major 级别发现;前 8 中的 Minor 和 Suggestion 候选项直接作为保留项通过。如果前 8 中没有 Critical 或 Major 级别的发现,则不启动任何 Agent。
验证内容
- 验证每条
severity为critical或major的发现。minor和suggestion级别的发现不做处理;绝不发送给验证 Agent。 - 如果没有 Critical 或 Major 级别的发现,则不启动任何 Agent,并将
rejected_count = 0。
并行分发
- 每个至少包含一条 Critical 或 Major 级别发现的类别启动一个验证 Agent。在一条消息中并行启动所有验证 Agent,绝不能逐个启动。最多 9 个。
/codeprobe quick会只启动一个验证 Agent,负责验证所有类别中临时排名前 8 的 Critical 和 Major 级别发现。
验证 Agent 提示词组成
每个验证 Agent 提示词按以下顺序包含:
shared-preamble.md中的 只读约束 块。- 按路径区分的验证标准,置于以下标记之间:
不要将验证标准内联。如果验证 Agent 回复=== VERIFICATION RUBRIC === Read the file at {absolute path of verification-rubric.md, resolved relative to this SKILL.md} with the Read tool before doing anything else. It defines your role, procedure, hard limits, and output shape. If the Read fails, stop and reply with exactly `RUBRIC UNREADABLE: {path}` and nothing else. === END VERIFICATION RUBRIC ===RUBRIC UNREADABLE,则自行读取该文件,并将其内容逐字内联到相同标记之间,然后重新启动该验证 Agent 一次。 - 待验证的发现——该类别下的 Critical 和 Major 级别发现(对于
quick,为前 8 中的 Critical 和 Major 级别发现,可能跨越多个类别),并包含第 5 节规定的所有输出契约字段。 - 文件清单(第 4 节“上下文准备”步骤 2)。
- 参考指南路径(仅路径)。
- 目标路径。
- 一行 Bash 使用规范:“每次 Bash 调用只能包含一条命令——绝不使用
&&、;、循环或 shell 变量;使用 Read 读取文件。”(第 9 步“调用协议”中,所有子技能 Agent 提示词也都包含相同句子。)
验证标准、前言和子技能文件的绝对路径来自本 SKILL.md 所在位置(技能基础目录);绝不要运行 realpath、pwd 或 cd 来推导路径。
不要包含子技能的 SKILL.md、其检测表,或只读约束块以外的共享前言。验证 Agent 如果看到检测模式,就会重新执行该模式,而不是追查该声明。
处理验证结果
验证器返回 verification-rubric.md 中定义的结构(findings[],包含 verification 和 verification_note,以及一个 summary)。按以下方式应用每项结果:
verification | 协调器操作 |
|---|---|
confirmed | 原样保留该发现。 |
downgraded | 保留 id;将原始严重级别记录为 old_severity,然后将 severity 设置为回传的值(必须恰好比原始级别低一个档位——若不符合,则按 confirmed 处理);将 verification_note 存储在该发现上。将 {id, location, old_severity, severity, verification_note} 追加到 downgraded[]。 |
rejected | 在 Section 7A 之前且在评分之前移除该发现。将 {id, location, verification_note} 追加到 rejected[]。 |
然后设置 rejected_count = len(rejected[]) 和 downgraded_count = len(downgraded[])。忽略任何 id 不在输入中的回传条目、任何提高严重级别的结果以及任何新发现——验证器不能添加或升级发现。未收到验证结果的输入发现将未经验证、原样保留;其类别计入 unverified_categories(无论该类别有多少发现缺少结果,也无论其验证器是否同时因 Failure handling 而失败,每个类别最多计数一次)。
失败处理
如果验证器 Agent 报错、超时,或返回的输出无法映射到评分标准的结构,则该类别的每项发现均未经验证、原样保留,并将 unverified_categories 加一。验证绝不会阻止或延迟报告;缺失的验证器结果会显示在仪表板行(Section 8)中,不会重试。唯一例外是 RUBRIC UNREADABLE 回复:它会按 Verifier prompt composition 中的说明进行一次内联重新生成;若再次失败,则适用本规则。对于 /codeprobe quick,其单个验证器涵盖多个类别,失败时 unverified_categories 设置为其输入中涉及的类别数。
报告规则(适用于所有界面)
凡是显示验证计数的界面,都必须准确呈现 **Rejected by verification:** {rejected_count}(PR 评论改用表格行)。当 unverified_categories > 0 时,追加 ({n} categories unverified);当 n 为 1 时使用 category。若配置 verify 为 false,则完全省略该行、表格行以及 Rejected/Downgraded 部分。各界面的放置位置有意不同——终端中位于仪表板最后一行,保存文件的 Score Breakdown 中位于 "Duplicates removed" 之后——且每个模板都规定了自己的位置。
/codeprobe quick 渲染规则
单个验证器返回结果后:剔除 rejected 候选项、应用降级、重新排列剩余项(按严重级别,再按类别权重),然后渲染排名前 5 的项。降级行的 Severity 单元格末尾追加 _(downgraded from {old_severity} by verification)_(模板中的 {downgrade_note})。如果渲染的行少于 5 行,且至少有一个候选项被拒绝,则在表格正下方添加 Fewer than 5 findings survived verification.;否则,较短的表格不添加说明。排名第 9 或更低的候选项永不验证,也永不渲染。{total_findings}、严重级别总数和 Estimated Score 均根据扫描模式的计数得出,其中已移除所有被拒绝的候选项,所有降级候选项均按新严重级别计数。
5. 输出约定
每个子技能报告的每项发现都 MUST 包含所有标记为 Yes 的字段。两个验证字段只能由编排器的验证器(第 4B 节)设置,子技能不得设置:
| 字段 | 必填 | 描述 |
|---|---|---|
id | Yes | 格式为 {PREFIX}-{NNN} 的唯一标识符(例如,SRP-001、SEC-003) |
severity | Yes | 以下之一:critical、major、minor、suggestion |
severity_rationale | Yes | 用一句话说明为何属于此严重性级别,而不是低一级。 |
location | Yes | 文件路径 + 行范围(例如,src/UserService.php:45-67) |
problem | Yes | 用一句话描述问题 |
evidence | Yes | 来自代码的具体证据——引用相关代码行 |
suggestion | Yes | 修复建议 |
fix_prompt | Yes | 一段可直接复制粘贴的提示词,用户可交给 Claude Code 应用修复 |
refactored_sketch | No | 可选的代码片段,展示改进后的版本 |
verification | 仅限编排器 | 以下之一:confirmed、downgraded、rejected。只能由编排器的验证器针对 Critical/Major 级发现设置;子技能不得设置。 |
verification_note | 若已降级/驳回 | 用一句话说明:对于 downgraded,严重性理由中的哪项边界判断不成立;对于 rejected,说明原因并引用起到缓解作用的代码。对于 confirmed,留空。 |
发现格式示例
### SRP-001 | Major | `src/UserService.php:45-67`
**Problem:** UserService violates Single Responsibility — handles authentication, email sending, and database queries in one class.
**Severity rationale:** Major (not Minor) because three unrelated responsibilities are concentrated in one class on a critical auth path — refactoring will touch every caller; not Critical because the code works correctly today, this is a maintainability risk, not a production defect.
**Evidence:**
> Lines 45-50: `public function authenticate($credentials) { ... }`
> Lines 52-60: `public function sendWelcomeEmail($user) { ... }`
> Lines 62-67: `public function findByUsername($name) { ... }`
**Suggestion:** Extract email logic into a dedicated `UserMailer` service and database queries into a `UserRepository`.
**Fix prompt:**
> Refactor `src/UserService.php` to follow Single Responsibility Principle: extract `sendWelcomeEmail()` into a new `UserMailer` class and `findByUsername()` into a `UserRepository` class. Keep `authenticate()` in `UserService` and inject the new dependencies.
6. 严重性级别
| 级别 | 优先级 | 含义 | 示例 |
|---|---|---|---|
| Critical | P0 | 已确认的 Bug、可利用的安全漏洞,或可能导致生产环境危害的数据丢失/损坏风险 | 使用用户输入的 SQL 注入、数据变更端点缺少身份验证、导致数据损坏的竞态条件、核心路径上未处理的崩溃、多步骤写入缺少数据库事务 |
| Major | P1 | 影响可维护性、可靠性或可扩展性的重大问题,会增加风险,但不是会立即影响生产环境的缺陷 | 关键业务逻辑缺少测试、类过大、代码重复、外部调用缺少错误处理、N+1 查询、缺少输入验证 |
| Minor | P2 | 代码异味,风险较低,值得为长期健康考虑处理 | 魔法数字、嵌套过深、命名不佳、缺少边界情况测试、错误详情过于冗长 |
| Suggestion | P3 | 改进建议,有则更好,忽略也没有实际风险 | 模式方面的机会、风格改进、推测性泛化 |
严重性判定准则
以下情况绝不属于 Critical——最高归类为 Major:
- 缺少测试(即使是关键业务逻辑的测试)
- 代码重复或类/文件过大
- 任何类型的代码异味
- 违反框架惯例
- 缺少文档、注释或类型注解
Critical 仅适用于以下情况:
- 已确认的 Bug(代码会产生错误结果或崩溃)
- 可利用的安全漏洞(注入、绕过身份验证、有证据支持的 IDOR)
- 数据丢失或损坏风险(缺少事务、写入时发生竞态条件)
- 敏感数据泄露(代码中包含密钥、日志中记录凭据)
**子技能:不得将发现的严重性提升到检测表指定级别以上。**如果表中标注为「Major」,即使具体情况看起来很严重,也应按 Major 报告。编排器的评分公式会考虑各级别发现的数量。
7. 评分
收集所有发现后,按类别计算分数,并计算总体分数。
类别分数公式
每个扣分项都设有上限,以防单个严重级别主导分数:
crit_penalty = min(50, critical_count * 15)
major_penalty = min(30, major_count * 6)
minor_penalty = min(10, minor_count * 2)
category_score = max(0, 100 - crit_penalty - major_penalty - minor_penalty)
建议不会影响分数。
理由: 收益递减机制可防止单个严重级别将分数降至最低。某个类别有 4 个严重问题时,得分为 50(而不是 0),这表明存在问题,但代码并未完全失效。三个级别的总扣分上限为 90,因此只有各个严重级别都出现极端问题时,分数才会降至 0。
类别权重
| 类别 | 权重 |
|---|---|
| 安全性 | 20% |
| SOLID | 15% |
| 架构 | 15% |
| 错误处理 | 12% |
| 性能 | 12% |
| 测试质量 | 10% |
| 代码异味 | 8% |
| 设计模式 | 4% |
| 框架 | 4% |
所有 9 个类别均已启用。权重总和为 100%。
总体分数
overall = sum(category_score_i * weight_i for each active category)
如果 .codeprobe-config.json 中的 skip_categories 排除了部分类别,则通过除以启用类别的权重总和来归一化:
overall = sum(category_score_i * weight_i for each active category) / sum(weight_i for each active category)
将结果限制在 [0, 100] 范围内。
分数解读
| 范围 | 状态 |
|---|---|
| 80-100 | 健康 |
| 60-79 | 需要关注 |
| 0-59 | 严重 |
7A. 跨类别去重
在计算分数之前,并在验证环节(第 4B 节)移除被驳回的问题并应用降级之后,对多个类别针对同一问题提出的问题进行去重。
去重流程
-
按位置分组问题。 将每个问题的
location规范化为{file}:{start_line}。如果两个问题位于同一文件,且行范围重叠(即 start_line_A <= end_line_B 且 start_line_B <= end_line_A),则视为重叠。 -
先检查是否确有分歧。 去重适用于“同一问题,不同视角”,而非相互矛盾的建议。如果两个重叠问题的建议方向相反(例如,SOLID 建议抽取抽象,而性能类别认为该抽象会带来开销;架构类别建议解耦,而性能类别建议保持局部性),则不要去重。保留两个问题的完整严重级别,并将这组问题列入报告的相互冲突的建议部分,同时用一行说明列出需要权衡的事项。操作人员必须看到这种冲突并作出决定——悄悄选出一个胜者,会掩盖恰恰需要人工判断的事项。
-
针对其余来自不同类别、彼此重叠的问题组: a. 选择主要问题。 按以下优先顺序处理:
- 涉及身份验证、注入或数据暴露的问题,优先选择安全性问题(SEC)
- 涉及异常或验证的问题,优先选择错误处理问题(ERR)
- 涉及查询或缓存的问题,优先选择性能问题(PERF)
- 涉及结构性违规的问题,优先选择 SOLID 问题(SRP/OCP/LSP/ISP/DIP)
- 涉及层级或边界违规的问题,优先选择架构问题(ARCH)
- 如果仍无法确定,则优先选择权重较高的类别(第 7 节)
b. 移除重复项。 将组内每个非主要问题从问题列表中彻底移除——它既不会出现在报告正文中,也不会计入所属类别的严重级别统计。(早期版本会将重复项降级为
suggestion,这只会让建议数量被无关项虚增。) c. 交叉引用主要问题。 在主要问题的suggestion字段末尾追加:Also flagged by: {list of duplicate category:id pairs}— 这会保留跨类别信号(也会影响热点排名),同时避免重复条目。 d. 统计移除项。 记录移除的重复项总数,并在仪表板的“已移除重复项”一行中报告。
-
去重后重新统计每个类别的严重级别总数,然后继续评分。
示例
- 在同一位置发现“刷新会绕过配额”:SEC-007、ERR-011、FW-001。保留 SEC-007(交叉引用“另见:ERR-011、FW-001”),删除 ERR-011 和 FW-001。
- 在同一文件中发现“上帝组件”:SRP-001、SMELL-001、ARCH-005。保留 SRP-001(结构性问题优先采用 SOLID),删除其他项。
- SRP-002 建议“从
OrderService中提取PricingCalculator”,而同一行的 PERF-004 则指出“这条热路径应保持内联——间接调用会导致每个请求都产生分配”:这是实质性冲突——两项都保留,并在“冲突建议”下呈现。
8. 报告呈现
根据所用命令呈现最终输出。
/codeprobe audit — 完整审计报告
使用 templates/full-audit-report.md 中的模板(通过 Read 加载)来组装保存的报告文件的 Markdown。终端输出是摘要——用户必须在终端中看到可视化摘要,不能只看到“报告已保存”这一行。
终端与保存文件的内容划分(强制):
| 界面 | 显示内容 | 生成方式 |
|---|---|---|
| 终端 | 仪表板 + 执行摘要 + 关键发现(完整详情)+ 优先修复顺序(前 5 项)+“报告已保存”一行 | 在助手回复中流式输出 Markdown 各部分 |
保存的文件(./codeprobe-reports/<project>-<cmd>-<ts>.md) | 全部内容:仪表板、执行摘要、所有关键/主要发现、次要问题/建议数量、完整优先修复顺序、“验证后降级”和“验证后驳回”部分 | 使用 Write 工具写入纯 Markdown |
终端输出绝不能为空,也不能缩减为仅有保存确认。如果 Claude 在之前的运行中只输出了保存提示,那就是未正确遵循这些指令导致的错误——应按顺序执行以下流程予以修正。
逐步流程
A. 计算数据(两个界面共用)
- 按第 4 节运行子技能,收集发现项;按第 4B 节验证关键/主要发现项;按第 7A 节去重。
- 计算类别评分、总评分、热点和代码库统计信息。
- 在内存中组装“报告数据包”:
{dashboard_data, exec_summary, critical[], major[], minor_counts[], suggestion_counts[], fix_order[], rejected[], rejected_count, downgraded[], downgraded_count, unverified_categories}。
B. 呈现到终端(面向用户——按顺序在助手回复中直接输出为 Markdown)
不要通过 Bash 工具传递仪表板。Claude Code 的界面默认会折叠 Bash 工具的输出(+N lines (ctrl+r to expand)),将仪表板隐藏在折叠区域中。应将仪表板作为普通的助手回复 Markdown 输出,让用户能立即看到。现代终端(Ghostty、iTerm2 等)会自行应用 Markdown 样式——粗体、行内代码高亮、强调——这是此路径中唯一可用的着色方式。如果没有显示颜色,纯文本也可以;不要尝试在回复中强行加入 ANSI 转义序列。
(对于用户在 Claude Code 之外的自有 Shell 中直接运行审计,scripts/render_dashboard.py 可供使用,其标准输出是真正的 TTY。不要在 /codeprobe audit 流程中调用它。)
- 仪表板(markdown) — 内联输出仪表板区块。包括:标题行(
## Code Health Report — {project})、**Overall Health:** {score}/100 [{status_label}]、包含 9 行的 Category Scores markdown table,列为Category | Score | Bar | Status(进度条用反引号括起,使用 20 个 Unicode 字符█/░,按分数比例显示)、代码库统计区块(文件数、LOC、后端/前端占比、最大文件、测试比例、注释比例)、热点列表(最多 3 项),以及最后单独一行的**Rejected by verification:** {rejected_count}(当unverified_categories> 0 时,附加({n} categories unverified);n 为 1 时使用category;仅当配置verify为false时才省略整行)。Status 列中的状态标签使用纯文本,不用表情符号,表格内不加方括号。 - 执行摘要 — 用 2–3 句话概述最重要的发现。
- 关键发现 — 完整详情 — 针对每项关键发现,提供:ID、位置、问题、严重性判定依据、证据、建议、修复提示词。(仍为 Critical 的发现从未被降级,因此这里不会出现
**Verification:**行;降级项列在已保存文件的 “Downgraded by Verification” 表格中。)这是信号最集中的部分;始终在终端中显示。 - 优先修复顺序(前 5 项) — 显示完整优先修复顺序中的前 5 项。完整列表请参阅已保存文件。
- 保存确认行 —
--> Report saved to ./codeprobe-reports/{project}-{cmd}-{YYYY-MM-DD-HHMMSS}.md(不使用表情符号;使用 ASCII 箭头)。这是终端输出的最后一行。
不要同时在终端输出主要发现表、次要/建议数量或完整修复顺序——这些内容已包含在保存文件中,重复输出会使终端内容冗长。用户可以打开已保存文件查看完整内容。
C. 编写已保存文件的 markdown
- 使用
templates/full-audit-report.md中的占位符构建完整 markdown,其中包含不会输出到终端的部分(主要发现表、次要/建议数量、完整优先修复顺序、“Downgraded by Verification” 表格——当downgraded_count为 0 时省略,以及折叠的 “Rejected by Verification” 区块——当rejected_count为 0 时省略)。 - 按
{project}-{cmd}-{YYYY-MM-DD-HHMMSS}.md生成文件名:{project}— 将目标路径解析为绝对路径(用户未传入路径时,使用当前工作目录);取其基本名;如果该基本名指向文件,则去掉扩展名;将其转换为 slug(小写;将[^a-z0-9]+的任意连续匹配替换为单个-;去除开头和结尾的-);如果 slug 为空,则使用unknown。{cmd}— 第 1 节中路由的子命令(audit、diff、security、solid、architecture、performance、errors、tests、smells、patterns、framework),转换为小写。{YYYY-MM-DD-HHMMSS}— 当前本地时间,通过一次 Bash 调用获取:date +%Y-%m-%d-%H%M%S。如果 Bash 不可用或被拒绝,则使用任意工具输出中可见的最新时间戳;否则使用0000-00-00-000000;绝不可让占位符未填充。
- 确保
./codeprobe-reports/存在(如不存在,通过 Bash 执行mkdir -p ./codeprobe-reports)。 - 使用
Write工具写入./codeprobe-reports/{project}-{cmd}-{YYYY-MM-DD-HHMMSS}.md。 - 如果写入失败(文件系统只读、权限被拒绝等),在终端中简短提示,但不要重新输出摘要。
D. 终端输出约定(硬性要求)
- 终端输出必须按以下顺序包含:仪表板 → 执行摘要 → 关键发现 → 前 5 项修复顺序 →「报告已保存」行。
- 当配置
verify开启时(默认开启),仪表板必须以**Rejected by verification:**行结尾——0是有效计数。 - 如果没有关键发现,则显示仪表板、执行摘要、一行「未发现关键问题」说明、前 5 项修复顺序(仅包含主要问题)和保存确认——内容仍不得为空。
- 如果报告保存失败,仍须输出完整的终端摘要——不得因文件写入而阻止输出摘要。
- 如果模板文件缺失,则按照相同的章节顺序内联呈现;保存步骤 (C) 仍适用。
状态阈值(适用于整体健康度和各类别评分):
- 80-100 =「健康」
- 60-79 =「需要关注」
- 0-59 =「严重」
令牌预算指南: 对于约有 100 项发现的代码库,分层发现布局(主要问题使用表格,次要问题/建议仅显示计数——全部详情保存在文件中)预计在磁盘上占用约 8,000-12,000 个令牌(相比之下,所有发现均提供完整详情时约为 40,000 个令牌)。终端摘要要精简得多,因为其中只会输出仪表板、执行摘要、关键发现和前 5 项修复顺序。用户可以通过 /codeprobe security . 等命令查看特定类别的完整详情。
/codeprobe quick — 快速审查摘要
使用模板 templates/quick-review-summary.md(通过 Read 加载)。呈现之前,先对暂定的前 8 项执行第 4B 节(/codeprobe quick 呈现规则)中说明的单次验证流程;表格显示排名前 5 的保留项,降级项在其 Severity 单元格中附带降级说明。如果因候选项被拒绝而导致呈现的条目少于 5 项,则显示一行说明。若模板尚不存在,则内联呈现:
- 标题:项目名称、「快速审查 — 前 5 项问题」。
- 前 5 项发现:对影响最大的 5 个问题提供完整详情,并为每项附上修复提示词。
- 摘要计数:按严重程度统计所有类别中的问题总数(移除被拒绝的候选项,降级项按其新严重程度计入),然后显示
**Estimated Score:**,接着显示**Rejected by verification:** {rejected_count}(第 4B 节报告规则)。 - 后续步骤:建议运行
/codeprobe audit了解完整情况。
/codeprobe diff — PR 风格审查
使用模板 templates/pr-review-comment.md(通过 Read 加载)。将 {branch} 替换为当前分支(git rev-parse --abbrev-ref HEAD),将 {base_branch} 替换为解析出的基准分支,将 {changed_files} 替换为已审查文件数,并将 {overall_score} 替换为按照标准公式(第 7 节)对差异发现应用计算后的分数。将 {version} 替换为此文件 frontmatter 中的 metadata.version。
- 终端:将填充后的模板直接作为助手响应 Markdown 输出(内容足够精简,可整体输出),然后输出保存确认行(格式与第 8B 节步骤 5 相同)。
- 已保存文件:将相同的 Markdown 按照第 8C 节的文件名和写入规则,写入
./codeprobe-reports/{project}-diff-{YYYY-MM-DD-HHMMSS}.md。 - 呈现的 Markdown 专为粘贴到 GitHub PR 评论中而设计——内容必须自包含(正文中不得提及「已保存的文件」)。
- 差异发现适用验证规则(第 4B 节);
{rejected_count}用于填充摘要表格中的「Rejected by verification」行,降级发现的要点则在问题文本后附加_(downgraded from {old_severity} by verification)_(即模板中的{downgrade_note})。
/codeprobe <category> — 单类别报告
适用于 security、solid、architecture、performance、errors、tests、smells、patterns 和 framework。一个子技能以 full 模式运行,然后由一个验证器进行验证(第 4B 节)。单个类别的范围有限,用户深入查看某个类别正是为了获取完整细节,因此此处不要将 Minor 或 Suggestion 级别的发现折叠为计数。
终端(直接以助手回复的 Markdown 输出,顺序如下):
- 标题:
## {Category} Review — {project},并在下一行列出计数:{n} critical · {n} major · {n} minor · {n} suggestions。 - 每条发现的完整详情,按
### Critical Issues、### Major Issues、### Minor Issues、### Suggestions分组(省略空分组),每条均按shared-preamble.md中的 Rendered Finding Format 呈现,包括**Severity rationale:**行;如果发现的严重程度已下调,还需包含**Verification:**行。 - 按照第 4B 节的报告规则,显示
**Rejected by verification:** {rejected_count}。 - 保存确认行——格式与第 8B 节第 5 步相同。
保存的文件:与终端输出相同的 Markdown,另加折叠的“Rejected by Verification”部分(包含一个 <details>,内含 ID | Location | Reason 表格;当 rejected_count 为 0 时省略),并按照第 8C 节的文件名和写入规则,写入 ./codeprobe-reports/{project}-{cmd}-{YYYY-MM-DD-HHMMSS}.md。
9. Claude.ai 降级模式
检测是否可访问文件系统。如果用户粘贴或上传了代码,而不是提供文件路径,或者 Read/Glob/Grep 工具不可用:
- 切换到降级模式:仅分析上下文中提供的代码。
- 按顺序执行子技能,分析粘贴的代码(不使用并行 Agent)。
- 跳过
file_stats.py、dependency_mapper.py及所有依赖脚本的步骤(子技能改用仅由大模型执行的分析——架构分析将无法进行确定性的循环检测)。 - 跳过
/codeprobe diff、审计仪表板中的 Codebase Stats 行,以及报告保存步骤(不写入文件系统)。仍需在终端输出评分、热点和发现。 - 跳过验证流程(第 4B 节)——没有可运行验证器的子 Agent——并按照第 4B 节的报告规则输出
**Rejected by verification:** 0 ({n} categories unverified);其中 n 为其 Critical 或 Major 级别发现原本需要交由验证器处理的类别数量;当 n 为 0 时省略括号中的后缀。 - 告知用户:“正在 Claude.ai 模式下运行——代码库统计、差异审查和多文件分析等部分功能不可用。正在直接分析所提供的代码。”
- 仍需按标准输出约定格式生成发现。
- 仍需根据可用子技能的发现计算评分。
10. 执行流程摘要
调用 /codeprobe 时,按以下顺序执行:
- 解析命令:从用户输入中提取子命令和目标路径。
- 验证命令:检查路由表。如果子命令未知,说明情况并列出可用命令。
- 解析目标路径:使用提供的路径,或默认使用当前工作目录。对于
diff:改为按照第 4A 节解析基准引用,并收集已更改文件及其行范围——清单仅限于这些文件。 - 加载配置:检查项目根目录是否存在
.codeprobe-config.json。如果不存在,则应用默认值。 - 自动检测技术栈:扫描目标路径以查找技术信号。加载匹配的参考资料。
- 应用配置覆盖项:如果配置中设置了
framework,则调整检测结果。应用skip_categories和skip_rules。 - 执行子技能:准备共享上下文(第 4 节),然后以适当模式并行启动所有适用的子技能 Agent。
- 收集发现项:按输出约定格式汇总所有发现项。
8a. 验证发现项:对严重/主要级别的发现项执行第 4B 节(每个类别启动一个验证器,并行运行;
quick使用一个验证器验证其初步前 8 项中的严重/主要发现项);删除未通过验证的发现项,应用降级,记录rejected_count、downgraded_count和unverified_categories。如果配置项verify为false,或处于 Claude.ai 降级模式(第 9 节),则跳过此步骤。 - 去重发现项:应用跨类别去重流程(第 7A 节)——将真正的冲突归入“冲突建议”部分,删除真正重复的发现项,并重新统计各类别的严重级别数量。
- 计算分数:使用去重后的严重级别数量以及第 7 节中的公式,计算各类别及总体分数。
- 生成报告:使用适当的模板或内联格式整理输出。对于
/codeprobe audit,使用分层输出格式。 - 呈现给用户:显示最终报告。
请记住:整个过程均为只读。在任何情况下都不会修改用户文件。