分支审核追踪器 是做什么的?
对分支进行多轮修复的审核。每一轮都会重新审核分支并更新一个页面:一个带编号的问题列表,每个问题都有状态和一个“详细信息”弹出框,其中给出证据、负责的提交以及需要查看的位置。
该页面是一个 claude.ai Artifact,它是审核的记录。查看者只能读取:只有 Claude 可以更改状态,随着审核和修复的推进而更新。新会话会从页面的小型 context.json 文件恢复,而不是从对话或本地文件。
追踪器包含三个文件:
index.html:页面,是assets/tracker.html的副本;issues.json:每个问题以及会话日志;context.json:恢复笔记、下一个会话的问题索引、启动会话的提示,以及等待用户处理的简短列表(这是页面显示的唯一部分)。
1. 询问审核内容
首先收集候选者,然后在一个 AskUserQuestion 调用中一次性询问所有内容。跳过随调用一起提供的答案所对应的问题,例如 PR 编号或 URL。
git for-each-ref --sort=-committerdate --count=6 --format='%(refname:short)' refs/heads
git symbolic-ref --short refs/remotes/origin/HEAD # 默认基础分支
git log --format=%s <base>..<target> | grep -oE '[A-Z]+-[0-9]+' | sort -u
gh pr list --head <target> --json number,url,title # 或:glab mr list --source-branch <target>
| 问题 | 选项 |
|---|---|
| 目标分支 | 如果提供了 PR,则为 PR 的头部分支;否则为除基础分支外最近更新的三个本地分支 |
| 基础分支 | 远程仓库的默认分支(推荐),然后是其他长期存在的分支(如有) |
| 工单 | 在分支名称及其提交主题中找到的 ID;无工单 |
用户始终可以输入其他值。在已知分支后询问工单问题,或者从其最可能的目标派生选项。
2. 检查环境
运行预检脚本并向用户显示其表格:
<this skill>/scripts/preflight --target <branch> [--base <base>] [--ticket <id>]
它会检查仓库、两个引用、用户的检出状态、本地分支是否匹配 PR 头部、主机上的 PR、可能阻止 git worktree 的检出过滤器,以及审核使用的 CLI。退出代码 2 表示阻塞性错误;1 表示仅有警告。它不检查项目的构建工具:这些属于项目的辅助技能。
该脚本会获取两个分支。它从远程仓库获取基础分支(那里是最新的),并从克隆获取目标分支(作者可能已推送)。针对脚本打印的引用进行审核。如果脚本警告本地分支与 PR 头部不同,则审核 PR 头部:使用 git show <sha>:<path> 读取它,而不是检出它。
然后检查此会话的工具(脚本无法看到),并将它们添加到表格中:
| 所需用途 | 工具 | 缺少时的影响 |
|---|---|---|
| 审核本身 | code-review 技能,或 Agent 工具 | 阻塞 |
| 页面 | Artifact 工具 | 将文件保留在临时区域并在每轮后向用户提供其路径;并告知用户 |
| 工单上下文及发布工单 | Atlassian 工具(getJiraIssue,createJiraIssue) | 在缺少的情况下进行审核;并告知用户 |
| PR 评论和检查 | 已认证的 gh 或 glab | 仅审核分支;并告知用户 |
然后查找项目的辅助技能,如下面的“辅助技能”部分所述,并为每个辅助技能在表格中添加一行:找到的,显示其名称;缺失的,显示审核将缺少什么。
在阻塞性错误时停止,并说明缺少什么。对于警告,说明审核不会涵盖的内容,然后继续。
如果可以读取工单,获取其摘要和状态。在 ID 后以括号形式写入状态:PROJ-123 (进行中)。
3. 第一轮
-
审核。 对
<target>针对<base>调用code-review,或针对 PR 编号调用。告诉审核者使用git show <rev>:<path>读取其他提交,并且永远不要在用户目录中检出任何内容。 -
审核说明文字,如下面的“说明文字审核”所述。
code-review负责查找代码中的缺陷,不涵盖此部分。 -
验证每条发现,如下面的“验证发现”所述。只有在此步骤之后,问题才会出现在页面上。未通过验证的发现要么在列出前被丢弃,要么在列出后将其状态设置为
dismissed并附上原因。 -
对每个问题进行分类。
- 负责的提交:
git log -S'<symbol>' <base>..<target>,或git blame -s <target> -- <path>。 - 基础分支是否也存在该问题:
git show <base>:<path>。基础分支已有的问题将获得"commitRole": "Pre-existing on"和"commit": "<base>"。它不算分支的回归,但当分支使其更严重时(例如,通过它暴露更多数据),仍可能阻止合并。 - 每个位置的
file:line,指向被审核的提交。
- 负责的提交:
-
将会话临时区域中的追踪器文件写入一个以分支命名(将
/替换为-)的文件夹:index.html:assets/tracker.html的副本,其中__TITLE__被替换为页面名称。名称是分支主题的两到四个单词,后跟“Review”,例如API Key Authorization Review。issues.json和context.json,如下面的“数据文件”所述。
-
验证这两个文件。验证器会检查模式、被审核提交处每个位置是否存在,以及
context.json中的索引是否与问题匹配:python3 -I <this skill>/scripts/validate-issues.py <dir>/issues.json --repo <repo> -
使用 Artifact 工具的发布操作发布,设置
file_path为<dir>/index.html,files为{"issues.json": "<dir>/issues.json", "context.json": "<dir>/context.json"},icon: "checklist"以及一句话的描述。将返回的 URL 写入两个文件("artifact"),重新发布,并向用户提供链接。
4. 后续轮次
当用户表示分支已更新,或要求重新审核时,运行一轮。
- 确认分支已移动。 将 PR 头部或目标引用与
reviewed进行比较,并查看git reflog -3 --date=iso <target>。推送可能延迟到达,用户的本地分支可能落后于 PR。如果没有任何移动,说明情况并停止。 - 获取基础分支(
git fetch origin <base>)。如果基础分支已移动,记录下来,并使用git range-diff <old-base>..<old-tip> <new-base>..<new-tip>比较分支。 - 查看更改内容:
git range-diff <base>..<reviewed> <base>..<target>显示哪些提交被重写、添加或删除;git diff <reviewed> <target>显示净更改;- PR 的新评论、审核和检查(
gh pr view <n> --json comments,reviews,gh api repos/<owner>/<repo>/pulls/<n>/comments,gh pr checks <n>)。
- 评估每个修复。 对于更改所解决的每个问题,阅读修复代码并记录在
fix中它做了什么以及代码现在如何表现。仅在阅读确认后设置fixed,并在verified中说明验证到何种程度。 - 查找修复引起的问题。 修复通常会将问题转移而不是消除。检查旧代码无意中处理过的输入:
- 缺失、空或 null 的值,例如客户端未设置的属性,以前会产生无害的字面量,现在意味着“无限制”;
- 值回退到的默认值;
- 更改未触及但可达的代码路径,例如调用者、其他端点、旧客户端和导出的导入端;
- 更改对其未定位的请求造成的不同行为。 将每个问题添加为新问题,并在两个问题上注明是哪个修复引起的。对净更改运行“说明文字审核”。
- 针对新代码重新评估每个未修复的问题,并再次查看代码已更改的已修复问题。
- 仅按下方“通过测试复现”允许的方式运行测试。
- 更新追踪器,如下方“保持追踪器更新”所述:
- 将
reviewed设置为新的 tip。 - 将
commits重写为新哈希。被重写的提交获取其新哈希;被删除的提交从映射中移除;新增的提交被添加。 - 更改已更改问题的
status,commit,commitRole,note,fix和detail。 - 使用
git grep -n在新 tip 处重新查找每个位置的行号。不要通过算术推算行号。 - 使用下一个空闲编号追加新问题。永远不要重新编号。
- 将
- 验证,然后重新发布到相同的 URL。
- 向用户报告: 本轮修复了什么,哪些仍然未解决,以及什么是新的,附带文件:行号和运行了哪些操作。以页面链接结束。
验证发现
在问题出现在页面上之前,你自己在被审核的提交处阅读代码。
- 端到端追踪场景。 从输入进入的地方跟随到损害发生的地方,并用
file:line命名每个步骤。如果某个发现需要的步骤代码中不存在,则将其驳回,并将该步骤作为原因。 - 检查先决条件。 询问触发状态如何产生:
- 谁可以创建输入,例如通过哪个 API,以及验证器或默认值是否会阻止它;
- 配置的默认值(例如无限期生命周期或在未提供时分配的角色)是否使场景不可达,或者使其成为正常情况;
- 现有数据是否可能包含它。当只有仓库外部的数据可以回答时,使用项目的数据检查辅助技能;如果没有此技能,询问用户如何查找。在
verified和日志中记录答案。
- 区分“预期”与“可接受”。 显示行为是有意的运行手册、测试或代码注释并不意味着它是无害的。单独检查向后兼容性:现有客户端和已部署版本、现有数据,以及从未使用新功能的供应商或用户。对现有工作流程的故意破坏是一个问题,并且除非用户接受,否则是阻塞性的。
- 说明如何验证。 将其写入
verified:“通过控制器级测试复现;服务层被桩化”、“通过阅读代码;未运行”、“数据检查:无匹配记录”。报告证据证明了什么,并说明它未证明什么。不要断言数据未显示的因果或比较性结论。 - 驳回时留下记录。 驳回设置
status: "dismissed"和包含谁决定、何时以及为什么的dismissal。当 Claude 驳回时,说明这一点,并且无人签署;页面将显示它。 - 受到质疑时重新打开。 当用户质疑驳回或结论时,从代码重新检查而不是为其辩护。如果结论错误,重新打开问题,删除驳回记录,并在
note中清楚说明先前的结论错在哪里。
通过测试复现
仅在用户要求时,或仓库和用户说明允许时(无需询问),运行构建和测试。如何构建和测试项目,使用哪种工具链和设置,来自项目的构建和测试辅助技能及其说明,而不是来自本技能。
- 绝不要使用用户的检出。 将要测试的提交放在单独的目录中:
git worktree add --detach <scratchpad>/<name>-wt <sha>;- 如果任何东西阻塞了工作树,则改为导出提交,排除阻塞的路径:
git archive <sha> -- . ':(exclude)<blocked-path>' | tar -x -C <dir>。例如,git-crypt污点过滤器在密钥不可用时会失败于加密路径。预检脚本会命名具有检出过滤器的路径。
- 按照项目说明的方式构建和运行。 工具失败(例如项目不支持的工具链)不是测试结果:按照项目的辅助技能或说明修复环境,然后重新运行。如果没有辅助技能,询问用户而不是猜测,并将学到的东西记录到项目笔记中。
- 编写测试使其断言正确的行为。 失败则会复现问题,并且同一个测试成为修复的回归测试。沿路径驱动真实类,并且仅桩化场景所需的内容。使每个桩模仿真实代码所做的,并在
verified中命名每个被桩化或未执行的层,例如 HTTP、安全链或数据库。 - 运行最窄的集合: 新测试,以及覆盖更改代码的测试。
- 将测试源码保留在追踪器中。 临时区域可以在会话之间被清除。将测试作为
tests/<Name>.<ext>发布在files中,设置contentType: "text/plain",并在问题中命名它。 - 清理。 移除工作树或导出,以及运行在用户检出中留下的任何构建输出,例如编译后的测试类(后续构建会拾取)。然后检查
git status和git worktree list显示用户的检出未更改。
辅助技能
审核流程对于每个项目都是相同的;项目所了解的内容存在于其自身的技能中。当它们存在时使用它们;本技能永远不会硬编码项目工具。
在此会话的可用技能列表中通过其描述找到它们。不要猜测名称。在步骤需要时使用 Skill 工具加载它们。
| 辅助技能 | 用途 | 缺少时的影响 |
|---|---|---|
| 审核检查清单 | 项目的风险领域:安全模型、兼容性承诺、API 契约、迁移 | 审核依赖一般知识;说明可能遗漏的领域 |
| 构建和测试 | 隔离构建和测试一个提交:命令、工具链、设置、已知阻塞项 | 测试仅在询问用户如何运行后运行;发现保持“来自阅读代码” |
| 数据检查 | 安全地回答来自仓库外部的数据问题 | 用户被询问如何查找 |
| 说明文字规则 | 注释、文档字符串、变更日志、提交消息和 PR 文本,例如生成... |