gsd-2 重构专家 Agent(refactorer)完整指南:行为保持的代码转换规范
gsd-2 重构专家 Agent(refactorer)完整指南:行为保持的代码转换规范
本篇技术指南深入解析 gsd-2 仓库中内置的重构专家子代理 refactorer 的完整规范。该 Agent 专职执行安全、行为保持(behavior-preserving)的代码转换——抽取、内联、重命名、简化、移动与分解,同时严格禁止混入功能变更或缺陷修复。读完本文,你将掌握如何在多 Agent 编排中正确调用该角色、理解其五步处理流程与五条安全红线,并学会使用其标准化的 Transformation / Changes / Verification 输出格式来保证每次重构可审、可测、可回溯。
refactorer 是什么:从文档定位到项目应用场景
在 gsd-2 的 Agent 体系中,refactorer 被定义为一个重构专家(refactoring specialist)。其职责边界非常清晰:只做"安全、行为保持的代码变换",任何功能变更(feature changes)与缺陷修复(bug fixes)都不得混入重构过程。
从仓库文件结构看,src/resources/agents/ 目录下与 refactorer 并列的还有 debugger.md、doc-writer.md、git-ops.md、javascript-pro.md、planner.md、researcher.md、reviewer.md、scout.md、security.md、tester.md、typescript-pro.md、worker.md 等专业角色,共同构成一个分工明确的多 Agent 工作台。其中 refactorer 属于"实现层"专职代理——在 refine-slice.md 的规划提示中明确写着:规划单元不应派发 worker、refactorer、tester 这类实现层 Agent,实现工作属于 execute-task 阶段;而 write-gate-planning-unit.test.ts 的测试则验证了在需要精化切片时,规划单元允许的派发名单中确实包含 refactorer。这说明该角色的典型应用场景是:切片任务已明确、代码结构需要优化时,作为隔离上下文的专职执行者被调度。
Agent 文件结构:Frontmatter 是发现与路由的关键
refactorer.md 以标准 Frontmatter 开头,这是 gsd-2 加载与路由 Agent 的核心元数据:
---
name: refactorer
description: Safe code transformations — extract, inline, rename, simplify
model: sonnet
---
三个字段各司其职:
name:Agent 的调用标识。在多 Agent 调度中,通过subagent工具的agent参数按名称路由(见下文)。description:发现信号。它描述了该 Agent 的能力边界——安全代码转换:抽取(extract)、内联(inline)、重命名(rename)、简化(simplify)。主代理正是依据这段描述判断何时该把这个任务交给refactorer而非其他角色。model:默认模型偏好。本文件指定为sonnet。注意这只是默认值,可以在调用时被覆盖——subagent 扩展 的参数说明明确:model字段是"子代理的模型覆盖(例如 'claude-sonnet-4-6'),优先于 Agent frontmatter 中的 model"。
在加载机制上,仓库的 component-loader.ts 提供了 loadComponentFromAgentFile 函数,专门从"扁平的 legacy agent .md 文件"读取组件;同文件第 301 行给出诊断信息 "agent file missing name or description in frontmatter",即 name 与 description 是 Frontmatter 中的必填字段。配套测试 component-loader.test.ts 覆盖了 legacy Agent 格式的解析。此外,prompt-tool-names.test.ts 还约束 Agent Frontmatter 中不得引用已被替换的工具名(如 web_search),说明 Frontmatter 同样会被静态校验。
在调用侧,/subagent 命令(subagent/index.ts)会扫描 ~/.gsd/agent/agents/ 与 .gsd/agents/ 下的 .md 文件并列出可用 Agent,格式为 name [source] (model): description——这再次印证 Frontmatter 的三个字段直接决定了 Agent 的可见性与可调度性。
五步重构流程:从读懂到验证
refactorer.md 规定的核心工作流是一个严格顺序的五步过程,任何一步缺失都会削弱重构的安全性:
- Read — 阅读代码,理解当前行为。重构的前提是准确掌握"现在的行为是什么",这是后续判断"行为是否保持"的基准线。
- Identify — 确定要应用的具体转换。一次任务聚焦一种转换(或一组紧密相关的转换),而不是"顺便改改风格"。
- Check — 检查所有会受到影响的调用点(call sites)、导入(imports)与引用(references)。这一步是行为保持的关键:遗漏一个调用点,就意味着行为的隐性漂移。
- Transform — 以小步、可验证的粒度执行转换。小步意味着每次改动都能独立定位问题、独立回滚。
- Verify — 运行现有测试,确认无行为变化。验证不是可选项,而是流程的终点。
从工程语义看,这套流程本质上是"测试先行"思想的变体:先确立基准行为(第 1、2 步),再枚举影响面(第 3 步),最后用测试结果证明等价(第 5 步)。在 gsd-2 中,这与 tester 角色的分工天然衔接——如果受影响代码没有测试,refactorer 的安全规则要求显式标记出来,而不是盲目重构。
六类受支持的转换:能力边界
refactorer 明确支持六种转换类型,每种的约束也一并说明:
| 转换 | 含义 | 关键约束 |
|---|---|---|
| Extract(抽取) | 将代码抽入新的函数、类、模块或变量 | 保持抽取前后语义一致 |
| Inline(内联) | 当抽象不再带来价值时,用函数/变量的函数体替换其引用 | 仅当抽象"无增值"时使用 |
| Rename(重命名) | 为提高清晰度修改名称 | 必须更新所有引用 |
| Simplify(简化) | 降低复杂度:压平嵌套、删除死代码、简化条件表达式 | 不得改变控制流语义 |
| Move(移动) | 将代码迁至更合适的模块 | 必须更新所有导入 |
| Decompose(分解) | 将大函数/大类拆分为更小、更聚焦的单元 | 保持对外行为不变 |
这份清单界定了该 Agent 的能力上限:它只管结构层面的变换,不管行为层面的增减。换言之,"为什么这样写更好"是它的思考范畴,"新增什么功能、修复什么 bug"则严格排除在外。
五条安全规则:重构的红线
文档中的 Safety Rules 是 refactorer 的行为底线,逐条展开如下:
- 转换前后都要运行测试 — 不仅转换完成后要跑,开始之前也要跑。转换前的测试结果作为行为基准;转换后的结果与基准比对,才能确认"无行为变化"。
- 绝不将重构与行为变更混在一起 — 重构与功能新增、缺陷修复必须分属不同提交/不同任务。混在一起会让回归定位变得不可能。
- 声明完成前,用 grep 检查所有旧名称 — 重命名类转换的最大风险是"漏网引用"。文档明确要求在宣布完成前,对旧名称做全仓检索,确保所有调用点、导入与文档引用都已更新。这与第 3 步流程(Check all call sites)前后呼应。
- 除非被明确指示,否则保留公共 API 签名 — 公共 API 是外部契约,擅自改动签名会让调用方静默失效。签名变更必须由主代理显式授权。
- 受影响代码没有测试时,标记出来——不要盲目重构 — 这是安全规则的收口:无测试覆盖的代码重构等于"在黑暗中飞行"。正确动作是标记风险并上报,而非继续。
这五条规则与仓库对安全性的整体重视一脉相承:gsd-2 的编排层对 Agent 行为的约束通过策略测试来固化,例如 write-gate-planning-unit.test.ts 对 shouldBlockPlanningUnit 的断言、prompt-tool-names.test.ts 对 Frontmatter 工具名的静态检查——都是把"行为契约"变成可执行校验的实例。
标准输出格式:让重构可审、可回溯
refactorer.md 要求所有任务以三个固定小节收尾,这一格式化输出让主代理与后续 reviewer 能快速审计:
## Transformation
What was refactored and why.
## Changes
1. `path/to/file.ts` — what changed
2. `path/to/other.ts` — updated call sites
## Verification
Test results before and after — confirming identical behavior.
三个小节各回答一个问题:
- Transformation:改了什么、为什么改——说明重构动机与所选转换类型(对应流程第 2 步)。
- Changes:逐文件列出改动,包括"某文件改了什么"与"某文件更新了调用点"。
path/to/file.ts这类占位符在实际输出中必须替换为真实路径,并且所有受影响文件都要列出——这正是第 3 步"检查所有调用点"的落地产物。 - Verification:转换前后测试结果对比,作为"行为保持"的硬证据(对应流程第 5 步)。
这套输出格式与同目录 worker.md(## Completed / ## Files Changed / ## Notes)及 tester.md(## Coverage Analysis / ## Tests Written / ## Test Results)的风格一致,说明 gsd-2 的 Agent 家族统一采用"分节化、可机读"的汇报契约,方便主代理汇总与后续角色接手。
在 gsd-2 中如何调用 refactorer
在 gsd-2 的实际工作流中,refactorer 通过 subagent 工具被调度。参考 subagent 扩展 的参数契约,一次典型的单任务派发大致如下:
subagent(agent: "refactorer", task: "对 src/parser.ts 的 parseToken 做抽取转换,保持行为不变,完成后输出 Transformation / Changes / Verification")
派发时可用的关键参数包括:
agent:目标 Agent 名称,如refactorer;task:委托的具体任务(单任务模式);tasks/chain:并行或顺序的多任务批量派发;model:模型覆盖,优先于 Agent Frontmatter 中的model: sonnet;isolated:在隔离文件系统(git worktree)中运行子代理,变更以补丁形式捕获并合并回主工作区(需在配置中启用taskIsolation.mode);background:后台启动并把状态持久化到 run 记录中。
值得注意的是,refactorer 的调度并非随心所欲:规划单元(planning unit)层会通过策略检查拦截不合适的派发——write-gate-planning-unit.test.ts 中展示了 shouldBlockPlanningUnit 配合 allowedSubagents: <a href="https://link.gitcode.com/i/40c54a726db79604617d664716070387" target="_blank">'refactorer'] 的授权逻辑,而在 [refine-slice.md 的提示模板中,实现层 Agent(worker、refactorer、tester)被明确排除在"规划"阶段之外,只能在执行阶段被调用。这意味着正确姿势是:规划阶段不要调用 refactorer,执行阶段按需调度。
实战自检清单
将文档规范与仓库实现结合,一次合格的 refactorer 任务应当满足以下全部条件:
- [ ] 已读懂现状代码,能口头复述其当前行为
- [ ] 明确选择了六类转换中的一种(或一组紧密相关者),并确认不属于功能变更/缺陷修复
- [ ] 已用 grep 枚举全部调用点、导入与引用,且重命名后再次 grep 旧名称确认无残留
- [ ] 未触碰公共 API 签名(除非主代理显式要求)
- [ ] 转换前已运行测试并记录基线结果
- [ ] 受影响代码若无测试,已显式标记并上报,而非盲目重构
- [ ] 输出遵循
Transformation / Changes / Verification三段式格式,Verification 给出前后测试对比
参考文件:refactorer Agent 定义、Agent 文件加载器、subagent 派发工具、Agent 加载测试、规划单元派发策略测试、refine-slice 规划提示。