mcpField
P
pasteurize

pasteurize

github.com/paulnsorensen开发19652 次安装6 天前更新
代码仓库

关于 pasteurize

pasteurize 是用于排查难复现软件故障的结构化调试技能。它要求先建立并验证复现循环,再提出排序假设,并指导埋点、回归测试、修复与清理。

主要功能

  1. 01建立可重复的故障复现循环
  2. 02多次运行确认预期故障
  3. 03排列可测试的假设
  4. 04指导定向埋点与修复
  5. 05扫描临时调试标记

适用场景

  1. 01排查不稳定或时序敏感的故障
  2. 02修改生产代码前追查回归问题
  3. 03通过回归测试和原复现循环验证修复

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/paulnsorensen/easy-cheese --skill pasteurize

安装后在 Claude Code 中输入/pasteurize确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

wedge.toml
references/
commands.md
feedback-loops.md

详细介绍

/pasteurize

遇到棘手的 Bug 时,使用此流程。

纪律

**规则:**先建立可靠的反馈闭环,再提出假设。

遇到以下任何警示信号时,都要停下:

  • 在闭环还不能复现故障之前就指出原因。
  • 把无关故障当作复现结果。
  • 因为真实接缝难以处理,就在模拟接缝处添加测试。
  • 针对同一组假设尝试修复第四次。
  • 没有进行会话标签全面检查,就报告工作树干净。
自我辩解回应
“原因很明显。”先建立闭环。明显的原因跑一次就能确认。
“编写闭环太慢了。”即使闭环很慢,也比错误修复强。
“任何故障都能证明 Bug 存在。”确认退出代码或输出是否符合预期。
“模拟接缝已经足够接近。”记录缺失的接缝,并转交给 Mold。
“再试一次就能成功。”先写一份新的假设列表。

探索代码时,遵循 code-intelligence-routing.md。 使用 artifact-path specs 解析规格存储位置。 阅读解析出的目录中有关失败接缝的备注。

阅读 harness-portability.md,了解如何使用可移植工具。 优先使用随附的辅助工具或仓库内的辅助工具,而不是 ${CLAUDE_SKILL_DIR}。 将 ${CLAUDE_SKILL_DIR} 视为可选的宿主回退路径。 将交接区块作为可移植契约。 请记住,斜杠命令是宿主环境的呈现形式,而非控制模型。

输入

<input> 是报告的症状。 接受 Bug 报告、堆栈跟踪、失败测试输出或制品路径。 接受来自 Affinage、Cheese 或 Cook 的调查请求。

调查请求使用以下字段:

字段类型必填含义
sourcestring是发起请求的 skill,例如 affinage。
source_refstring否拉取请求评论或发现项标识符。
symptomstring是用一句话描述报告的故障。
expect_exitinteger否表示故障的退出代码。
expect_outputstring否故障输出的正则表达式。
modestring否investigate 或 fix。默认为 fix。

接受以下标志:

  • --auto 无需回答两个问题即可运行各阶段。
  • --open-pr 通过 Cook 到达 Plate。
  • --hard 通过 Cook 到达最终的 Hard-cheese 门禁。

将 --open-pr 和 --hard 传递给每条 /cook 和 /mold 命令。 不要丢弃调用方提供的标志。

Cheese 可以提供 handoff_context.wiki_hits。 每条命中都包含 page、line 和 why 字段。 在第 1 阶段之前阅读每条命中。 指出任何会改变假设排序的命中。

mode: investigate 请求在第 2 阶段后停止。 向来源 skill 返回 reproduced、not-reproduced 或 inconclusive。 调查请求不得启动第 4 阶段。

第 1 阶段:建立反馈闭环

在诊断 Bug 之前,先建立快速且可靠的通过/失败反馈闭环。 此反馈闭环会控制后续所有阶段。

阅读 references/feedback-loops.md,了解按优先顺序排列的闭环选项。 选择能够触及失败接缝的第一个选项。

继续之前,改进闭环。

  • 减少设置步骤和无关初始化。
  • 检查确切症状。
  • 控制时间、随机值、文件和网络访问。
非确定性 Bug

将复现率提高到 50% 以上。 重复触发条件。 增加压力。 缩小时间窗口。 增加可控延迟。

无法建立可用循环

无法建立可用循环时,请停止。 列出你尝试过的每种方法。 请求访问复现环境。 或者,请求获取捕获的产物,或请求允许临时进行生产环境监测。 编写一个 status: needs-context: <the access you need> 交接标记。 协调器提供访问权限后,会重试本次运行。 没有循环时,不要提出假设。

进入第 2 阶段前,请确认以下条件:

  • 每次运行循环都会得到相同结果。
  • 对于不稳定的循环,复现 bug 的概率超过 50%。
  • 一条命令即可运行循环,无需人工操作。
  • 循环会检查报告中提到的确切症状。
  • 循环在 30 秒内完成。

尽量将循环控制在 5 秒内完成。

第 2 阶段:复现 bug

运行循环 5 次。

python3 skills/pasteurize/scripts/pasteurize.pyz repro-rerun \
  --cmd "<repro-command>" --runs 5 \
  --expect-output "<expected failure text>" --threshold 0.5 --timeout 30

始终注明预期的故障模式。 对于输出已知的故障,使用 --expect-output。 对于退出代码已知的故障,使用 --expect-exit。 确认结果包含 reproduced: true。 对于确定性 bug,确认 matches 等于 runs。 查看 results 列表,确认每次匹配的运行。 如果运行 5 次仍未复现不稳定的 bug,请增大 --runs 的值。 在循环复现预期故障之前,不要继续。 不要将无关故障视为复现结果。

症状关卡

提出假设前,先对症状进行分类。

  • 如果堆栈跟踪清晰且循环可靠,请继续使用当前模型层级。
  • 如果涉及竞态、跨模块故障、性能回归或 Heisenbug,请升级模型层级。

使用 harness 命令升级模型。 对于 Claude,使用 /model opus。 然后使用 /effort。 对于 Codex 或 OMP,使用对应的命名命令。 对于其他宿主,使用通用模型升级方式。

第 3 阶段:提出假设

测试任何假设前,先写出 3 至 5 个按优先级排序的假设。 为每个假设说明一个可测试的预测。 无法说明预测的假设应予以舍弃。

使用以下格式:

如果 <X> 导致了 bug,那么 <changing Y> 会消除它,或者 <changing Z> 会使情况恶化。

通过 handoff-gate.md 展示按优先级排序的列表。 领域知识可以改变排序。 如果用户无法联系,或使用了 --auto,请按当前排序继续。

第 4 阶段:添加检测

将每项探针对应到第 3 阶段的一个预测。 一次只更改一个变量。

按以下顺序使用工具:

  1. 如果环境支持,请使用调试器或 REPL。
  2. 在能够区分不同假设的边界处添加有针对性的日志。
  3. 不要记录所有数据后再进行搜索。

为本次调查选择一个会话标签,例如 a4f2。 每条临时日志前都加上确切的标记 [DEBUG-a4f2]。 在交接标记中记录会话标签。 使用会话标签查找清理过程中需要移除的每条临时日志。

对于性能回归,在更改代码前测量基线。 使用计时 harness、性能分析器或查询计划。 然后对故障区间进行二分查找。

阶段 5:修复 bug

在修复前添加回归测试。 仅当存在正确的测试接缝时才添加测试。

正确的测试接缝会在 bug 实际发生的调用点触发真实 bug。 它使用真实的数据路径和故障模式。 浅层或模拟的测试接缝会带来虚假的信心。

将缺少测试接缝视为架构问题。 在交接 slug 中记录此问题。 写入适用的提前停止状态。 设置 next: mold。 不要在错误的接缝处添加测试。

存在正确的接缝时,完成以下步骤:

  1. 将最小复现转换为该接缝处的失败测试。
  2. 运行测试并观察失败。
  3. 应用能够修复该失败的最小生产代码改动。
  4. 运行测试并观察成功。
  5. 运行原始的阶段 1 循环,确认症状已消失。

在下次尝试前撤销未成功的修复。 三次修复尝试均未成功后停止。 返回阶段 3。 编写新的假设排序列表。 没有新假设时,不要进行第四次尝试。

发现新假设时,从阶段 4 重新开始。 否则,写入修复尝试已耗尽状态。 然后设置 next: mold。

将更广泛的改动留给 /cook。 在交接 slug 中记录这些改动。

阶段 6:清理工作树

编写交接 slug 前,完成此清单:

  • 运行原始循环,确认 bug 已消失。
  • 运行回归测试并确认成功。
  • 不存在正确的测试接缝时,记录缺少测试接缝的问题。
  • 移除所有 [DEBUG-...] 插桩。
  • 删除临时测试工具和原型。
  • 在 slug 中记录任何保留的调试文件。
  • 在 slug 中记录已确认的假设。

使用你的会话标签运行插桩扫描:

python3 skills/pasteurize/scripts/pasteurize.pyz debug-tag-sweep \
  --session-tag a4f2 --changed-only --root .

--session-tag 与确切标记 [DEBUG-a4f2] 匹配。 --changed-only 会扫描此工作树中改动过的文件。 扫描会排除 .cheese/、缓存和运行日志等工具输出。 扫描会输出一个包含 files 和 total 的 JSON 对象,并在完成时以状态码 0 退出。 total 为 0 表示扫描未发现标记。 total 非零表示扫描发现了 files 所列的标记。 继续前移除每个列出的标记。 非零退出状态表示输入错误;其 stderr 行是包含 error 和 exit_code 的 JSON。 不要使用范围较广的 --tags 扫描来确认工作树干净。

确定哪些因素可以防止此 bug。 在 slug 中记录必要的架构工作。 应用修复后再提出此建议。

将完成的 slug 交给 /cook <slug> --auto。 Cook 会检查 diff 并运行 cook (⇄ press) -> age -> cure。 Pasteurize 不会提交改动或创建拉取请求。

扇出规模

/pasteurize 当前不会启动任何 Agent。 size_pasteurize_fanout() 在 src/easy_cheese/shared/fanout/pasteurize_route.py 中定义了未来的策略。

该策略会在从最后一个已知正常版本到 HEAD 的可疑范围内,按降序读取 review_surface。 证据评分越低,Agent 数量越多,因为这代表更大的搜索空间。

Bug 类型范围复现Agent 数量
回归紧凑,评分 < 250确定性1
回归紧凑,评分 < 250非确定性2
回归广泛,评分 > 250确定性2
回归广泛,评分 > 250非确定性3
回归无评分确定性3
回归无评分非确定性5
竞态、海森堡 bug 或性能回归任意任意3
冷启动 bug无评分确定性3
冷启动 bug无评分非确定性5

评分 250 定义了紧凑范围。

这些常量由审查者根据经验设定。运行数据尚未对其进行测量。 审查阈值基于 30 次仓库提交。 这些常量没有运行历史。 保留可调整的命名常量。 有真实运行数据后再审查它们。

仅使用 bundle 的主机可以通过以下命令调用该策略:

python3 skills/pasteurize/scripts/pasteurize.pyz pasteurize-route <request.json>

该命令读取 JSON 并写入 JSON。 它遵循 age-route bundle 约定。

首选工具

需求首选工具后备方案
代码搜索与影响分析语义调用方和依赖项搜索限定范围的文本搜索,并提示精确度有限
读取代码从写入后端进行最新的限定范围读取使用稳定行锚点进行限定范围读取
插桩编辑可安全处理过期内容的锚定编辑使用 LSP 或快照编辑,并检测过期写入
GitHub 上下文gh本地 Git 历史或用户提供的链接
外部检查/briesearch明确标注的假设

可选工具不可用时,仍应继续诊断。

输出

返回一份简短报告,包含以下内容:

  • 具名原因及其置信度。
  • 循环命令和观察到的结果。
  • 考虑过的假设及已确认的假设。
  • 回归测试路径。
  • 更改的生产代码行。
  • 插桩和临时文件清理状态。
  • 下一条命令 /cook <slug> --auto。

置信度使用 <certain>、<speculating> 或 <don't know>。

交接 slug

将交接 slug 写入 .cheese/pasteurize/<slug>.md。 使用以下最简格式:

status: <canonical status field>
next: cook | mold | done
artifact: <path-to-richer-report-if-any>
<one-line orientation: what pasteurize confirmed>

cause: <one-sentence named cause>
loop: <command or repro path>
session_tag: <the Phase 4 session tag, or "none">
seam: <regression-test path:line, or "none — architectural follow-up">
fix: <production diff footprint, e.g. "src/foo.ts:42">
follow_up: <architectural follow-up note, or "none">

将方向说明放在第 4 行。 解析器会在方向说明之前读取 status、next 和 artifact。 它不会读取前言中的其他键值行。 在空一行后,将所有诊断字段放入正文。

将更详尽的报告放在 artifact 中,而非诊断内容中。 遵循交接约定。

使用以下状态:

状态处理方式用途
ok继续测试、复现和清理检查均成功。
ok-with-concerns: <reason>继续诊断已完成,但工作需要 Mold。
needs-context: <reason>重试本次运行需要复现权限或已捕获的产物。
halt: <reason>停止本次运行无法继续,且没有后续路线。

编排器会忽略 halt slug 中的 next:。 不要在 halt slug 中指定路线。

标准链路设置 next: cook。 诊断需要架构规范时设置 next: mold。 外部原因无需更改仓库时设置 next: done。

交接

流程: cheese -> pasteurize -> cook --auto (⇄ press) -> age -> cure -> plate

写好报告和 slug 后,通过 handoff-gate.md 提供以下选项:

  • 验证并继续: /cook <slug> --auto。
  • 验证但不启动自动链路: /cook <slug>。
  • 指定架构工作: /mold <slug>。
  • 停止: 将修复留在工作树中。

status: ok 时,推荐选择第一个选项。 用户未选择前,不要启动任何选项。 在 --auto 模式下,跳过此问题。

自动模式

--auto 会跳过 Phase 3 的排序问题。 也会跳过 Phase 6 的交接问题。 清理后启动 /cook <slug> --auto。 不会跳过 Phase 4 或 Phase 5。

提前停止条件

出现以下任一条件时停止:

  • Phase 1 无法得出可用的循环。
  • 两轮 Phase 3 排除了所有假设。
  • Phase 5 找不到合适的回归测试切入点。
  • 最小修复导致 pasteurize 范围外的不相关测试失败。
  • 连续三次修复均未成功,且所有假设均已排除。

缺少合适的测试切入点时,写入 status: ok-with-concerns: no correct regression-test seam。 修复尝试耗尽时,写入 status: ok-with-concerns: fix attempts exhausted — architectural re-examination needed。 这两种情况都设置 next: mold。 缺少复现权限时,写入 status: needs-context: <the access you need>。 始终写入 slug 并展示报告。 不要用猜测代替证据。

规则

  • 不要跳过第 1 阶段。
  • 没有复现循环时,不要提出假设。
  • 在第 5 阶段,仅修改回归测试和最少量的生产代码。
  • 交付前移除所有 [DEBUG-...] 标签。
  • 不要声称 Pasteurize 已发布此项更改。
  • 使用以下完成声明:“原因已明确,回归测试通过,修复已写入代码库,已准备好交接”。
  • 在 slug 中记录架构缺口。

参考资料

评论

支持 Markdown