Sonnet 5.5 重构提示词:用 CLAUDE.md 管住多文件改动
提供完整 CLAUDE.md、任务提示词和可下载练习,把 Python 工单报表拆成三个模块,核对原有行为、测试和修改范围。
让 Sonnet 5.5 重构代码,提示词需要说清三件事:允许改哪些文件、哪些行为必须保留、交付时拿什么证明。只说“把代码整理一下”,模型就可能顺手改接口、依赖或测试。稳定的项目约定放进 CLAUDE.md,本次拆分目标写进任务提示词,最后分别检查实现、测试和改动范围。
本文用一个 Python 工单工时报表练习,把解析、汇总和命令行协调拆开。下载完整练习包,内含初始项目、十项契约测试、提示词、范围检查脚本和参考实现。离线练习需要 Python 3.10 以上及 Git,不依赖第三方包或 API Key。
练习与参考实现由 Ofox 编写,已于 2026 年 10 月 8 日完成本地测试,没有调用 Sonnet 生成参考答案。测试通过说明这份实现满足所列检查,不代表模型成功率或速度。实际体验提示词时,请使用已获授权的 Claude Code 账号,另外保存自己的运行结果。
先写清不能改变的行为
初始 ticket_report/report.py 读取 CSV,校验工单编号和工时,按团队汇总后输出 JSON。表头固定为 id,team,hours。工时使用 Decimal 运算,避免把 0.1 加 0.2 变成浮点近似值;JSON 中的数值仍是字符串,保留小数格式。
python3 -m ticket_report fixtures/tickets.csv
随包样例的预期输出:
{"Billing": "1.50", "Support": "0.75"}
验收不能只看这行结果。旧调用方仍须能从 ticket_report.report 导入 parse_rows 和 summarize;团队按名称排序;错误行不能被悄悄丢掉;文件不存在或命令参数不正确时退出码为 2,错误写入 stderr,stdout 不输出成功结果。
| 职责 | 原位置 | 拆分后的要求 |
|---|---|---|
| CSV 解析和逐行检查 | report.py | 移到 parsing.py |
| Decimal 汇总与排序 | report.py | 移到 aggregation.py |
| 参数、文件、JSON、退出码 | report.py | 留在原文件 |
| 原有函数导入路径 | report.py | 通过重新导出保留 |
| 测试、样例和入口文件 | 独立文件 | 不修改 |
本例只练习保留行为的拆分,不是生产工单系统。它没有穷尽任意 CSV 的校验、恶意上传防护和大文件性能。发现这些不足时应记录下来,另开任务处理,不能借重构偷偷改变输入规则。
建立可比较的基线
解压后进入 starter,让同级的 reference 留在工作仓库之外,避免把参考答案误认成原项目代码。先提交基线,再运行测试:
cd sonnet-refactor-kit/starter
git init
git add .
git commit -m "Baseline ticket report exercise"
python3 -m unittest discover -s tests -v
python3 -m ticket_report fixtures/tickets.csv
应看到十项测试通过。若 Git 要求设置身份,按自己的项目规范配置,不要照抄别人的身份。初始测试失败时先排查解压和环境;没有正常基线,就无法判断后面的失败是不是模型引入的。
测试覆盖小数精度、空表、空白与 Unicode、重复编号、非法工时、表头顺序、空团队及三种命令行结果。非法工时还包含负数、非有限值、空值和非数字文本。真实项目也应记录起始 commit 和已有改动,使用独立分支或 worktree;不要为了“清理环境”一把重置其他人的工作。
CLAUDE.md 写长期规则
Claude Code 官方记忆文档说明,CLAUDE.md 属于指令上下文,并非强制配置。写下“不改测试”有用,但不能代替权限控制和代码复核。在会话中用 /context 检查预期文件是否载入,再依赖其中的约定。

2026 年 10 月 8 日截取的英文官方文档,展示规则来源,不代表模型任务运行成功。
练习包的完整文件如下,复制到自己的项目时先替换命令和路径:
# Ticket report exercise
Run commands from this directory. Python 3.10+; standard library only.
Run `python3 -m unittest discover -s tests -v` before and after changes.
Run `python3 -m ticket_report fixtures/tickets.csv` for the CLI contract.
Preserve the public imports `ticket_report.report.parse_rows` and `summarize`.
Keep Decimal arithmetic, JSON strings, sorted keys, error messages and exit codes.
Only edit report.py or add parsing.py and aggregation.py inside ticket_report/.
Do not change tests/, fixtures/, __main__.py, dependencies or this file.
No network, deployment, commits or unrelated cleanup are part of the task.
If a requirement conflicts with existing behavior, report it before changing behavior.
In the final response list files changed, commands and actual results, and limitations.
These instructions are task context, not a filesystem security boundary.
测试命令必须真实存在。临时验收条件放进当次任务,不要把每轮需求永久堆进项目文件;子目录规则与根目录冲突时,也应先消除矛盾。否则写得再长,模型仍面对互相打架的要求。
一次给出完整的重构任务
先在客户端核实模型和接入渠道,具体见 Sonnet 5.5 的 Claude Code 设置教程。模型是否可用、别名映射到谁,与提示词好坏是两件事;回答中自称 Sonnet 不能证明实际服务模型。
打开 starter 后使用以下提示词。这里保留英文版本,方便直接对应包内文件和测试;中文版解释与验收标准不变。
Refactor ticket_report/report.py without changing behavior.
First read CLAUDE.md and tests/test_contract.py, run the existing tests,
and explain the current contract.
Extract parse_rows to ticket_report/parsing.py and summarize to
ticket_report/aggregation.py.
Keep report.py as the CLI coordinator and re-export both public functions.
Allowed changes: ticket_report/report.py, ticket_report/parsing.py,
and ticket_report/aggregation.py only.
Do not update tests or fixtures to accommodate your changes.
Do not add dependencies or deploy.
After editing run the full test suite and CLI example; inspect the final diff.
Report actual test output, the file list, and remaining limitations.
If blocked, report the exact blocker.
关键是既给目标结构,也给外部可观察行为。“重新导出”不能省略:函数搬家以后,旧导入路径仍要能用。保留命令行协调逻辑,则避免为了拆文件顺手改掉 python -m ticket_report 的入口。
Anthropic 的 Sonnet 5.5 提示指南指出,effort 会影响自主工作与验证行为,也建议明确任务范围。不要把更高档位当成测试替代品。effort 档位说明可辅助选择,但不改变本例验收条件。模型提出额外清理时先记入后续事项,避免让一次小改动变得难以归因。
测试通过与范围正确分开验收
会话结束后自己运行命令,不只接受“全部通过”的口头结论:
python3 -m unittest discover -s tests -v
python3 -m ticket_report fixtures/tickets.csv
python3 ../scope_check.py
git diff --check
git diff HEAD
范围脚本同时读取相对 HEAD 的已跟踪改动和未忽略的新文件。后者很重要:新拆出来的两个模块尚未进入 Git,普通差异视图可能漏掉它们。允许列表仅含 ticket_report 下的 report.py、parsing.py 和 aggregation.py,预期没有范围外文件。
范围正确不等于实现正确,允许文件里写坏代码仍能通过路径检查;测试通过也不能掩盖样例被改小、配置被修改的问题。因此既要读 diff,也要打开新增文件。本文参考实现只搬走两个函数,在原模块重新导入,保持 CLI 协调逻辑;初始版与参考版均通过同样的十项测试,样例输出与前文一致。你的模型运行需另行验收。
失败时缩小修复,而不是放宽要求
| 现象 | 先检查 | 处理方式 |
|---|---|---|
| 拆分后导入失败 | 旧公开路径 | 补回重新导出,不改调用方 |
| 出现浮点尾数或数值类型变了 | 运算和序列化 | 恢复 Decimal 和字符串输出 |
| 改了测试才通过 | 验收条件漂移 | 恢复原测试,修实现 |
| 总数正确但退出码不同 | 命令行协调层 | 同时核对 stderr、stdout、状态码 |
| 差异中看不到新模块 | 未跟踪文件 | 打开检查并运行范围脚本 |
| 客户端选不到模型 | 账号和渠道 | 先解决权限,不当作编程能力失败 |
修复提示可以直接给真实失败,例如:
The original test test_cli_missing_file now fails: expected exit code 2.
Keep the original tests unchanged. Inspect only the allowed files and
restore the prior CLI error behavior. Run all ten tests, the CLI fixture,
and the scope checker again. Report the actual output.
上面是修复模板,不是本次发生过的模型故障。使用时替换为你实际看到的测试名和输出。出现越界修改,逐项辨认并撤回本次不需要的改动,不要用整仓重置抹掉他人工作。
最终把模型来源、完整提示、基线 commit、补丁、测试输出和修复轮次一起保存。若继续比较 Sonnet 与 Opus 的编程表现,两者应从同一基线出发、接受同一验收标准。一个小练习成功,只能说明那次运行的结果,不能推广成模型全面胜出。
这套方法也适合把数据库访问或格式化函数拆出原模块,但先要补足对应契约:数据库任务还需处理事务边界,异步任务要保留异常与取消行为。不要直接把本例的十项检查当成任何项目都够用的清单。先找真正依赖旧行为的调用方,再决定需要哪些回归样例。
交付时确认旧导入仍有效、原十项测试通过、CLI 输出一致、仅三个许可路径变化,最后人工检查模块职责是否清楚。未覆盖的条件如实列出,这样后续接手者知道哪些结果已验证、哪些仍需验证。
常见问题
- CLAUDE.md 能强制禁止 Sonnet 修改其他文件吗?
- 不能。它提供指令上下文,不是访问控制。需要时使用权限限制和隔离工作区,并检查实际差异。
- 参考答案是 Sonnet 5.5 生成的吗?
- 不是。练习和参考实现由 Ofox 编写并在本地测试;提示词供读者在已获授权的 Claude Code 会话中使用,不代表模型实测结果。
- 重构时哪些行为不能变?
- 本例保留公开导入路径、输出类型和顺序、数值运算、错误信息与退出码。新增功能或调整校验应另开任务。


