name: review description: 代码审查与自动修复 — 计划与实现对比或结构化git差异审查。自动修复审查中发现的问题。 allowed-tools: 读、写、编辑、Bash、Glob、Grep、AskUserQuestion disable-model-invocation: true
执行后审查
对计划与实际实现进行严格、结构化的比较。每个接受标准都有一个裁决。检查范围合规性。审查中发现的问题在可能时自动修复;复杂问题记录为待办事项。
步骤1:查找并加载计划
从活动和归档目录中发现所有计划:
Glob(".maestro/plans/*.md")
Glob(".maestro/archive/*.md")
- 如果两个目录中都没有计划:跳转到无计划审查流程。
- 如果恰好有一个计划(来自任一目录):加载它。
- 如果多个计划:通过
AskUserQuestion向用户呈现组合列表,并询问要审查哪个计划。包括文件名、修改日期和位置上下文 — 将.maestro/plans/中的计划标记为**(active),.maestro/archive/中的计划标记为(archived)**。加载选定的计划。
完整读取所选计划文件。
步骤2:解析所有计划部分
从计划中提取这些部分:
- 目标 — 顶级目标声明
- 范围(内) — 明确在范围内的项目(在
**In**:下的项目列表) - 范围(外) — 明确在范围外的项目(在
**Out**:下的项目列表) - 任务 — 每个任务包括:
- 任务编号和标题(来自
- [ ] Task N: Title或- [x] Task N: Title) - 提交SHA(来自复选框行的
<!-- commit: {SHA} -->注释,如果存在) - 文件路径(来自
**File**: \path``) - 描述(来自
**Description**:) - 接受标准(在
**Acceptance criteria**:下的项目列表) - 代理分配(来自
**Agent**:)
- 任务编号和标题(来自
- 验证 — 验证部分中列出的命令/检查
- 笔记 — 任何技术决策、回滚策略、研究发现
如果任何部分缺失,记录为[SECTION NOT FOUND]并继续。
步骤3:验证每个任务的接受标准
对于计划中的每个任务,检查每个接受标准个体:
- 提交可追溯性:如果任务有
<!-- commit: {SHA} -->注释,使用git show {SHA} --stat识别该提交中更改的确切文件,并使用git show {SHA}检查差异。这将验证范围限制为此任务实际进行的更改,而不是搜索整个代码库。 - 文件存在:
**File**:中引用的文件是否存在?(Glob) - 每标准检查:对于每个接受标准:
- 如果提交SHA可用,优先检查
git show {SHA}的差异以获取证据 - 否则,读取目标文件并使用Grep/Read查找证据
- 查找描述的具体模式、函数、部分或行为
- 标记为通过(找到证据)或失败(无证据或矛盾证据)
- 记录证据(文件路径+行号或grep匹配)或失败原因
- 如果提交SHA可用,优先检查
不要只检查文件存在 — 验证内容匹配每个标准。
步骤4:检查范围合规性(范围外)
对于范围部分**Out**:下列出的每个项目:
- Grep/Glob查找文件、模式或更改,表明在范围外项目上进行了工作
- 如果找到范围外工作的证据,标记为范围违规
- 记录发现的内容和位置
这捕获了范围蔓延 — 明确排除但完成的工作。
步骤5:检查范围完整性(范围内)
对于范围部分**In**:下列出的每个项目:
- 查找实现证据:创建的文件、编写的函数、更改的配置
- 对照任务列表交叉参考 — 这个范围内项目是否由至少一个任务覆盖?
- 标记为已覆盖或未覆盖
这捕获了范围缺口 — 承诺但未交付的工作。
步骤6:运行验证命令
执行计划## Verification部分中的每个验证命令:
- 通过Bash运行命令
- 记录输出
- 如果命令成功(退出代码0且输出符合预期)标记为通过,失败则标记为失败
- 对于测试内容存在的命令(例如grep),通过意味着找到内容
如果验证命令引用未安装的工具或包,标记为跳过并说明原因。
步骤7:检查回归
查找并运行项目的标准验证检查:
- 检查
package.json中的test、build、lint、typecheck脚本 — 如果存在则运行它们 - 检查
Makefile— 如果存在则运行相关目标 - 检查CI配置(
.github/workflows/、.gitlab-ci.yml) — 注意CI将运行的内容 - 检查验证脚本(例如
scripts/validate-*.sh) — 运行它们
将每个结果记录为通过、失败或跳过(带原因)。
步骤8:检查智慧提取
检查/work是否为此执行创建了智慧文件:
Glob(".maestro/wisdom/*.md")
- 查找与此计划对应的智慧文件(按名称或时间戳)
- 如果找到:通过 — 记录文件路径
- 如果未找到:失败 — 遗漏了智慧提取
步骤9:生成结构化报告
以确切格式生成最终报告:
## 审查:{计划名称}
**计划**:`{计划文件路径}`
**审查日期**:{当前日期}
---
### 目标
{从计划中陈述目标}
**达成**:是 / 部分 / 否
---
### 任务完成情况
#### 任务{N}:{标题}
**文件**:`{路径}`
**提交**:`{SHA或"无"}`
**状态**:完成 / 部分 / 缺失
| # | 标准 | 裁决 | 证据 |
|---|------|------|------|
| 1 | {标准文本} | 通过/失败 | {文件:行或原因} |
| 2 | {标准文本} | 通过/失败 | {文件:行或原因} |
{对每个任务重复}
---
### 范围合规性
**范围内覆盖情况:**
| 项目 | 状态 | 证据 |
|------|------|------|
| {范围内项目} | 已覆盖/未覆盖 | {实施位置} |
**范围外违规:**
| 项目 | 状态 | 证据 |
|------|------|------|
| {范围外项目} | 清洁/违规 | {发现内容} |
---
### 验证结果
| # | 检查 | 结果 | 输出 |
|---|------|------|------|
| 1 | {验证命令} | 通过/失败/跳过 | {摘要} |
---
### 回归检查
| 检查 | 结果 | 输出 |
|------|------|------|
| {检查名称} | 通过/失败/跳过 | {摘要} |
---
### 智慧提取
**状态**:通过 / 失败
**文件**:`{路径或"未找到"}`
---
### 补救措施
{仅当有失败时包括此部分}
对于每个失败,提供具体的修复建议:
- **任务{N},标准{M}**:{需要做什么来修复它}
- **范围违规 — {项目}**:{如何撤销或处理}
- **验证 — {检查}**:{如何修复失败的检查}
---
### 自动修复结果
{由步骤9.5填充 — 见下文}
---
### 裁决:完成 / 需要工作 / 失败
**摘要**:{1-2句摘要}
- **完成**:所有标准通过,范围清洁,验证通过,智慧提取
- **需要工作**:大多数标准通过但一些失败需要关注
- **失败**:大多数标准失败或关键任务缺失
{如果需要工作或失败,列出需要关注的具体项目}
填充每个部分。不要跳过部分 — 如果部分没有适用项目,使用“N/A”。证据要精确:包括文件路径和行号,而不是模糊描述。
步骤9.5:自动修复
生成报告后,自动修复可以通过机械编辑解决的问题。
分类发现
审查报告中的每个失败发现(任务完成标准、范围违规、验证失败)。将每个分类为:
- 可修复:缺失的导出、错误的函数/变量名、缺失的导入、不正确的配置值、markdown文件中缺失的部分、引用中的错误文件路径、具有明显修正的小逻辑错误。修复是明确的,并限于少数几行。
- 复杂(待办):缺失的功能实现、架构更改、需要新的测试文件、需要设计决策、多文件重构且范围不明确。修复需要判断或大量新代码。
应用修复
对于每个可修复发现:
- 使用报告证据中的路径和行号读取目标文件
- 使用
Edit(file_path, old_string, new_string)应用修复 — 使用最小的可能编辑 - 记录更改的内容:
{文件}:{行} — {修复描述}
对于每个复杂发现:
- 不要尝试修复
- 记录为待办:
待办:{任务N,标准M} — {需要做什么}
重新运行验证
应用所有修复后,重新运行步骤6中的验证命令和步骤7中的回归检查:
# 重新运行计划验证命令
Bash("{计划中的每个验证命令}")
# 重新运行项目验证
Bash("{步骤7中的test/build/lint命令}")
记录更新后的结果。
更新报告
填充报告中的自动修复结果部分(步骤9中添加的占位符):
### 自动修复结果
**已修复({失败总数中的N个}):**
| # | 发现 | 文件 | 应用修复 |
|---|------|------|----------|
| 1 | {任务N,标准M或发现描述} | `{文件}:{行}` | {更改内容} |
**未修复 — 待办({剩余M个}):**
| # | 发现 | 原因 |
|---|------|------|
| 1 | {任务N,标准M或发现描述} | {为什么无法内联修复} |
**重新验证:**
| # | 检查 | 修复前 | 修复后 |
|---|------|--------|--------|
| 1 | {命令或检查名称} | 失败 | 通过/失败 |
如果报告中未发现失败,填充部分为:没有问题需要修复。
重新计算裁决
修复后,基于仅剩余未修复问题更新裁决:
- 完成:所有失败已修复(或不存在),重新验证通过
- 需要工作:一些失败已修复但待办事项仍存在
- 失败:关键失败无法修复,或重新验证仍失败
更新报告底部的裁决部分以反映修复后状态。附加说明:
自动修复应用:{N}个问题已修复,{M}个剩余为待办。
修复升级循环
如果自动修复后重新验证仍显示失败结果:
- 第1轮:重新读取失败文件,根据错误输出应用第二轮有针对性的编辑修复
- 第2轮:如果仍失败,使用Bash运行失败命令,捕获完整错误输出,并基于完整错误上下文应用修复
- 第3轮:如果仍失败,停止并将剩余失败报告为待办事项
退出条件:
- 所有失败解决 → 更新裁决为完成/需要工作
- 相同失败3轮 → 停止,标记为待办
- 最大总轮数为3(包括初始自动修复尝试)
更新最终裁决并附加:自动修复升级:{M}轮中修复了{N}个额外问题,{R}个剩余为待办。
步骤10:审查后归档
如果裁决为完成且计划是从.maestro/plans/加载的(尚未在.maestro/archive/中):
- 如果归档目录不存在,则创建它:
mkdir -p .maestro/archive/ - 将计划移动到归档:
mv .maestro/plans/{name}.md .maestro/archive/{name}.md - 报告:“计划已归档到
.maestro/archive/{name}.md”
如果计划已在.maestro/archive/中,或裁决不为完成,则不做任何事情。
审查后知识捕获(自动)
触发条件:审查找到≥2个失败发现(跳过清洁审查)。
自动提取审查见解作为学习技能:
- 从审查报告中收集所有失败发现
- 按模式分组(例如,“缺失导出”、“未测试边缘情况”、“硬编码秘密”)
- 对于每个出现2次以上的模式,应用学习者质量门(非可谷歌、特定上下文、可操作、来之不易)
- 通过模式 → 保存到
.claude/skills/learned/{slug}.md,触发器匹配模式关键词 - 单次出现失败 → 跳过(尚不构成模式)
这确保复发性审查失败被编纂为未来代理将看到的技能,打破重复错误的循环。
无计划审查流程
当未找到计划时,基于git更改执行结构化代码审查。
步骤P1:确定差异范围
通过检查git状态识别要审查的更改:
-
检查是否在功能分支(不是
main或master):Bash("git rev-parse --abbrev-ref HEAD")- 如果在功能分支:与基础分支(
main或master)差异Bash("git diff main...HEAD --name-only") - 如果在
main/master:差异最近的提交与未提交更改
如果无未提交更改,差异最后一个提交:Bash("git diff HEAD --name-only")Bash("git diff HEAD~1 --name-only")
- 如果在功能分支:与基础分支(
-
如果根本未找到更改:报告"未检测到更改。无需审查。"并停止。
-
收集完整差异用于确定的范围:
Bash("git diff main...HEAD") # 或上述适当的差异命令 -
列出更改的文件及其更改类型(添加/修改/删除):
Bash("git diff main...HEAD --name-status")
记录差异范围(分支名、提交范围或“未提交”)用于报告头部。
步骤P2:代码质量审查
对于每个更改的文件(跳过删除的文件),读取文件和相关的差异块。检查:
- 命名 — 变量、函数、类的命名是否清晰且与项目约定一致?
- 结构 — 代码组织良好吗?函数/方法大小合理吗?有不必要的嵌套吗?
- 可读性 — 其他开发人员能理解此代码而无需过多注释吗?复杂部分有文档吗?
- 重复 — 有应提取的复制粘贴代码吗?使用Grep检查代码库中的类似模式。
- 死代码 — 差异中引入了未使用的导入、变量或函数吗?
对于每个文件,读取它:
Read("{file_path}")
将发现记录为{文件, 行, 维度, 严重性, 描述}元组列表。严重性级别:
- 失败 — 必须修复:错误、逻辑损坏、明显违规
- 警告 — 应该修复:不良命名、不必要的复杂性、轻微重复
- 信息 — 考虑:样式建议、小改进
步骤P3:安全审查(自动委托)
为差异生成security-reviewer代理进行深度安全分析:
Task(
description: "代码审查的安全审查",
subagent_type: "security-reviewer",
model: "sonnet",
prompt: |
分析以下差异中的安全漏洞:
{步骤P1的差异}
检查:身份验证/授权、输入验证、秘密暴露、注入风险(SQL、XSS、命令)、依赖安全、敏感数据记录、错误消息泄露。
如果适用,运行生态系统审计(bun audit / pip-audit / govulncheck)。
用以下内容报告每个发现:严重性(关键/高/中/低)、文件:行、描述、建议。
)
将安全审查发现映射到审查维度:
- 关键/高 → 审查报告中的失败严重性
- 中 → 警告严重性
- 低 → 信息严重性
所有发现进入审查的“按文件发现”表,维度为“安全”。
步骤P4:测试覆盖审查
对于每个包含实现代码的更改文件(不是测试文件、配置或文档):
-
识别预期测试文件 — 基于项目约定,确定测试应存放的位置:
Glob("**/*test*{file_basename}*") Glob("**/*{file_basename}*test*") Glob("**/__tests__/{file_basename}*") Glob("**/test_*{file_basename_no_ext}*") -
检查测试存在 — 是否存在相应的测试文件?
- 如果是:读取它并检查更改/新函数是否被覆盖
- 如果否:标记为警告(“未找到{file}的测试文件”)
-
检查差异中的测试更改 — 测试文件是否作为此更改的一部分被修改?
- 新函数/方法添加无相应测试添加 = 警告
- 错误修复无回归测试 = 警告
- 纯重构且有现有通过测试 = 信息(可接受)
记录发现:
- 失败 — 新的公共API或关键逻辑零测试覆盖
- 警告 — 更改逻辑无更新测试,或缺失测试文件
- 信息 — 测试覆盖存在但可更彻底
步骤P5:回归检查
运行项目的标准验证检查(与基于计划的步骤7相同):
- 检查
package.json中的test、build、lint、typecheck脚本 — 如果存在则运行它们 - 检查
Makefile— 如果存在则运行相关目标 - 检查CI配置(
.github/workflows/、.gitlab-ci.yml) — 注意CI将运行的内容 - 检查验证脚本(例如
scripts/validate-*.sh) — 运行它们
将每个结果记录为通过、失败或跳过(带原因)。
步骤P6:提交卫生审查
如果审查具有多个提交的分支,检查提交质量:
Bash("git log main..HEAD --oneline")
检查:
- 原子提交 — 每个提交是否代表单个逻辑更改?标记混合不相关更改的提交(例如,功能+格式化)
- 提交消息 — 消息描述性强吗?标记通用消息如“修复”、“更新”、“wip”、“asdf”
- 调试工件 — 检查差异中残留的
console.log、debugger、print()、TODO/FIXME,这些似乎是临时的:Grep("(console\\.log|debugger|print\\(|TODO|FIXME|HACK|XXX)", changed_files) - 大文件 — 标记任何单个文件更改超过500行(可能需要拆分)
- 敏感文件 — 标记对可能包含秘密的
.env、凭据或配置文件的更改
记录发现:
- 失败 — 生产代码中的调试工件、提交的秘密
- 警告 — 不良提交消息、非原子提交、大更改
- 信息 — 小样式观察
步骤P7:生成无计划审查报告
以确切格式生成报告:
## 代码审查:{分支名或“未提交更改”}
**范围**:`{差异描述,例如,“功能分支 vs. main(12次提交,8个文件)”}`
**审查日期**:{当前日期}
---
### 更改的文件
| # | 文件 | 状态 | 发现 |
|---|------|------|------|
| 1 | `{路径}` | 添加/修改/删除 | {计数}失败,{计数}警告,{计数}信息 |
---
### 按文件发现
#### `{文件路径}`
| # | 行 | 维度 | 严重性 | 发现 |
|---|----|------|--------|------|
| 1 | {行} | 质量/安全/测试/卫生 | 失败/警告/信息 | {描述} |
{对每个有发现的文件重复}
---
### 回归检查
| 检查 | 结果 | 输出 |
|------|------|------|
| {检查名称} | 通过/失败/跳过 | {摘要} |
---
### 摘要
| 维度 | 失败 | 警告 | 信息 |
|------|------|------|------|
| 代码质量 | {n} | {n} | {n} |
| 安全 | {n} | {n} | {n} |
| 测试覆盖 | {n} | {n} | {n} |
| 提交卫生 | {n} | {n} | {n} |
| **总计** | **{n}** | **{n}** | **{n}** |
---
### 自动修复结果
{由步骤P7.5填充 — 见下文}
---
### 裁决:清洁 / 需要工作 / 失败
**摘要**:{1-2句摘要}
- **清洁**:无失败,少或无警告,回归通过
- **需要工作**:无失败但多个警告应解决
- **失败**:一个或多个失败必须在合并前修复
{如果需要工作或失败,列出需要关注的具体项目}
填充每个部分。如果文件无发现,从“按文件发现”中省略,但保留在“更改的文件”表中“0发现”。行号要精确。
步骤P7.5:自动修复
生成报告后,自动修复可以通过机械编辑解决的问题。
分类发现
审查报告中的每个失败发现(代码质量、安全、测试覆盖、提交卫生维度)。将每个分类为:
- 可修复:未使用的导入、缺失的导出、死代码标记为删除、调试工件(
console.log、debugger、print())、小命名修复、缺失类型注释且类型明显。修复明确且限于少数行。 - 复杂(待办):缺失的测试文件、架构问题、需要设计更改的安全漏洞、大重构。修复需要判断或大量新代码。
同时审查警告发现 — 应用相同分类。修复机械的警告(例如,移除console.log),跳过需要判断的警告。
应用修复
对于每个可修复发现:
- 使用报告证据中的路径和行号读取目标文件
- 使用
Edit(file_path, old_string, new_string)应用修复 — 使用最小的可能编辑 - 记录更改的内容:
{文件}:{行} — {修复描述}
对于每个复杂发现:
- 不要尝试修复
- 记录为待办:
待办:{维度,文件:行} — {需要做什么}
重新运行回归检查
应用所有修复后,重新运行步骤P5中的回归检查:
# 重新运行项目验证
Bash("{步骤P5中的test/build/lint命令}")
如果一个先前通过的回归检查在修复后失败:
- 撤销修复导致回归的修复,使用
Edit恢复原始代码 - 将该发现重新分类为复杂(待办),说明:
已撤销 — 在{检查名称}中导致回归 - 重新运行失败的检查以确认撤销解决它
记录更新后的结果。
更新报告
填充报告中的自动修复结果部分(步骤P7中添加的占位符):
### 自动修复结果
**已修复({失败+警告总数中的N个}):**
| # | 发现 | 文件 | 应用修复 |
|---|------|------|----------|
| 1 | {维度:描述} | `{文件}:{行}` | {更改内容} |
**未修复 — 待办({剩余M个}):**
| # | 发现 | 原因 |
|---|------|------|
| 1 | {维度:描述} | {为什么无法内联修复} |
**重新验证:**
| # | 检查 | 修复前 | 修复后 |
|---|------|--------|--------|
| 1 | {检查名称} | 通过/失败 | 通过/失败 |
如果报告中未发现失败或可修复警告,填充部分为:没有问题需要修复。
重新计算裁决
修复后,基于仅剩余未修复问题更新裁决:
- 清洁:所有失败已修复(或不存在),无警告剩余,回归通过
- 需要工作:所有失败已修复但警告或待办事项仍存在
- 失败:失败无法修复,或重新验证仍失败
更新报告底部的裁决部分以反映修复后状态。附加说明:
自动修复应用:{N}个问题已修复,{M}个剩余为待办。
修复升级循环
如果自动修复后重新验证仍显示失败结果:
- 第1轮:重新读取失败文件,根据错误输出应用第二轮有针对性的编辑修复
- 第2轮:如果仍失败,使用Bash运行失败命令,捕获完整错误输出,并基于完整错误上下文应用修复
- 第3轮:如果仍失败,停止并将剩余失败报告为待办事项
退出条件:
- 所有失败解决 → 更新裁决为清洁/需要工作
- 相同失败3轮 → 停止,标记为待办
- 最大总轮数为3(包括初始自动修复尝试)
更新最终裁决并附加:自动修复升级:{M}轮中修复了{N}个额外问题,{R}个剩余为待办。
审查后知识捕获(自动)
触发条件:审查找到≥2个失败发现(跳过清洁审查)。
自动提取审查见解作为学习技能:
- 从审查报告中收集所有失败发现
- 按模式分组(例如,“缺失导出”、“未测试边缘情况”、“硬编码秘密”)
- 对于每个出现2次以上的模式,应用学习者质量门(非可谷歌、特定上下文、可操作、来之不易)
- 通过模式 → 保存到
.claude/skills/learned/{slug}.md,触发器匹配模式关键词 - 单次出现失败 → 跳过(尚不构成模式)
这确保复发性审查失败被编纂为未来代理将看到的技能,打破重复错误的循环。