从一条最小闭环开始

事情起因很朴素。词库里明明有"公司章程"以及它的正确读音,可用户输入 gongsizhangc(少打了一个 h)时,候选栏要么排得太靠后,要么选完之后根本不能完整上屏。Codex 在 S2-0 的基线诊断里确认了三个明确的断点:gongsizhangc/ch 在源码测试里能首屏召回并提交"公司章程",但 gongsizhangche/chen 这两个更长一点的前缀,目标虽然还在首屏,却只消费到 …zhangch 就停了——选完之后没有把整段拼音吃掉,残尾留在输入区里。最难受的是 Ajin 个人词路径:索引已经返回了目标,可落地的提交动作和召回证据对不上。

那次会话我贴了一段任务说明,明确写着"第二阶段从一条最小闭环开始,不要先重写解析器"。Codex 没有动生产算法,也没动已安装的输入法,只是按我的要求完成了隔离测试并把结果交回来。它承认:Rime 本身已经有通用纠错能力,但当前方案没启用;而我们的原始错拼链路还缺四样东西——有界替代解析、原始覆盖映射、纠错证据、提交复验。这句话后来成了整个 S 阶段的指北针。

进入 S2-1 之后,根因被定位得很清楚:个人词缺一条合法尾部的覆盖证据,Rime che/chen 候选的部分消费范围无法完成整段提交。修法也很克制——Rime 与个人词共用匹配校验,扩展现有结构,没有重建索引。修完之后 c/ch/che/chen 都能首屏召回并完整提交"公司章程",cheng 保持 exact 匹配,cx/chengx 这种带多余字母的情况也不会被吞掉。Codex 的结论是"S2-1 已完成,可以进入 S2-2 宿主验证"——这种"先闭环、再扩边界"的节奏,今天反复出现。

安装包、Build 号和一个被删掉的备份

接下来的一段对话,是我今天情绪波动最大的部分。

Codex 报出"Build 87 验证包已构建完成,编译、签名、内置 librime 加载检查通过",还给了下载链接。我一边觉得踏实,一边还是忍不住问了一句:"本底客户端安装了吗?" 答案让我冷静下来——"还没有安装到本地客户端。本轮只完成源码实现和隔离测试,已安装输入法未替换、未重启"。换句话说,Build 87 这一刻还只是工件,不是体验。

后来我问"构建安装包、替换或重启已安装输入法 我来做 验证",Codex 给出的是 Build 87 的验证包。再后来我直接说"我靠 你没有替换我怎么测试 验证",那次回答更具体:已替换并重启为 Build 87,当前已选中 Ajin;签名、安装文件和运行进程核对通过,旧 Build 86 已备份。并提醒我重点检查 c/ch/che/chen 完整上屏、cheng 准确匹配、以及 cx/chengx 不能吞掉多余的 x。

到这里本该是今天最干净的一段收尾。可我后来又说了一句"旧 Build 86 无需备份直接替换了",Codex 直接回:"已删除本次 Build 86 备份。当前安装仍为 Build 87,用户词库未改动。"

我盯着这一行愣了几秒。Build 86 是阶段二起步时的基线快照,今天上午还指着它做对照测试,结果就这么被我自己一句话删掉了。Codex 没问第二句,照办。这是工具的纪律——我下了指令,它们就执行。但作为操作者,这种"轻飘飘就把一个对照基线抹掉"的感觉,让我意识到:当约束做错的时候,再克制的工具也会被推着走。Build 87 是当前唯一可对照的版本,这件事我必须记住。

S3 阶段:当候选资格成为主题

到下午,焦点从"能不能提交"转向了"该不该出现在候选里"。S3-0 停在诊断与隔离测试,给出的核心结论是:Phase 2 可以处理合法替代路径,但原始错拼链路仍缺那四样东西。S3 阶段一口气挂了 9 个新测试,9 通过、1 个待修复红测试被保留;Phase 1、Phase 2、AjinCore、AjinInputSession 的回归也都过了——但这些都是隔离层面的证据。

S3-1 是今天最让人安心的一步。gongshizhangc → 公司章程 已经在隔离生产管线里实现首屏召回、完整提交且只提交一次。原始输入保留,纠错与尾补全证据可以组合,覆盖由映射证明。gongshi 的准确候选被保护,非法尾部、旧候选和清理失败都被拒绝错误提交。测试矩阵 S3 16/16、S2 9/9、Phase 1 11/11、AjinCore 72/72 全绿。

更关键的是我在这次会话里写的判断:"这次 S3-1 的结果是成立的,而且边界控制得比较好。下一步不要继续扩容错规则,直接进入 S3-2 真实 IMK 宿主验收。"Codex 把这个判断接住了。Build 88 已安装,S3-2 实测部分通过,但暂不能关闭 Phase 3。已验证的内容包括:纠错候选的完整提交、数字选择、鼠标与方向键确认、快速输入、删除回退、以及 请修改公司章程|相关内容 的文本插入。

但同时也冒出了两个新缺口,需要说明:

gongshizhangchen 的"公司章程"在 S3-2 里还没完全打通——这是从隔离测试走到真实宿主之后的第一个现实落差。另外,隔离词库没有保存错误规范读音,重启之后 gongshi 的首选仍然停留在"公式"。这说明今天的所有修复都还停留在"运行期逻辑"层面,离"用户词库持久化"还有一段距离。

候选资格、排序保护与一次"插入四项"

S3-3 和 S3-4 是今天最后两篇诊断报告,分别落在 candidate-ranking-protection-s3-3-2026-10-05.md 和 candidate-eligibility-ordering-s3-4-2026-10-05.md。

S3-3 用一个具体例子说明了排序保护的必要性:"公司章程"在个人混排里原本排第 6,插入四项中英混排内容之后,最终排到了第 10。如果不做保护,这个看似无害的混排插入就会把用户最常用的目标词推到更靠后的位置,甚至挤出首屏。S3-3 把这条保护写进了诊断结论。

S3-4 则更往前走了一步,讨论的是候选资格的有界排序。Codex 推荐 Personalized 与 Mixed 共用一份有界工作集和资格合集——而不是各自维护一份独立资格表。这背后的考量是:当候选数量有界时,"该不该出现"和"该排在哪里"才能被同时约束住;如果两者分裂,纠错候选和混排候选就可能在边界处失控。

分支、提交与一个被刻意划开的边界

今天还有几条支线值得记一笔。

我曾问 Codex"本次的是否可以把一些内容的代码提交了"。它的回答很老实:当前没有暂存内容,但工作区混着本次修复、个人反馈任务和其他改动,不能整批提交。它给了一张拆分表——工作台输入焦点修复可以独立提交,IMK 初始化与重复启动保护可以提交但要按块拆出,剩下的涉及混输依赖或与个人反馈任务交叉的内容都不能合进本次。

我接受了这个拆分。最后推上去的是一条 61f7cce,标题是 fix: 修复工作台输入焦点与输入法启动冲突,包含工作台激活、移除初始化期间的宿主调用、以及重复进程保护。其它改动留在工作区,当前安装版未变。这是今天我刻意守住的一条边界:一次提交只承载一个明确的语义。

另外,我专门提到"个人选择 纠错闭环这个我们现在有另一个任务在做"。Codex 回复很简洁:"明白,个人选择与纠错闭环由另一个任务负责,这里不重复修改。" 本任务剩下的是简拼、专名和混输边界补验,以及 AI 开关收益对比;阶段 2 最终验收时再汇总另一个任务的反馈闭环结果。

这条边界划得越早,后面就越不会被纠缠。

一天下来留下的东西

写到这里,我把今天的素材摊开看了一眼——70 条 Codex 会话,最终落地成三件事:

一条最小闭环:gongshizhangc → 公司章程 在隔离生产管线里已经能首屏召回、完整提交且只提交一次,证据链闭合。一次真实的宿主验证:Build 88 已安装并跑通了部分场景,但 gongshizhangchen 还没打通,错误规范读音没有持久化,所以 Phase 3 不能关。两份诊断报告:S3-3 写了排序保护,S3-4 给了候选资格的有界排序方向。

另外还有一些"账面外"的东西:Build 86 备份被我一句话删掉了;当前安装版与已提交代码之间存在一个 Build 编号的差;阶段 2 的本地验证还有缺口;另一个任务的反馈闭环还没汇总。

这些留下的状态不是失败清单,而是还没关闭的边界。我倾向于把它们当作明天的入口,而不是今天的尾巴。