拿到 KAT-Coder-Pro V2.5 之后直接丢一句「重构这个项目」,结果改动散乱、漏文件、顺手改了无关模块,通常不是模型能力问题,而是输入里没有仓库索引和任务边界。多文件重构和改两三个文件的小修不同:模型需要知道哪些文件属于本次范围、它们之间怎么调用、改完用什么命令验收。把这三件事先写清楚,再让模型出 diff,后面核对和回退都会轻松。
多文件重构能不能交给 KAT-Coder-Pro V2.5,取决于输入里有没有文件范围、依赖索引和可执行的验收命令。建议按「圈文件 → 拆单步任务 → 附带索引提交 → 逐条核对 diff → 跑测试或静态检查」推进。如果连目标文件清单或验收方式都拿不出来,更适合先退回单文件修改,避免一次生成一大片无法核对的改动。
在代码仓库里圈出本次重构涉及的文件范围
先决定哪些文件进入任务,而不是把整个仓库当上下文。整个仓库塞进去,模型容易在无关目录里做「顺手优化」,真正的目标文件反而被稀释。可以先在本地把范围收敛成一个明确的文件列表,再交给模型。
常用的筛选方式有三种,通常组合使用:按目录树限定模块,按后缀限定语言类型,按模块名或符号名限定业务对象。下面的命令只是骨架,路径需要结合你的仓库实际结构调整。
# 先看两层目录结构,不要一上来递归到底
find src -maxdepth 2 -type d
# 按后缀筛出候选文件
git ls-files | grep -E '^app/order/.*\.(py|pyi)$'
# 按模块名或业务词筛
git ls-files | grep -E '\.(ts|tsx)$' | grep -i billing
# 把结果落盘,作为本次任务边界
wc -l refactor-files.txt
把筛选结果存成 refactor-files.txt 这类清单,它同时是给模型的输入和后面核对 diff 的对照表。如果清单超过几十个文件,建议先按子模块再切一刀,一次只重构一层调用关系内的文件。
把重构目标拆成可验证的小任务
多文件重构最容易失控的地方,是一句「统一时间处理」被模型理解成十几个方向的改动。更稳的做法是让每一步只处理一个明确改动,并且这一步自带验收方式。任务描述可以按下面的模板写,字段名可以替换,但输入、期望改动、不改动、验收四块建议都保留。
【单步任务】
目标:把 app/order 下的时间处理统一为带时区的 datetime
输入文件:
- app/order/service.py
- app/order/model.py
期望改动:
- 只替换裸 datetime.now() 的调用
- 保持所有函数签名不变
不要改动:
- 其他模块、测试文件、公开接口、依赖声明
验收命令:
- python -m pytest tests/order -q
输出要求:
- 只输出 unified diff,且不触及清单外文件
「不要改动」这一栏经常被忽略,但它决定了后面 diff 好不好核对。凡是本轮不打算动的公共接口、配置文件和测试,都值得显式列进去。如果某个子任务牵涉的文件超过当前清单,先停下来讨论要不要拆成两步,而不是让模型一次做完。
把仓库索引和任务描述一起交给 KAT-Coder-Pro V2.5
上下文不是文件越多越好,而是让模型看懂目标文件处在调用链的哪个位置。建议把内容分成几段,用明显的标记隔开,模型更容易分清哪些是指南、哪些是要改的代码。下面是不依赖任何官方接口参数的通用骨架,可以按自己的接入方式改写。
[REPO_INDEX]
语言与框架:Python 3.11 + Django
已裁剪目录:app/order、app/common
目标文件:
- app/order/service.py
- app/order/model.py
[DEPENDENCY]
调用链:views.py -> service.py -> model.py
只读依赖:app/common/clock.py(允许引用,禁止修改)
相关测试:tests/order
[TASK]
(把上一步的单步任务整段粘进来)
[CONSTRAINTS]
不改公开函数签名;不改测试;不新增第三方依赖
[OUTPUT]
只返回 unified diff,并附上改动文件清单
调用链和只读依赖这两块尤其值得写,它们能让模型判断哪些文件必须改、哪些只能引用。如果拿不准某项依赖是否受影响,可以先只提交目标文件加一层直接调用方,跑通再扩大范围。
逐条检查模型返回的 diff 是否越界
模型返回 diff 后不要直接落盘,先当作一次代码评审来读。核对的重点是范围,而不是风格。下面几条检查项按顺序过一遍,通常几分钟就能判断是否越界。
- 文件数量:diff 里的文件是否等于任务清单里的文件,多出来的要逐一看原因。
- 函数签名:公开函数的参数、返回值、异常类型有没有被动过,动了就属于接口变更,应该单独处理。
- 导入语句:有没有新增未授权的第三方依赖,或者把只读模块的调用方向改反。
- 测试与配置:有没有顺手改测试、改配置文件、删文件或重命名文件。
# 先看改动概要,再逐个文件细看
git diff `--stat`
git diff `--name-only` | wc -l
git diff -- app/order/service.py
# 确认越界后,只回退越界的文件
git checkout -- path/to/overreached_file.py
如果越界文件数量偏多,说明任务边界本身没写清楚,此时单靠回退解决不了问题,应该回到第二步把单步任务再拆细。回退是为了保住当前进度,不是修复边界的手段。
在测试或静态检查里验证重构结果
diff 范围正确只说明改动没跑偏,行为是否保持还需要靠可运行的检查。优先跑与目标模块直接相关的测试,再跑静态检查,两类命令都需要按你的仓库实际脚本替换。
# 单元测试(按语言和框架替换)
python -m pytest tests/order -q
npm test -- `--runInBand`
go test ./app/order/...
cargo test -p order
# 静态检查与类型检查
python -m mypy app/order
ruff check app/order
npx eslint src/order
go vet ./app/order/...
cargo clippy -p order
如果目标模块缺少测试,可以先补最小范围的回归测试再重构,也可以退一步只跑静态检查和类型检查,同时人工确认关键调用路径。当测试长时间跑不过、越界改动反复出现,或者任务清单已经难以维护时,更适合缩小范围,甚至退回单文件修改,把多文件重构留给边界更清晰的那一步。