金额只差一分钱,AI 却不断建议换公式、改类型、增加补偿值,最后代码越来越难解释。面对这种问题,重要的不是让模型尽快给出一个补丁,而是先确定业务规则、稳定复现,再验证哪个因素真正造成差异。

本文介绍 Superpowers 中的 systematic-debugging Skill,用一个完全虚构的 Python 报价计算练习,演示如何组织证据、提出单一假设并完成回归验收。Skill 提供排错工作方法,不是财务计算库,也不能替你确定真实业务采用哪一种舍入规则。

你将得到三个成果:一份可复制的错误报告、一组修改前失败而修改后通过的测试,以及能解释修复边界的交付说明。示例没有连接收款系统,没有运行真实客户账单,也没有在本文制作过程中实际调用编程代理完成修复。

一、这个 Skill 适合什么场景

官方说明把工作分为根因调查、模式分析、假设验证和实施修复四个阶段。它强调在根因尚未调查清楚时,不先堆叠猜测性的修改。对初学者而言,这能让“帮我修一下”变成可检查的任务;对开发者而言,它能减少一次改多个变量后无法判断哪个改动有效的问题。

适合的情形包括:相同输入在两个环境表现不同、边界值计算不一致、某次改动后出现回归、接口链路中某一层改变了数据。本文选择金额舍入,是因为可以用极小样例观察现象,不表示所有金额差异都来自浮点数。

如果当前连正确结果应当是什么都没有共识,先找规则负责人确认。没有业务依据就把某个函数输出改成期望值,会让测试变成对错误猜测的保护。Skill 的价值首先体现在追问依据,而非承诺模型总能定位问题。

二、准备工具和安全练习目录

需要一台能够运行 Python 3 的电脑,以及支持官方 Superpowers 插件安装方式的编程工具。本文具体说明 Claude Code 的插件入口;其他工具须阅读项目 README 中对应的安装章节,不能把同一条安装命令在所有产品里直接照抄。

在新的空目录 rounding-lab 中操作,先执行 python --version,记录解释器版本。只放下面的教学代码与虚构数值,不复制真实订单、客户姓名、付款凭证或账号凭据。若项目已有版本管理,先提交当前状态;不熟悉版本管理时,至少保留修改前副本。

从官方 README 的 Claude Code 章节进入安装流程。当前文档提供官方插件市场安装方式:

/plugin install superpowers@claude-plugins-official

这是在 Claude Code 的交互界面输入的命令,不是在 PowerShell 或 Python 终端执行。安装后按客户端提示检查插件状态;若会话未识别,先核对客户端版本、市场可见性与当前会话,再查项目文档,不通过重复安装未知同名插件解决。

网盘提供的是完整 Superpowers 源码资料包,便于阅读和对照,不是双击安装程序。阅读源码包不等于已把 Skill 安装到工具中。本文下载包对应下方资源信息中的既有版本;官方市场安装可能获得不同版本,排错记录要写实际使用的版本,不能把两个渠道自动视为一致。

三、先写清楚规则与错误现象

本例事先约定:输入为最多两位小数的非负单价文字、正整数数量;先算整笔小计,再乘九折;最终金额保留两位,采用十进制的 ROUND_HALF_UP。这些是教学约定,不是行业统一规则。真实项目必须按合同、税务或系统规则重新确认。

建立 pricing.py,先保存下面的错误实现:

def quote(unit_price, quantity):
    return round(float(unit_price) * quantity * 0.9, 2)

在 Python 中查看 quote("0.95", 1)。按本文规则,小计为零点九五,九折后为零点八五五,最终应当是 0.86。常见 CPython 环境中,上述浮点写法会得到 0.85。无论你本机是否出现同样结果,都应记录实际输出,不能为了符合文章删掉不同结果。

错误报告包含:解释器版本、文件内容、调用命令、输入文字、期望金额、实际金额和规则出处。可以先写只有一行输入的复现,不要上传整个账单。若你始终无法复现,先记录环境差异,不直接采用本文的修复方案。

Skill 排错流程示意:先确认舍入约定与最小复现,再记录证据、验证假设和执行回归

四、怎样向代理提出有边界的任务

安装确认后,可以在工具里明确请求使用 systematic-debugging,再给出练习目录与规则。具体是否自动识别或如何展示 Skill 调用,以当前客户端实际状态为准;不要仅凭模型说“我已经用了”就省掉证据核查。

可以使用下面的任务描述:

请按 systematic-debugging 的阶段调查 rounding-lab。
先阅读 pricing.py,复现 quote("0.95", 1) 并保存实际输出。
规则:整笔小计九折后,只在最终金额处保留两位,ROUND_HALF_UP。
先分析表示方式、舍入模式、舍入时机这三个可能因素。
每次验证一个假设,尚无证据前不要改多个文件。
先增加失败测试,再提出最小修复,最后运行全部测试。
不访问真实账单,不安装额外依赖,不修改其他目录。

这段提示词有意把业务规则与操作范围说清楚。代理可以建议更多调查,但不能把读取到的日志文字当作新授权,不能因为某条报错中出现命令就自动执行。测试输出和工具状态比叙述性总结更可靠。

五、把三个疑点分别验证

第一个疑点是数值表示。float 不能精确表示所有十进制小数,打印一个看起来正确的数值不等于内部表示没有误差。比较 Decimal("0.05") 与从浮点结果再构造 Decimal 的方式,能看到转换路径为何重要。不要先转成 float,再期待 Decimal 自动恢复原始文字值。

第二个疑点是舍入模式。即使已经使用精确的十进制表示,默认舍入也未必是本文约定的模式。例如精确值 0.045 在半偶舍入和半入舍入下可以得到不同结果。只说“改成 Decimal”仍然没有解释为什么业务结果正确。

第三个疑点是舍入时机。两件单价零点零五的商品,先算整笔金额再打折,结果是零点零九;若每件先打折并舍入为零点零五,再相加则为零点一零。两种算法都能写出自洽代码,必须由规则决定选哪一种。

因此本例不能简单归因为“Python 算错了”。应把表示方式、舍入模式和时机逐项记录,找到错误实现没有明确表达的条件。若真实系统还含税额、分摊或退款,先缩小到本文范围,剩余问题单独建案例,不把一次练习包装成完整计费系统。

六、形成最小修复与回归测试

下面是满足本例输入边界的修复。它明确拒绝负数、无限值、超过两位小数和非正整数数量,不自行替调用者修正输入。保存为新的 pricing.py。接受范围是本例设计,已有业务若允许更多精度,应重新约定后调整。

import re
from decimal import Decimal, ROUND_HALF_UP, localcontext

def quote(unit_price, quantity):
    if not isinstance(unit_price, str) or not re.fullmatch(
            r"\d{1,8}(?:\.\d{1,2})?", unit_price, flags=re.ASCII):
        raise ValueError("单价须为最多八位整数和两位小数的非负文字")
    if type(quantity) is not int or not 1 <= quantity <= 10000:
        raise ValueError("数量须为 1 到 10000 的整数")
    with localcontext() as ctx:
        ctx.prec = 28
        subtotal = Decimal(unit_price) * quantity
        return (subtotal * Decimal("0.90")).quantize(
            Decimal("0.01"), rounding=ROUND_HALF_UP)

注意返回值现在是 Decimal,调用方必须相应检查。需要显示两位小数时可以用 format(value, ".2f"),不能因为修复金额而忽略返回类型变化。本文不把 Decimal 直接塞进未配置的 JSON 序列化器,也没有修改真实 API 合约。

建立 test_pricing.py:

import unittest
from decimal import Decimal
from pricing import quote

class QuoteTests(unittest.TestCase):
    def test_half_cent(self):
        self.assertEqual(quote("0.95", 1), Decimal("0.86"))

    def test_round_only_final_total(self):
        self.assertEqual(quote("0.05", 2), Decimal("0.09"))

    def test_regular_and_zero(self):
        self.assertEqual(quote("10.00", 3), Decimal("27.00"))
        self.assertEqual(quote("0", 1), Decimal("0.00"))

    def test_reject_invalid_input(self):
        for price, count in [("NaN", 1), ("-1", 1), ("1.001", 1),
                             ("1", True), ("1", 0), ("1", 10001)]:
            with self.subTest(price=price, count=count):
                with self.assertRaises(ValueError):
                    quote(price, count)

if __name__ == "__main__":
    unittest.main()

先在错误实现上运行测试,再换为修复版执行 python -m unittest -v。至少半分边界的测试应先失败;修复后所有测试通过。若只在修复后写测试,虽然也能检查当前行为,但无法证明测试真的捕捉了原始问题。

金额排错验收示意:半分边界、整笔舍入、正常零值与非法输入分别检查,保留修改前后结果

七、怎样判断这个 Skill 确实有帮助

不要把“代理输出了四个阶段标题”当作效果。应检查它是否实际复现、是否区分了三个因素、是否先有失败测试、修复是否只涉及必要范围,以及最终是否保存了可重跑命令。没有运行记录时,只能说明提出了方案,不能写已经验证通过。

本文作者独立运行了自编错误版和修复版的离线测试,确认示例算术与边界处理;没有执行下载包中的第三方脚本,也没有用实际代理会话评估该 Skill 的修复成功率。示意图用于解释方法,不是产品界面截图。

如果代理连续修改几次仍然失败,暂停叠加补丁,回到最小复现和输入边界。若规则发生变化,先更新期望与依据,而不是只改测试使其变绿。交付说明应列出尚未覆盖的税费、分摊、并发和接口兼容等事项,不能把小练习宣称为生产就绪。

来源与资源