Skip to content
Touchskyer's Thinking Wall
S3E01
11 min read

硅基团队 S3E01: 第二个人不是没来,是卡在门口

硅基团队 S3E01

前情提要: 前两季造了一台机器,然后用它做了八个产品。

S1 的核心发现:AI 能写代码,但不能信它自己说的”写得好”。所以造了 OPC——做的人不评自己,评的人不做事,不过不放行。三条规则约束出来的信任。

S2 把 OPC 拉上战场。家庭日历暴露了方向决策问题,Pi-Math 暴露了停机问题,30 个开源项目提供了参照系,opc-viewer 让审查过程可见。每个产品推一个边界,每个边界倒逼一次框架升级。产品暴露工具的短板,短板驱动工具的进化——这是 S2 的主线。

但 S2E08 用 OPC 审 OPC 自己时,发现了一个尴尬的事实:八个产品,几十次门禁判定,“不过不放行”的回环机制一次都没触发过。核心承诺是一个未行使的承诺。

S2 结尾的问题:从”我能用”到”别人也能用”,中间隔着什么?

S3 不讲 OPC 开源多成功,也不讲没人理。S3 讲信任如何分层转移——有人来了,但他们只信任最外层。

163 Stars 不等于 163 个用户

OPC 开源后,数字来了。

163 个星标(star)。39 个复刻(fork)——至少 39 个人把代码拉到了自己的账号下。GitHub trending 上露了一次脸——那天一天多了 15 个以上的 fork。Issues 开始出现。Pull Request 开始出现。

在这些数字的语境里,“有人来了”是真的。

但”有人来了”和”有人在用”是两件事。star 的成本是一次点击——对代码本身没有任何承诺。fork 的成本稍高:它至少意味着”我想看看源码”,但不意味着”我运行了这个东西”。163 个人表示了兴趣,但兴趣不是使用。要从兴趣变成使用,中间还有一个没有任何数字能衡量的环节:把代码跑起来。

然后第一个真正有价值的外部信号来了。不是夸奖,不是 feature request,而是一句话:

Linux 上跑不起来。

skill.mdSKILL.md

OPC 作为 Claude Code 的一个技能(skill)安装到本地。安装路径是 ~/.claude/skills/opc/,技能定义文件叫 skill.md

问题出在这里:Claude Code 的 skill loader 期望的文件名是 SKILL.md——全大写。

macOS 的默认文件系统 HFS+(macOS 日志式文件系统,APFS 同理)是大小写不敏感的。在 macOS 上,skill.mdSKILL.md 指向同一个文件。你写 skill.md,skill loader 找 SKILL.md,照样找得到。一切正常。

Linux 的 ext4(Linux 默认文件系统)是大小写敏感的。skill.mdSKILL.md。skill loader 找 SKILL.md,文件系统说:没有这个文件。技能静默加载失败。OPC 不工作。

没有报错。没有异常。就是不工作。

报错意味着系统知道自己出了问题——调用者拿到了诊断信息,可以定位原因。静默失败意味着系统认为一切正常,只是功能凭空消失了。用户唯一能感知到的是”这个工具装了等于没装”。对一个刚 clone 下来准备试用的人来说,静默失败和”这个工具根本不存在”没有任何区别。

整个 S1 和 S2——两季的工具链开发、八个产品、109 个测试文件、bash test/run-all.sh 全绿——都在 macOS 上完成。在大小写不敏感的文件系统上。这个 bug 从第一天就存在,但在我的环境里永远不会被触发。

GitHub Issue 里只需要一句”Linux 上 skill 没加载”,但这一句话背后的信息密度比任何一个 feature request 都高:你的测试覆盖范围受限于运行环境的假设。

修复是 11 个文件

PR #21 的修复核心是一行 shell 命令:

git mv skill.md SKILL.md

但改名不够。仓库里所有引用了旧路径的文件都要更新:

  • bin/opc.mjsMANAGED_ENTRIES 数组
  • package.jsonfiles 字段里的安装清单
  • bin/hooks/opc-post-compact.sh:上下文压缩后的恢复提示
  • CONTRACTS.mdCONTRIBUTING.mdINTEGRATION.md
  • 5 个 pipeline 文档:gate-protocol.mdloop-protocol.mdreport-format.md

11 个文件,+16 行 / -16 行。每一个改动都很小——把 skill.md 换成 SKILL.md。但这 11 个文件分布在代码、配置、钩子脚本和文档四个不同的层面。一个文件名的大小写,牵动了四层基础设施。

这个扩散范围本身就说明了问题。如果 skill.md 这个文件名只出现在一个地方,修复就是改一行。但个人工具在发展过程中不会刻意管理引用关系——好用就行,哪里需要就写哪里。两季的迭代下来,一个文件名被嵌进了入口脚本、包清单、恢复钩子和设计文档四个不同层面。没有人在 Day 1 会为一个文件名建立引用索引,但到了需要改名的时候,这些散落的引用就变成了修复的成本。

109 个测试文件全部通过——它们从来没测过”文件名在大小写敏感的文件系统上能不能被正确找到”。因为运行环境本身就是大小写不敏感的。测试在自己的环境里看不到自己的盲区。这和 S2E08 发现的”FAIL 路径从未被触发”是同一类问题:在本书反复验证的经验中,没被测过的机制和不存在的机制,在生产环境里没有区别。

你可以写测试验证文件是否存在、路径是否正确、内容是否被正确读取——但你没办法在大小写不敏感的文件系统上测试大小写敏感的行为。这不是测试覆盖率的问题,而是测试运行环境本身的局限。覆盖率工具会告诉你每一行代码都被执行过了,但不会告诉你:执行这些代码的前提条件在另一个操作系统上不成立。100% 行覆盖率 + 零跨平台测试 = 对自己环境的 100% 信心和对其他环境的 0% 信心。

信任有五层

S2E08 的结尾问了一个问题:“从我能用到别人也能用,中间隔着什么?”

#21 给出了第一个答案:中间隔着你看不到的环境假设。

但 #21 只是第一层。回看 OPC 开源后的所有外部信号——stars、forks、issues、PR——一个模式开始浮现。信任的转移不是整体发生的,而是一层一层的:

第一层:基建。 别人能不能跑起来?#21 说不能。macOS 上的一切正常,Linux 上静默失败。第一个用户碰到的不是你精心设计的审查流程,而是 skill 加载失败。

第二层:模式。 别人能不能理解你的设计模式?这不只是”代码能看懂”——代码能看懂是最低要求。模式是指:你的约定、你的命名规则、你组织文件的方式、你选择让某些东西可扩展而让另一些东西硬编码的决策逻辑。后面的 PR 会回答这个问题——有人看懂了 roles/*.md 的格式,照着现有角色的结构,自己加了新角色。

第三层:贡献。 别人敢不敢往里面加东西?理解是被动的——读代码就够了。贡献是主动的——你要做一个判断:“我改的东西会不会破坏现有的东西?“这个判断需要信任自己对系统的理解,也需要信任系统有足够的防护网来兜底。

第四层:核心。 别人敢不敢碰约束工程(harness)、门禁(gate)、审查流程(review flow)这些核心机制?核心机制是约束系统的骨架——一旦改动,影响的不是一个功能,而是所有功能的行为边界。碰核心意味着”我理解这个系统为什么这样设计,并且我认为设计本身应该改变”。这是最高程度的信任。

第五层:承受。 系统能不能承受外部使用者的失败、误解和非预期用法?一个只被作者使用过的系统没有经受过误解的压力。外部用户会传错参数、跳过前置步骤、用你没预想到的方式组合功能。系统要么足够健壮能给出有意义的错误提示,要么就会在非预期用法中静默崩溃——就像 skill.md 在 Linux 上那样。

163 stars 测量的是兴趣。39 forks 测量的是好奇。但”兴趣”和”能跑起来”之间,隔着一个文件名的大小写。S3 要写的,就是信任如何从第一层开始,一层一层往上转移。

个人工具变公共工具的第一课

#21 的教训不只是”记得用大写”。它暴露了一类更普遍的问题:个人工具里隐含着大量未声明的环境假设。

我的开发环境:macOS + zsh + Homebrew + 英文 locale。OPC 在这个环境里打磨了两季。所有的 shell 脚本、路径处理、文件名约定,都隐含了一个假设:运行环境和我的一样。

这些假设不是有意做出的——没有人会写一行注释说”注意,这里依赖 macOS 的大小写不敏感特性”。它们是开发过程中自然累积的。你选择了一个文件名大小写约定、选择了一个路径分隔符的写法、选择了一个 shell 语法特性,这些选择在你的环境里不构成”选择”——它们只是”事实”。只有当运行环境改变时,“事实”才暴露为”假设”。

这个假设在 S1-S2 不是问题——只有一个用户,就是我。但 OPC 开源的那一刻,这个假设就变成了一枚地雷。没人知道第一个 clone 的人用的是 Ubuntu 还是 Arch Linux,是 bash 还是 fish,locale(语言区域设置)是 en_US.UTF-8 还是 zh_CN.GBK。一个用户只有一种环境组合,一百个用户意味着一百种你没见过的组合。个人工具开源的那一刻,测试矩阵从 1×1 膨胀成 N×M——N 种操作系统乘以 M 种 shell 和配置的排列。

S2E08 说”隐式连接是定时炸弹”——那是在讲工具链之间的隐式依赖。#21 说的是同一件事,但方向不同:隐式的环境假设是定时炸弹,只会在别人的机器上爆。

这不是一个可以通过”多测一点”解决的问题。你需要做的不是在 macOS 上多跑几轮测试,而是在不同的操作系统、不同的文件系统、不同的 shell 上跑。CI 矩阵、Docker 容器、跨平台冒烟测试——这些不是”有了最好”的东西,它们是信任基建层的地基。

“别人也能用”的第一关不是文档

回看这一集的核心:

第一个真正有价值的外部反馈不是”你的审查流程很聪明”,也不是”能不能加个 feature”。是”跑不起来”。

你花了两季优化审查的准确度、加角色、加门禁、加设计审查、让过程可见。然后第二个人来了,卡在了安装步骤。

“别人也能用”的第一关不是文档有多完善、README 写得多清楚。是环境的真实差异——操作系统、文件系统、shell——这些开发者在自己的机器上永远不会碰到的东西。

开发者的直觉通常把”让别人用起来”等同于”写好文档”。这个直觉不是没有道理——文档确实是最显眼的缺口。但 #21 暴露的是另一个层面的问题:即使文档完美无缺,一字不差地描述了安装步骤,用户按照步骤操作,在 Linux 上依然什么也不会发生。文档解决的是”用户不知道怎么做”,而 #21 暴露的是”用户完全按照说明操作但系统无法工作”。前者是知识缺口,后者是基础设施缺口。两种缺口的修复方式完全不同。

#21 还是 OPEN 状态。修复已经准备好了——11 个文件的改动干净利落——但它提醒的不只是一个 bug:你在一个平台上”能用”和”任何人在任何平台上能用”之间的距离,比你想的远得多。

下一集,有人不仅跑起来了,还开始往里面加东西。但他们加的东西,和你预期的不一样。


硅基团队 S3: 从”我能用”到”别人也能用” ← S2E08: 让工具审自己,发现它从没拦过谁 | S3E02: 他们敢加角色,但不敢碰核心 →

留言