Skip to content

27 个 PR 没有深审,且它们彼此冲突:mergeable=MERGEABLE 是误导(附实测冲突图与合并顺序) #856

Description

@vansin

🔴 正文有两条推断已被实测证伪(2026-08-14)

下面第 30 行起的「#843×#845 合起来红」与第 50 行起的「取并集会出空壳 job」,
我后来真合了一次并跑了门自己的脚本,两条都不成立。原文保留不动,
但读到那两节请先看更正:#856 (comment)
merge-tree 跑出来的那张「6/10 对冲突」实测图仍然成立。

现状

gh pr list --state open = 31 个,其中 27 个没有任何深审(只有 codex bot 的模板评论),
全部是同一天、同一个作者开的。

瓶颈不在产出,在评审。继续开 PR 只会让这堆变大。

🔴 mergeable=MERGEABLE 在这里是误导

GitHub 的 mergeable 只回答「今天能不能并进 main」。31 个里 30 个都是 MERGEABLE
(唯一 CONFLICTING 的是 #460)。但它们彼此冲突。

git merge-tree --write-tree(干跑,不改任何东西)对 qa.yml 那一簇两两求交:

#798 × #801  ❌     #798 × #803  ❌     #798 × #843  ❌     #798 × #846  干净
#801 × #803  ❌     #801 × #843  ❌     #801 × #846  干净
#803 × #843  ❌     #803 × #846  干净
#843 × #846  干净

10 对里 6 对冲突。第一个落地之后,其余四个的 MERGEABLE 会立刻变成 CONFLICTING。

单测门那一簇同样:

#800 × #801  ❌     #800 × #854  ❌     #801 × #854  ❌

🔴 更危险的一类:merge-tree 看不见的语义冲突已证伪,实测两个合并顺序都绿

文档 pin 那一簇 #843 / #844 / #845 两两文本干净,但合起来会让门变红:

  • #845mcp-tools.md(ZH+EN)的行号 pin 从 44 + 44 清到 0,共移除 43 个唯一 pin;
  • 其中 18 个正是 #843 基线文件里的条目;
  • #843 那道门的判据之一就是「基线里不能有已经不再被引用的残留」——
    它会打印 FAIL: N 个基线条目对应的引用已经不在文档里了,请从基线里删掉 并 exit 1。

所以 #843#845 谁后合,谁就得先缩基线。两个 PR 各自都绿、两两也不冲突,合起来红。

复现:

git merge-tree --write-tree <843-head> <845-head>     # 干净
# 但:
git show <843-head>:docs/doc-source-pins-baseline.txt          # 基线条目
git show <845-head>:docs-site/docs/api/mcp-tools.md | grep -c 'blob/main/[^)#]*#L'   # 0

🔴 qa.yml 那一簇尤其要小心怎么解冲突已证伪,10 对+五全合一个空壳 job 都没有

.github/workflows/qa.yml5 个 PR 同时改(#798 #801 #803 #843 #846)。
这个文件上「按冲突块取并集」会产出:

doc-source-pins:
  name: doc source-pin floor (Docker)     ← 到此为止,没有 runs-on、没有 steps
doc-claims:
  name: doc claim freshness (Docker)
  runs-on: ubuntu-latest
  steps: 

这是合法 YAML,GitHub 接受它,job 名字出现在检查列表里并显示绿色 ——
一道从不执行的门和一道执行且通过的门,在 PR 页面上长得一模一样。
成因是两个 job 的 runs-on / timeout-minutes / steps: / - uses: actions/checkout@v4
逐字相同,被 git 判成公共上下文只留一份。

正确解法不是取并集,是把属于同一个 job 的碎片拼回完整块:
每个 job = 自己的头 + 公共块(各复制一份)+ 自己的体。

(#848 那道 workflow 结构门就是为挡这个而开的 —— 它自己也还没合。)

建议的合并顺序

按「冲突面从小到大」,每合一个就重跑下一个的 merge 检查:

  1. 无冲突的先走:docs: 留一份「陈旧 issue 怎么复核」的做法(四次实核提炼) #846docs(changelog): RFC-014 那条的源码引用钉到当时的提交(现在指向一个 15 行文件的第 253 行) #834docs(changelog): v0.10.1 那两条 cli.ts 引用钉到当时的提交(行号在范围内但已经指错) #851chore: 删掉 test682 这道过时的门,以及 #698 废弃设计留下的两个死模块 (#804) #855docs: 英文 troubleshooting 把 latest 的现状写成了历史;并更正 RELEASE-SOP 一句不成立的话 #807docs: record GrokTUI dog node recovery #808docs: 节点存活判据 —— 看产物推进,不看进程数/started 行 #812docs(CLAUDE.md): Dashboard 那行指向的不是产品形态(能打开、标题也对,所以更难发现) #833docs: record communication dog live TUI UAT #837chore(deps): agent-network lockfile 把 hono 推过修复线(4.12.25 → 4.13.1,清 6 条告警) #842
    只碰自己文件的。
  2. qa.yml 簇:挑一个先合(建议 test(ci): 给 server 补上聚合单测门(69 个单测此前 CI 只跑 6 个) #798,它是其余几个的依赖),
    然后逐个 rebase 其余四个 —— 不要并行合。解冲突时照上面那条规则。
  3. 单测门簇:test(ci): 让 test725/test745 覆盖 tests/ 目录(两个门自称 complete 却漏了 25 个文件) #800test(ci): 给 src/ 补绝对下限 —— 两道门都放行「大量删除测试文件」(#817) #854ci: 元门 —— 新增测试文件不能落在所有聚合门的扫描范围之外(依赖 #798 #800) #801(ci: 元门 —— 新增测试文件不能落在所有聚合门的扫描范围之外(依赖 #798 #800) #801 自称依赖 test(ci): 给 server 补上聚合单测门(69 个单测此前 CI 只跑 6 个) #798 test(ci): 让 test725/test745 覆盖 tests/ 目录(两个门自称 complete 却漏了 25 个文件) #800)。
  4. 文档 pin 簇:先 docs(mcp-tools): 章节源码链接改钉符号 —— 实测 17 处行号锚点 17 处全错 #844 / docs(mcp-tools): 正文行号引用改钉符号 —— 两版行号 pin 归零 #845(它们缩小 pin 集合),再合 ci(test831): 文档站行号 pin 的下限门(守住不再变多,不解决 #831) #843 并同步缩基线;
    反过来的话 ci(test831): 文档站行号 pin 的下限门(守住不再变多,不解决 #831) #843 合完就会被 docs(mcp-tools): 正文行号引用改钉符号 —— 两版行号 pin 归零 #845 弄红。

我为什么开这条

我是上面大部分 PR 的作者。自己写的自己批没有意义,所以我能做的是把这堆的
依赖和冲突关系算清楚,让接手评审/合并的人不必一个个撞。

这一轮我没有再开新的功能 PR。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions