二十个 PR,九个合并,剩下的各有各的死法
九月十九号深夜十一点半,我提了给 Octop 的第一个 PR。
起因特别小。我发现删掉一个对话线程之后,绑定在线程上的会话不会跟着删,变成一堆悬空数据。这个 bug 阴就阴在它不报错,历史就那么静默地不落库,你聊天聊得好好的,重启一看记录少了半截,最后命令行工具直接一个断言崩溃把事情挑明。
我顺着崩溃栈翻进代码,发现会话仓库层少一个级联删除,再往下扒,读会话的路径也得加一道兜底重绑。一个多小时修完提了上去。当时的我并不知道,这只是接下来两周的开胃菜。
到今天为止,我在 Octop 主仓提了二十个 PR,九个合并,五个被关,六个还开着。外加底层运行时 harness 里一个。今天这篇,我想把这二十个 PR 当成一份解剖标本,讲讲一个普通贡献者在六千星项目里打工的真实体验。
先按个头从小到大,一个一个说。
最小的那个,一行 CSS。Octop 的暗色模式有个设计变量没定义,知识库预览在暗色底下白得刺眼。我顺手补了一个变量提了上去,二十分钟合并。这是我在这个项目的第一针疫苗,从此知道了它的发版节奏和 review 口味。
然后是一小串同类的。缺的设计 token、缺失的双语翻译键、AI 生成图片的内联预览没有做沙箱隔离、备份导入会顺手覆盖掉内置技能。这些都不是什么高深的 bug,纯粹是用得多了,坑自己会浮出水面。九月二十七号那天,我一连提了四个,前面说的那行 CSS 就是其中之一。
再往上一级,开始有点意思了。悬空会话那个 PR 合并之后,我在重构频道连接的时候发现 OAuth 回调有问题。它把用户保存的跳转地址直接插进脚本,把提供商的错误信息直接插进 HTML,存储型 XSS 加开放重定向,一步到位。
这个我写得格外认真。复用现有的 SSO 重定向校验,拒绝外站、反斜杠、还有浏览器解析前会移除的控制字符,包括那种用换行绕过域名校验的骚操作。弹窗通信不再用通配符,回归测试一起交。后来它进了 1.0.2 的版本说明。
下一个是我自己最偏爱的,因为它治的是一种很阴的病。
多 agent 协作的时候,目标 agent 的模型重试耗尽了,底层默认返回一条普通的空消息,后台的收件箱一看,有消息,正常完成,记 done。任务失败了,但系统里所有人都以为它成功了。
阴就阴在这里。错误本身不传染,假的成品才会。派活的 agent 拿着这份空成品继续往下走,编排链条上每一个后续节点都在消费一个不存在的成功,等你在结果里发现不对劲的时候,离故障现场已经隔了七八个环节了。
这个 PR 改的是失败的表达方式。重试耗尽就该抛错,让收件箱老老实实记 failed,把错误传回给派活的人。听起来天经地义对吧,但在框架里,把静默成功改成语义化失败,动的每一刀都牵着一串下游。
再往上,是我第一个完整走完闭环的功能。
有个 issue 提议让专家可以配置默认对话模式。我先把现状核实了一遍,写了份完整的 PRD,结论先行,现状十条精确到代码行号,后端四个方案前端四个方案,风险和开放问题列清楚。然后照着自己写的 PRD 实现,十二个文件,加九十三行删七行,四天后合并。
这个 PR 本身不大,但我喜欢它的过程。先想清楚再动手,和 issue 作者确认语义,存储走现有的配置通道不做迁移,每一行 diff 都能回答为什么要存在。开源贡献里最舒服的感觉就是这种,方案在评审之前就已经把自己解释完了。
然后该讲死法了。五个被关的 PR,各有各的宿命,我挑两个说说。
有个团队后台回复的 PR,我实现得挺得意,结果上游后来用另一条路做了一版,主持人改写派工,比我的方案优雅。我心服口服地关掉自己的。还有个定时任务时区的,同样被上游更好的实现收编。另外有个被关掉的时候我挺不服气的,点开合并进上游的提交一看,核心改动确实在里面,只是被压成了别人的提交。内容赢了,名字输了,这算第零点五种死法。被毙不丢人,真的。两个方案撞一起,好的那个活下来,这事本身就挺开源的。
真正值得讲的是另外两个死而复生的。同 agent 重载串行化、上下文用量的统计口径,这俩我都提过一次,被关了,我看了合并进上游的处理后觉得没修干净,重开新 PR 继续跟。现在它们还开着,评论在慢慢积累。开源里没有死透的 PR,只有还没找到时机的 PR。
哦对,还有底层运行时那个 thinking 分块的修复,读过我本地实测那篇的朋友应该记得,我自己修的 bug 在我自己机器上炸了,扳手是自己打的。就发生在昨天凌晨,此处不表。
最后是现在进行时,也是目前最大的一个。
官方 issue 里有个人一直想要的 Agent Mail,让 agent 能收发邮件。十月三号我把实现提了上去,三十八个文件,两千四百多行。设备码授权,十一个邮件和附件工具,邮箱按实例隔离,五种写操作先预览再执行,凭一次性令牌确认,五分钟过期。新邮件靠官方接口的长连接触发定时任务,空闲时不调模型。
为什么写邮件这件事要做得这么啰嗦,因为 agent 摸邮箱这件事的风险等级跟查资料完全不是一个量级。它发给谁的每一封信都是不可撤回的现实操作。所以预览、令牌、过期,这套流程一个都不能省。
这个 PR 现在评论区还是零,维护者还没来得及看。它可能会被毙,可能会大改,也可能哪天出现在某个版本说明里。挺好的,开放结局才有下一集。
两周,二十个 PR,回头看,倒是能咂摸出几条挺朴素的道理。
每个 PR 都长在我自己的使用路径上,没有一个是为了贡献而贡献。能一行的绝不重构,安全修复的描述写得比代码还长,被毙的认真复盘,重开的咬得住。以及一个小发现,第一次提 PR 前我在输入框前坐了半天,反复检查怕丢人,到第九个之后,提交键按得比外卖下单还快。信任是按次储蓄的,对维护者是,对自己也是。
八月底写秋招那篇的时候我说过,企业不信一页纸的简历,信可回溯的痕迹。今天这篇算是那个论点的详细注脚,这二十个 PR 每一个都带着讨论、评审和版本号的轨迹,谁也做不了假。
至于值不值,那个六千星仓库的贡献者名单里有我的名字,changelog 里有几行我写的字。够了。
以上,既然看到这里了,如果觉得写得还行,随手点个赞、留个言吧,想第一时间看到后续也可以订阅我的 RSS~
谢谢你看我的文章,我们,下次再见。



