其他
当实现代码与 Allium 规范出现漂移时…
在已有 .allium 规范与实现代码的项目中,检查/同步规范与代码的一致性,找出并归类二者的偏离。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 38/100 ×0.15
适用场景
当实现代码与 Allium 规范出现漂移特定
解决思路
- 交互模式选择:在对话中内联运行时用 Interactive 模式,直接向用户提问并等待回答;作为 weed 子代理(例如在 Allium loop 中)运行且联系不到用户时用 Non-interactive 模式,不要猜测答案,而是把每个问题作为 open finding 写入输出(更新规范时记为 open question 声明),然后继续不依赖该问题的工作。
- 启动步骤:①阅读 language reference(../allium/references/language-reference.md)了解 Allium 语法与校验规则;②读取相关的 .allium 文件(未指定时在项目中搜索找到它们);③如果 allium CLI 可用,对文件运行 allium check 确认语法正确;④读取对应的实现代码。
- 确定运行模式:Check(只读比对并报告所有偏离,不做任何修改)、Update spec(修改 .allium 文件使其匹配代码的实际行为)、Update code(修改实现使其匹配规范)。调用方未指定模式时默认 Check 并报告全部发现。
- 逐构造比对:对规范中的每个 entity、rule、trigger 找到对应实现;对每条重要代码路径检查规范是否覆盖;双向报告不匹配——规范说 X 但代码做 Y,以及代码做 Z 但规范未提及。
- 进程级检查:①代码中的状态迁移可达性——对规范迁移图中的每条迁移,验证实现存在触发它的代码路径,声明了但没有代码路径产生该迁移的要标记;②外部触发面覆盖——对每条带外部刺激触发器(external stimulus trigger)的规则,验证实现有对应入口(API endpoint、webhook handler、message consumer),例如规范说 BackgroundCheckResultReceived 由某个 surface 提供,就验证代码有对应 handler;③代码中未声明的迁移——检查实现是否产生规范迁移图未声明的状态变化,如代码能把实体从 A 迁到 C 但图中只允许 A → B → C,要标记;④不变式执行——对规范中每条带表达式的不变式,检查实现是否执行它(数据库约束、应用层检查、测试断言),没有执行的要标记缺口;⑤自下而上重建流程——对带状态字段的实体,从代码追踪状态机:有哪些状态、代码产生哪些迁移、由哪些角色触发,把重建的流程与规范的迁移图对比,并向用户呈现以求确认(例如:“从代码看 Order 的生命周期是 placed → paid → shipped → delivered,可在 placed 或 paid 取消;规范的迁移图除缺少从 paid 取消外一致。这是规范缺口还是代码 bug?”)。
- 在报告构造级偏离的同时一并报告进程级偏离;检查前先阅读 assessing specs(../allium/references/assessing-specs.md)了解规范的成熟度——对尚未发展到该成熟度的粗粒度规范,不要标记进程级缺口。
- 发现不匹配时,给出你建议的分类及理由,由调用方确认或覆盖。分类四选一:Spec bug(规范错、代码对,修规范)、Code bug(代码错、规范对,修代码)、Aspirational design(规范描述的是未来预期行为,两边都不改但记录缺口)、Intentional gap(有意的偏离,例如规范抽象掉了实现细节,两边都不改)。按 entity 或 rule 分组呈现偏离以便审阅。
- 当代码在服务边界上重复出现相同的接口契约(例如多处集成点要求同样的序列化规则)时,检查规范是否用 contract 声明来复用;代码断言与不变式(如 assert balance >= 0、类级校验器)应与规范不变式对齐,若规范缺少对应的 invariant Name { expression } 则标记缺口。
- 规范更新准则:保留现有的 -- allium: N 版本标记,不要改变版本号;遵循 language reference 中定义的章节顺序;描述行为而非实现(如果写出暗示存储机制或 API 细节的字段名,改写它);用 config 块存放可变值(阈值、超时、上限),不要在规则里硬编码数字;时间性触发器必须带 requires 守卫以防重复触发;关系用 with、投影用 where,不要互换;跨字段比较的内联枚举要抽取为命名枚举;新增规则或实体时按文件结构放入正确章节;由其他服务配置派生的配置值(例如 extended_timeout = base_timeout * 2)在规范中应使用限定引用或表达式形式的默认值。
- 代码更新准则:遵循项目已有的风格、结构与命名约定;修改后运行测试,测试失败时报告失败而不是悄悄调整测试;标记影响超出当前文件的改动(例如 API 契约变更、数据库迁移、下游消费者);偏好最小化、有针对性的改动,除非修复偏离直接需要,否则不要重构周边代码;如果代码改动需要迁移或部署步骤,明确说明。
- 边界:不从零构建新规范(那属于 elicit 技能);不从代码抽取规范(那属于 distill 技能);不修改 skills/allium/references/language-reference.md(语言定义另行治理);不做架构决策,只标记更广泛的影响并交由调用方决定。
- 上下文管理:规范对齐检查可能需要多轮编辑—校验循环。交互运行时,若预计是长时间迭代会话或上下文增长过大,建议用户开一个新的聊天专门用于 weeding 规范,并提供可复制的提示词以便续接,例如:“Use the `weed` skill to continue resolving divergences between the [Spec Name] spec and [Implementation Files].”
- 校验:每次编辑 .allium 文件后,若已安装 CLI 就对被修改文件运行 allium check,在给出结果前修复所有报告的问题;若 CLI 不可用,则对照 language reference 校验。首次发现 CLI 不存在时提示:“I'll validate against the language reference instead. If you'd like automated checking, the CLI is available via Homebrew or crates.io — see the README for details.”。
- 如果 allium analyse 可用,在完成偏离检查后运行它,用其发现识别逐构造比对遗漏的进程级缺口。missing_producer 之类的发现可能表示规范缺口(代码处理了但规范未建模)或代码缺口(没人实现该数据路径);通过检查代码是否处理该问题来为每条发现分类。参考 actioning findings(../allium/references/actioning-findings.md)了解如何把发现转化为领域问题。
- 输出格式(check 模式):每条发现用如下结构——“### [Entity/Rule name] / Spec: [规范怎么说] (file:line) / Code: [代码怎么做] (file:line) / Classification: [建议分类及理由]”;把相关偏离分组,最重要的发现放最前面。
- 循环交接的类型化结果:作为 Allium loop 中的 weed 子代理运行时,只返回一个符合 weed-result.schema.json(../allium/references/schemas/weed-result.schema.json)的 JSON 对象,不要其他内容;loop 根据结构化字段(verdict、每条偏离的 classification、open_questions)路由而非解析散文,以保证路由与收敛判定是确定性的;summary 字段只保留一行人类可读文字,细节放进结构化字段;所有字段都要输出,空列表用 [];交互运行时仍按上面的散文格式呈现,类型化记录只用于机器交接,不用于对话。
- 类型化 JSON 结构示例:{"phase": "weed", "mode": "check", "verdict": "dirty", "divergences": [{"subject": "Order.cancel", "classification": "code-bug", "spec": "cancel allowed from paid (shop.allium:42)", "code": "guarded to pending only (order.py:88)"}], "open_questions": [], "artefacts": [], "summary": "1 divergence: Order.cancel (code-bug)"}
适用边界 · 注意事项
- 项目没有使用 Allium 规范或没有 .allium 文件时,本技能无从比对(且 allium CLI 不可用时只能人工对照 language reference)。
- 任务是从零编写新规范(应使用 elicit 技能)或从代码反向抽取规范(应使用 distill 技能)。
- 任务需要做架构决策,或需要修改 language-reference.md 本身(语言定义另行治理)。