claude-mem 合并准则(Merge Rubric):Bug-Fix PR 必须通过的根因修复验收标准
本文基于仓库中的 合并准则文档,完整解析 claude-mem 用于判定 bug-fix PR 是否合入的四条硬性标准:什么才算真 bug、为什么"容错机制"式的修复会被整体拒绝、"第二个系统"为何一票否决、以及 diff 规模与缺陷规模的比例检查。读完后你可以掌握这套准则的每一条判定细则,并看到仓库中 CHANGELOG、计划文档与反模式检测脚本是如何把它落地执行的。
准则的来源与整体定位
这套准则的原文档只有四个章节,但每条都来自真实的评审经验。文档末尾的 Origin 说明其出处:
distilled from a full audit of 100 open PRs (2026-07-22),其中合入的少数 PR 无一例外都是小而精准的根因修正——而每一个被拒的 PR 都是某种"为了在 bug 中存活而不是消灭 bug"的机器装置。 (见 docs/merge-rubric.md#L93-L96)
它在仓库中不是摆设,而是实际的执行标准。v13.12.2 版本发布时,仓库对全部 157 个 open PR 逐一按此准则评估,一次性合入 54 个社区 bug-fix PR,并在 CHANGELOG.md 中明确写道:"root-cause corrections only, with no guards, circuit breakers, fallbacks, retries, fail-open modes, self-healing machinery, truncation, or bolt-on second systems"。
整体判定规则写在文档开头,三条原则必须同时满足:
- 每一节都必须通过——任何一节失败即整体拒绝,没有部分得分,不接受"但其余部分是好的";
- 一半 diff 合格 ≠ 整体合格——如果 diff 只有一半符合条件,修复应该只提交那一部分重新提交;
- 准则针对的是 bug-fix PR,功能、强化、性能调优等其他性质的变更不在其中(第 1 节会详细说明)。
仓库内部的工作流文档也把它当作"绑定约束"引用。例如夜间修复计划 plans/2026-07-23-overnight-fixes-single-round.md 在开头第 15 行直接声明:"Binding constraints (repo merge rubric, docs/merge-rubric.md): root-cause corrections only. No retry loops, no circuit breakers, no fallback paths, no fail-open modes, no truncation of user data, no new background processes/state files, no env-var escape hatches. Fail-fast conversions and deletions of machinery are encouraged. Tests are always in scope. Diff size must match the size of the logic error."——这份计划随后按此约束完成了 4 个阶段的根因修复并以 v13.12.4 发布。
第 1 节:它必须修复一个 bug
准则的第一问:这个 diff 修复的是不是"今天就存在的错误行为"?
文档给出的 bug 定义非常具体:错误输出、数据丢失、崩溃、错误状态码、一条从未匹配到的路径、一个从未传出的 flag。这些才是 bug。
而以下六类变更明确不是 bug,提交它们会直接拒绝:
- 功能(Features)——新能力、新设置、新模式。功能 PR 不属于 bug-fix 通道。
- 强化(Hardening)——"让代码更健壮"但没有任何东西行为错误。文档点名了具体形态:对固定字面量参数做 argv 引号重构、纵深防御性的兜底、净化攻击者根本不控制的用户输入。判定标准原文是:"如果你说不出用户今天实际遇到的错误行为,那就是给一道没人受过的伤穿铠甲。'你的代码有多硬'是错误的问题——它正确吗?"
- 性能/成本调优(Perf/cost tuning)——为了经济性做的限流、批处理、缓存。此前什么都没有错。
- 可观测性(Observability)——"记录一条失败日志"不等于"修复失败"。
- Prompt 调优——用更强的指令去推模型的输出是缓解(mitigation),不是修复;这类 PR 通常自己都承认"不能消除问题"。
- 已被取代的修复(Superseded fixes)——bug 必须在当前 main 上仍然存在。对一个已经修好的 bug 做"正确的重修",只是一个戴着
fix:前缀的 no-op。
这条标准在实践中过滤效果显著:v13.12.2 合入的 54 个 PR 几乎全部是"一条错误比较、一个错误 flag、一条错误的 SQL 谓词"级别的修正,例如 CHANGELOG.md 中记录的 "getUserPromptsByIds applies limit after relevance reordering (#3347)"、"Custom observation types preserved instead of being misclassified as bugfix (#3185)"——都是典型的"今天就能复现的错误行为"。
第 2 节:修复不得由容错机制构建
这是准则中最核心、也最反直觉的一节(原文位于 docs/merge-rubric.md#L28-L57)。对 diff 中的任何条件分支,准则要求你回答一个问题:
它是从根因上纠正了逻辑,还是它察觉到了失败并安排如何"活着"?
前者是修复,后者在任何"装扮"下都会被拒绝。文档列举了七种典型装扮:
- Guards(守卫)——记录日志后继续的
try/catch、从不抛错的包装器、"设计上就是 best-effort"、"容忍 N 次失败再丢弃"的计数器。守卫的本质特征:触发之后,失败依然存在,只是更安静了。 - Circuit breakers(熔断器)——失败预算、冷却状态、隔离台账、持久化的重启配额。"唯一职责就是记住系统坏成什么样"的状态。
- Fallbacks(回退)——先试 X 回退到 Y;第一个数据源为空时切第二数据源;真实内容缺失时合成占位内容;用更差输入维持管道运转的降级模式。原文的判断很犀利:回退路径的存在本身,就是承认 X 是坏的而没人去修 X。
- Retries(重试)——作为韧性手段加进来的循环。对确定性失败重试是"变慢地失败";对瞬时性失败重试则掩盖了让它变成问题的缺陷。
- Fail-open / fail-soft 模式——"优雅降级"、"绝不阻塞编辑器"、吞掉错误只给警告。原文的结论是:错误必须大声暴露,否则下一个调试会话要连本带利偿还。
- Self-healing / 恢复 / watchdog / reaper——孤儿清扫器、回收进程的内存轮询器、启动时的进程表扫描、卡死后自重启。这些系统在生产环境里"管理"这个 bug,而不是把 bug 从代码里删除。
- Truncation(截断)——用限长、切片或静默丢弃数据让"症状"塞得下。原文的比喻:如果输出太大、错误或重复,去修生产者,别拿剪刀剪结果。这里有一个明确的豁免:在管道正确的位置遵守显式传入的
limit参数是语义,不是截断。
准则同样明确写出什么是被允许甚至鼓励的:
- 删除上述任何一类机制。"删掉一个重试、一条回退路径、一个静默 catch,是最优秀的 diff";
- Fail-fast 转换——把静默容忍变成位于正确边界上的响亮、即时、类型化的错误;
- 朴素的正确性——正确的排序、正确的路径展开、正确的引号、正确的 flag、正确的 spawn 机制、正确的操作顺序、WHERE 子句里正确的列。"一个
if语句本身是正确的逻辑时没问题——它不能站在错误逻辑前面当门童"。
这套标准在仓库里还有机械化的执行工具。scripts/anti-pattern-test/detect-error-handling-antipatterns.ts 是一个独立的检测脚本,它会扫描 src/ 下的 TypeScript 文件,自动识别字符串匹配错误信息(ERROR_STRING_MATCHING)、只记录 error.message 的局部日志等反模式,并支持用 [ANTI-PATTERN IGNORED]: 原因 注释登记豁免。与之配套的 docs/anti-pattern-cleanup-plan.md 把全仓库排查出的 132 处反模式逐文件列成了清理清单(worker-service.ts 36 处、SearchManager.ts 28 处、SessionStore.ts 18 处……),并声明"所有严重度标识已从检测器中移除——每个反模式都被当作 critical"。这与准则第 2 节的精神一致:与其容忍失败,不如让失败可见、让逻辑正确。
第 3 节:不得引入"第二个系统"
修复必须住在出 bug 的那个系统内部。文档列出五类"一眼拒绝"的形态:
- 新的后台进程、轮询器或定时清扫任务;
- 磁盘上新增的锁文件 / 标记文件 / 状态文件;
- 叠在现有路径旁边"作为兜底"的新生命周期管理器、恢复模块或 FFI 子系统;
- 新的环境变量驱动的备用模式——一个保留旧有错误行为的逃生舱,说明作者自己都不相信自己的修复;
- 任何代码行数远超其所针对的逻辑错误的模块。原文的比喻:"一个错误的比较,不需要 350 行的台账才能变成一个正确的比较"。
唯一的豁免是测试:回归测试是修复的一部分,不算第二个系统。这也与仓库实际做法吻合——第 2 节执行计划中反复出现"Allowed APIs"表格,修复都要求引用现有测试模式(如 tests/server/server.test.ts)为根因修正补齐回归测试,而不是新起一套验证装置。
第 4 节:规模检查
最后一节是一句可以贴在评审桌面上的话:修复的规模应与逻辑错误的规模成比例。
一行错误 → 大约一行的修改加测试。当一个一行缺陷出现在 400 行的 diff 里,多出来的 399 行一定是第 2 节的某种装扮——找出是哪种,然后拒绝。
这条规则把前三节的判断压缩成了一个可操作的启发式:先定位那一行(或那几行)真正的逻辑错误,估算修正它所需的最小 diff,再把超出部分逐行归因——归因结果如果落在 guard、fallback、retry、state file 等类别上,PR 按第 2 节或第 3 节拒绝。
准则在仓库中的完整执行闭环
把散落的仓库证据串起来,可以看到这套准则不只是文档,而是一条完整的执行链:
- 批量评审:v13.12.2 发布时,157 个 open PR 全部按准则评估,54 个通过并合入,CHANGELOG.md 的 13.12.2 条目是这次评审的公开记录,其中列出的修复全部是单点根因修正(Windows 路径引号、
limit应用时机、type=过滤空结果、语义搜索排序丢失等)。 - 约束传递:后续修复计划(如 plans/2026-07-23-overnight-fixes-single-round.md)把准则原文列为"Binding constraints",并进一步给出操作化细则:允许对特定领域状态做显式码值检查(如 close 时的
ERR_SERVER_NOT_RUNNING),禁止无差别try/catch-and-continue;禁止用 SQL 前缀匹配来"永远容忍脏数据",而要求修写入端并回填数据——这正是第 2 节"修生产者,别剪结果"的实例。 - 机械化检测:反模式检测脚本与 132 处清理计划(见第 2 节),把"哪些形态在代码里长什么样"沉淀成了可重复运行的检查。
- 处置记录:对不符合准则的历史 PR,仓库保留了处置说明,例如 plans/root-cause-holistic-execution.md 中对几十个 worker 生命周期、Chroma、Windows 进程相关 PR 逐一标注 "Consume"(采纳其经过测试的源码契约)或 "Supersede"(在此实现根因契约而非整体合入 PR),并遵循"运行时产物必须由源码修改加构建脚本产生,不得手改生成的
plugin/scripts/*.cjs"这类工件规则。
给贡献者的操作清单
如果你准备向 claude-mem 提交 bug-fix PR,可以按以下顺序自检,与准则四节一一对应:
- 第 1 节:我能用一句话描述用户今天实际遇到的错误行为吗?(错误输出 / 丢数据 / 崩溃 / 错误状态码 / 路径从未匹配 / flag 从未传出。)不能 → 这不是 bug-fix,停止。
- 第 2 节:diff 里每个
if/try/catch/ 循环,是在根因上纠正逻辑,还是在让程序"活过"失败?有没有删除机制、fail-fast 转换或纯正确性之外的东西? - 第 3 节:我是否新增了后台进程、磁盘状态文件、生命周期管理器、env 逃生舱,或一个行数远超缺陷本身的新模块?(回归测试不计入。)
- 第 4 节:diff 规模与缺陷规模成比例吗?若一行缺陷对应数百行 diff,多出的每一行能否归因到第 2 节?
- 任何一节失败就只提交合格的那一半,重新提交——准则明确"no partial credit"。
这套准则的价值在于它把"什么算修复"从口味之争变成了可判定的问题:不是代码够不够硬,而是它是否正确;不是失败有没有被兜住,而是失败有没有被删除。对维护一个带常驻 worker、SQLite 存储和多 IDE hook 的持久记忆项目来说,这条"只接受根因修正"的合并标准,正是它能批量处理 157 个积压 PR 并保持代码库收敛的关键工程决策。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00