跳到主要内容

audit-prompt 是异常值

· 阅读需 8 分钟

几十个文件里有一个反着活 —— 一个以英语为正典的框架里,唯一以西班牙语为正典的文件,存在了六个星期,没人发现。一次维护性修复,记录下博客一再遇到的一件事:异常值反过来教你什么是规范。

1. 从提交记录的一行说起

这是本文的操作性开头。2026 年 5 月 12 日的提交 a8a1ac5 包含如下正文,第一句话是这样的:

"dist/.straymark/audit-prompts/ 下的统一 audit-prompt 模板,是框架中唯一一个正典内容以西班牙语存储的制品 —— 其他所有模板、skill、工作流和治理文档,都遵循"英语正典 + i18n/<lang>/ 覆盖层"的模式,由 cli/src/utils.rs:146 负责解析。"

就这一个文件。在几十个文件之中。它反着活。而且它就这样活了整整六个星期,没有人发现。

这篇文章刻意写得很短。它所记录的修复 —— PR #142fw-4.13.3cli-3.12.3,合并于 5 月 13 日 —— 并不是什么重大的叙事节点。这是一次维护性工作。但它记录了我在这门手艺中反复遇到的一个规律:异常值有其价值。它们通过对比,教你什么是规范。


2. 异常值从哪里来

audit-prompt 并非生于框架之中。它最初是 Sentinel 的一个本地 skill —— sentinel/.claude/skills/plan-audit/ —— 诞生于第 3 篇文章所记录的六 Plan 实验期间,也就是四月。它是一个特定情境下的 skill,由操作者(我)以西班牙语编写,理由现在可以坦诚地列出来:这是一次私人实验,操作者说西班牙语,而且这个 skill 此后大概不会有人再读。我用自己的语言随手写了它,因为它只是为我而写。

当实验逐渐凝结成框架 —— 也就是第 4 篇文章所记录的从 fw-4.4.0 到 fw-4.9.0 的演进弧 —— 那个 skill 被移植到了正典路径 dist/.straymark/audit-prompts/audit-prompt.md。移植过程是机械的:复制文件,做够泛化处理使其不再引用 Sentinel 特定的组件,调整 PlanCharter 的命名。没有做的一件事是:把它翻译成英语。这个文件就以它被编写时的语言进入了框架。没有人做出这个决定,西班牙语就这样成了那一个制品的正典版本。

框架的其余部分 —— 每一个模板、每一个 skill、正典治理文档 —— 自一月起就以英语编写,西班牙语和 zh-CN 作为 i18n/<lang>/ 下的覆盖层。audit-prompt 是那个沉默的例外,持续了六周,直到 5 月 12 日。


3. 如何被发现:目视检查

发现它的不是智能体的涌现性观察。是操作者,靠眼睛发现的。CHANGELOG 条目毫无修辞地记录了这件事:

"在 Sentinel 审计 straymark explore 渲染效果时经验性地浮现出来:用户注意到 audit 周期模板是西班牙语,而其他所有模板和 skill 都是英语。"

straymark explore 是框架的 TUI —— 也就是第 14 篇文章将要介绍的交互式文档浏览器。它的价值在于把所有模板并排渲染在同一个视图中。而当所有模板并排显示,其中一个是另一种语言,就显而易见了。就是这样一个观察。

这个数据值得留下,因为它关乎博客的诚实。第 1 篇文章阐述了涌现性观察的模式 —— 智能体标记出没有人要求它标记的事情 —— 第 5 篇文章记录了因结构性可见性缺失而导致该模式不起作用时会发生什么。这个插曲两者都不是。这是一个更平常的观察:框架的一个新界面(TUI)把所有文件同时呈现在视图中,不一致性就变得像你整理书架时发现一本书脊朝内的书一样显眼。工具也能产生可见性。


4. 修复:一次提交里的三个动作

PR #142 在同一次提交里做了三件事:

  • dist/.straymark/audit-prompts/audit-prompt.md 以英语重写为正典版本。312 行。翻译时注意保留了原文的严重程度结构和校准示例。
  • dist/.straymark/audit-prompts/i18n/es/audit-prompt.md 作为覆盖层创建。318 行。原本住在根目录的西班牙语内容,现在回到了它正确的位置。
  • cli/src/commands/charter/audit.rs 接入 i18n 解析器。在此之前,该子命令硬编码了 dist/.straymark/audit-prompts/audit-prompt.md 路径,不查询采用者在 .straymark/config.yml 中的 language 字段。PR 合并后,它会读取项目配置并解析本地化路径 —— 如果采用者设置了 language: es,他们会得到西班牙语覆盖层;如果设置了 language: zh-CN,则回退到英语正典(audit-prompt 尚无 zh-CN 译文);如果设置了 language: en 或未指定,则得到正典版本。

三个新测试覆盖了这三条路径。对英语用户(占多数)零功能变化。对西班牙语用户而言是一次改善:此前,他们收到西班牙语 prompt 是出于偶然(因为正典路径指向了西班牙语);现在,他们收到西班牙语 prompt 是出于约定(因为解析器做出了决定)。


5. 顺带的一步

在做语言切换的同时,操作者借机提取了一处从 Sentinel 起源时遗留下来的具体性。prompt 的 §Step 5 小节 —— 关于发现项的严重程度校准 —— 引用了四月实验中一个真实的案例:"Etapa 12 Pub/Sub stub vs gochannel"。这是一个很有说明性的例子,但它特定于一个没有其他采用者会认识的 Sentinel 组件。

英语译文用一个供应商中立的表述替换了那个示例:"声明的延期,而非缺陷 —— 一个 Charter 引入了一个薄适配层,计划在未来的 Charter 中替换"。那个想法 —— 一个存根,是声明的技术债,而非缺陷 —— 保留下来了。消失的是组件的名称。

这个动作很小,但与博客的原则一脉相承。当有机会在不损失教学性的情况下将框架从某个特定采用者身上解耦,就应该这样做。这与第 3 篇文章为六个 Plan 所记录的、第 4 篇文章为第一个 Charter 所记录的泛化操作如出一辙:经验性内容留在 Sentinel 内部;进入框架的是供应商中立的抽象。audit-prompt,在将近一年之后,终于完成了对这条规则的尊重。


6. 结语

三个简短的论断:

  1. 在一个有约定的框架中,单个文件违反约定,是遗留问题的迹象,而不是设计的迹象。 audit-prompt 是异常值,因为它诞生得更早,而当其他制品对齐的时候没有人迁移它。异常值积累来历。

  2. 新工具产生可见性。 西班牙语到英语的切换,不是通过系统性地审查仓库来决定的。它是因为一个新的 TUI 把所有模板放在同一个屏幕上,不一致性变得显而易见,才被决定的。同样的道理适用于 grep、聚合视图、status 输出:每一个新界面都会暴露出曾经错位的东西。

  3. 小范围的重新标注是去标识化的机会。 当你触碰一个文件来更改语言时,顺带提取出源自起源的采用者特异性,边际成本为零。博客之前记录过这个模式(Plan → Charter、DevTrail → StrayMark);这是它的微缩版。框架一次一个文件地变得更加供应商中立。

下一篇文章,是一个已经在第 1 篇文章中擦肩而过、但值得独立处理的插曲:"模式之前的手工纪律"H-11)。在 Pattern 1 的链式演进机制存在之前,Sentinel 是如何处理 CHARTER-18 的 —— 那段经验性学习,后来在第 1 篇文章中被命名为元模式。


锚点:PR #142。发布版本:fw-4.13.3 / cli-3.12.3。关键提交:a8a1ac5。文件:dist/.straymark/audit-prompts/audit-prompt.md(英语正典)+ dist/.straymark/audit-prompts/i18n/es/audit-prompt.md(覆盖层)。CLI:cli/src/commands/charter/audit.rs 接入 i18n 解析器。

本文档在生成式 AI 工具(Claude 4.7)的协助下撰写;内容的全部责任由人类作者承担。