Skip to content
Touchskyer's Thinking Wall
S3E02
10 min read

硅基团队 S3E02: 他们敢加角色,但不敢碰核心

硅基团队 S3E02

上一集,第一个外部信号是”跑不起来”——基建层失败。这一集的信号更有意思:有人不仅跑起来了,还开始往里面加东西。但他们加的东西,和他们选择不碰的东西,同样值得分析。

五个 PR,五个新角色

两周之内,五个拉取请求(PR)先后出现在 OPC 的 GitHub 仓库里:

  • #24:Performance——性能审查专家。算法复杂度、隐藏的 O(n²)、缺失的记忆化(memoization)
  • #25:Technical Writer——技术写作专家。文档结构、渐进式披露、API 参考质量
  • #26:Localization——本地化专家。国际化就绪、字符串外部化、文化适配
  • #27:Data Engineer——数据工程专家。数据管道、ETL、数据质量、模式设计
  • #28:SRE——站点可靠性工程专家。可用性、告警、容量规划、事故响应

五个 PR 有一些共同特征:

每一个都只改了 roles/ 目录下的文件。#24 改了 1 个文件(roles/performance.md),#28 改了 2 个文件(roles/sre.md + TODO.md)。没有一个碰代码。

每一个都遵循了 OPC 角色文件的四段式格式——Identity(身份定义)/ Expertise(专业领域)/ When to Include(何时启用)/ Anti-Patterns(反模式)。CONTRIBUTING.md 里有一节”Good role ideas we’d love to see”,#24 的 PR 说明里明确引用了它。这意味着贡献者不只是读了代码——他们读了贡献指南,理解了格式约定,然后按照约定产出了内容。这是 EP01 信任模型里”模式理解”层的实证。

加起来:+268 行,-0 行。纯新增,不修改任何已有代码。

这个数字值得停一下。+268/-0 说明贡献者找到了一个”只加不改”的入口——往里加东西不需要删别人的代码。这不是偶然的。角色目录天然支持这种模式:每个角色一个独立文件,文件之间没有 import、没有依赖、没有执行顺序。加一个 roles/sre.md,不影响 roles/security.md 的任何一行。贡献者不需要理解系统里已经有哪些角色,也不需要知道角色之间的关系——零上下文就能参与。五个 PR 来自五个不同的贡献者,说明这不是一个人碰巧找对了入口,而是接口设计本身在说”往这边走”。

沉默的核心

现在看另一面。

翻遍 OPC 仓库的全部 28 个 PR 历史:

  • roles/*.md 的 PR:5 个(#24-28)
  • 碰文档(README、CONTRIBUTING、CONTRACTS)的 PR:5 个(#8-11, #18)
  • 碰测试文件的 PR:10 个(#3, #5, #13-17, #19-20, #22)
  • 碰约束工程(harness)核心代码的外部 PR:0 个
  • 碰门禁(gate)逻辑的外部 PR:0 个
  • 碰 review flow 的外部 PR:0 个
  • 碰扩展系统(extension system)的外部 PR:0 个

有一个 PR 最接近核心:#12 试图给 flow-transition.mjsJSON.parse 加保护(guard),防止未处理的解析异常。这是一个合理的修复——一行防御性代码。但它被关闭了,没有合并。

为什么?不是因为这个修复本身有错。给 JSON.parse 加 try-catch 是教科书级别的防御性编程。它被关闭,是因为即使一行修复,审查者也需要信任贡献者理解了周围的状态机。flow-transition.mjs 里的 JSON.parse 不是孤立的——它的返回值决定了下一个节点走哪条边。加一个 catch 块,catch 之后返回什么?返回 null?那下游的 edge-matching 逻辑会怎么处理 null?贡献者在 PR 描述里无法证明他理解了这些连锁反应。信息不对称太大了。

贡献者的选择是有规律的:他们愿意在最外层加东西,不愿意碰内层任何东西。 这不是一个人的选择——是所有外部贡献者共同的行为模式。

为什么是角色,不是核心

一个角色文件长这样:

---
name: performance
title: Performance Specialist
tags: [review]
---

## Identity
You are a performance-focused code reviewer...

## Expertise
- Algorithmic complexity analysis
- Memory allocation patterns
...

## When to Include
- Code touching hot paths or data-intensive loops
...

## Anti-Patterns
- Premature optimization without profiling evidence
...

一个 markdown 文件。四个固定段落。写错了最坏的后果:审查节点多了一个不太靠谱的视角。

对比核心代码。flow-transition.mjs 处理节点之间的状态转移——当前节点完成后该走哪条边、是 PASS 还是 FAIL、循环计数器是否到上限。改错一行,整个流水线的路径就错了。gate-protocol.md 定义了门禁的判定规则——emoji 计数、severity 阈值、PASS/FAIL 逻辑。改错一个条件,S2E08 发现的”FAIL 从未触发”可能变成”PASS 从未触发”。

而且核心代码之间存在隐式契约。flow-transition.mjs 假设 gate 的返回值只会是 PASSFAIL;gate 假设 flow 的节点定义包含 edges 数组。这些假设没有写在接口文档里——它们活在测试用例和作者的脑子里。外部贡献者看到的是一个函数签名,看不到它背后的约束网络。

改一个角色文件的风险:审查节点多一个视角,最坏无效。改一行核心代码的风险:整条流水线的行为改变。

贡献者不是胆小——是理性的。在不了解系统内部的情况下,碰最安全的一层是最合理的选择。他们在用最小风险验证自己对系统的理解。

这里有两个关键属性在起作用:隔离性可逆性

角色文件是隔离的——改一个不影响其他任何文件。它们也是可逆的——一个写得不好的角色,删掉就行,不会有副作用。核心代码两个属性都不具备。flow-transition.mjs 跟流水线里的每一个节点耦合;改那里的一行代码,影响面是整条流水线的全部路径。而且这种改动不可逆——一旦合并,依赖这段逻辑的测试、门禁规则、节点跳转全部要跟着验证。

这就是为什么 +268/-0 不是巧合。贡献者自发地找到了风险最低的参与方式——一个同时具备隔离性和可逆性的接口。他们不需要被告知”请只改 roles 目录”;接口的设计本身就在暗示”这里安全”。

信任分层转移

EP01 讲了五层信任模型。这一集用真实数据填充了前三层:

第一层(基建):#21 说明 Linux 用户跑不起来。基建层未完全通过。

第二层(模式):五个角色 PR 说明外部人读懂了 roles/*.md 的格式。他们不需要看源码就能理解这个模式——四段式结构是自解释的。更重要的是,五个 PR 来自不同的贡献者,他们各自独立地到达了同一个格式。这不是一个人碰巧猜对了,而是格式本身足够清晰到不需要教。模式层通过了。

第三层(贡献):五个 PR 被提交了。贡献者不只是读懂了模式,还自己按模式创作了新的、有实际审查价值的角色。贡献层在叶子级别通过了。

第四层(核心):零个 harness/gate/review flow PR。核心层没有转移。不是没人想——#12 试过——是风险太高、回报太低。在不理解门禁的内部状态机的情况下,碰一行 JSON.parse 的 guard 都可能引入新问题。

核心层的信任转移需要什么条件?代码需要变得”可读懂”——不只是语法可读,而是意图可读。架构决策记录(ADR)、解释”为什么不用显而易见的方案”的行内注释、作为可执行规格说明的测试用例——这些才是发出”你可以理解我的推理过程”的信号。没有这些,外部贡献者面对的不是一个开源项目,而是一个碰巧代码可见的黑箱。

EP01 说信任不是整体转移的。这一集确认了:信任在叶子层成功转移,在核心层停住了。

Stars/Forks/PRs 的真实结构

层级指标状态
兴趣163 stars
好奇39 forks
基建Linux 可用性未修复(#21 OPEN)
模式理解角色格式复用5/5 遵循
叶子贡献角色 PR5 个
核心贡献harness/gate/flow PR0 个

这张表比单看”163 stars”有信息量得多。163 stars 是一个数字;上面这张表是一个结构。GitHub 的默认统计(stars/forks/contributors)测量的是表面信号。信任转移需要按层拆解才能看清真实状态。

大多数开源项目在展示社区健康度时,用的是 stars 和 contributor 数量。但一个有 100 个 contributor 的项目,如果 95 个只改了文档和配置文件,那”100 contributors”这个数字掩盖了一个事实:核心的维护者可能只有 5 个。Stars 更不可靠——它衡量的是”看了觉得有意思”,跟”能帮你维护”之间的距离比想象中远得多。

OPC 仓库的 28 个 PR 历史提供了一个更诚实的视角:从 star 到 fork 到 PR 到合并,每一步的漏斗转化率在骤降。而这个漏斗里,最陡的断崖出现在”叶子贡献”到”核心贡献”之间——从 5 到 0。

他们不碰核心,说明核心还不是公共资产

回到这一集的标题:“他们敢加角色,但不敢碰核心。”

这句话表面上是描述外部贡献者的行为。但更准确的说法是:核心机制可用,不等于核心机制可被外部信任和维护。

S1-S2 的 harness 代码、gate 逻辑、review flow——这些是我一个人写的,一个人理解的,一个人维护的。它们在我的脑子里有地图。外部贡献者看到的是:一堆 .mjs 文件,没有架构图,没有决策记录(ADR),没有”为什么这一行这样写”的注释。

这不是疏忽——S1-S2 阶段,系统只有一个用户(我自己),写决策记录给自己看没有意义。但当第二个人到来时,昨天的合理省略变成了今天的信任壁垒。文档债不是技术债的一种——它是信任债。技术债让代码更难改;信任债让别人不敢改。

代码是公开的。但理解不是。

一个工具的”核心”不只是代码——是写代码时的权衡、放弃的备选方案、历史 bug 的上下文。这些信息锁在作者脑子里。当外部人只碰叶子不碰骨头,问题不在他们胆小。问题在你的核心没有发出”可以改”的信号。

这是开源的一个悖论。代码是最可见的产出物,但对信任转移来说,代码恰恰是最不重要的。真正转移信任的是元信息:为什么选这个方案、试过什么又放弃了、哪些不变量必须成立。当这些元信息缺失时,贡献者会自我筛选到他们能独立推理的那一层——叶子层。“不敢碰核心”不是能力问题,是信息问题。

下一集看看为什么角色系统能被外部理解——不是因为文档好,而是因为接口设计暗含了”改坏了不怕”的信号。


硅基团队 S3: 从”我能用”到”别人也能用” ← S3E01: 第二个人不是没来,是卡在门口 | S3E03: 为什么角色系统能被外部理解 →

留言