关于 caveat-lang
caveat-lang 是 Caveat 规则语言和运行时的编写桥梁,面向构建 Agent 的团队,可在证据变化时重新审视决策。它支持验证和测试策略、查看决策依据并查找依赖项。
主要功能
- 01验证 Caveat 源码
- 02运行策略场景测试
- 03解释决策的证据与限制
- 04跟踪重新打开的决策
- 05查找依赖值
适用场景
- 01集成前检查 Caveat 程序
- 02通过不同场景测试策略结果
- 03查看 Agent 决策重新打开的原因
MCP 相关
项目包含 MCP 服务,可向 Agent 提供 Caveat 工具;README 指向其配置指南。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
5收录的工具列表 · 更新于 2 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| source | string | 是 | 内联 Caveat 源代码;不查找文件或 URL。 |
详细介绍
原文在翻译后有更新,译文可能不是最新。
CAVEAT Language
面向 Agent 的决策台账。
Caveat 是一种可嵌入的决策运行时,配有一套精简的规则语言。它会在计算过程中追踪证据,保留已记录决策的依据,并支持在证据发生变化时,根据编写的策略重新审议决策。
对于需要治理 Agent 的团队,Caveat 也是 Agent 决策的审计跟踪记录。caveat explain 会显示每项决策的依据:相关证据与注意事项、所需权限及其原因,以及决策后来为何被重新打开。
撤回证据会将相关信息添加到记录中,绝不会改写决策最初的依据。应用程序负责存储事件;Caveat 不会为事件签名,也不会验证证据,因此它是对平台身份、权限和日志控制的补充,而非替代品。
已发布版本为 1.1.0,是 1.x 的首个次要版本。有关新增内容,请参阅 1.1.0 版本记录;有关 1.x 的承诺,请参阅 1.0.0 版本记录。
npm 发布已于 2026-10-19T16:58:54.313Z 验证:准确版本为 [email protected], 经测试的 Linux 构件 SHA256 为
f83ff39ed18c473f67c4d1ad2adb6ddaf1a9b6fec9e0a71ae9c1ffe4b71be41d。 由publish-npm.yml从标签v1.1.0发布,并附带 npm 来源证明。2026-10-19 已验证latest和next均为 1.1.0。 发布记录。
当工具结果被更正,或记忆被证实已过时,应用程序需要重新审议决策,同时保留最初的决策理由。Caveat 是一种编程语言,它会将证据和注意事项与计算所得的值一并保留,冻结决策的依据,并记录决策被重新打开的原因。
在空目录中使用 Node 20 或更高版本试用已发布版本 1.1.0。无需安装 Rust:
npm init -y
npm install [email protected]
npx --no-install caveat-lang init
npx --no-install caveat-lang test umbrella.scenarios.json
npx --no-install caveat-lang explain umbrella.cav events.jsonl
两个场景均可通过。解释结果显示,umbrella@1 = 70 因 sky 而重新打开,仍基于 rain_chance@1,并保留其 forecast_is_old 注意事项。新知识改变了决策的状态,但其原始依据仍清晰可见。入门指南将带你了解这些文件,语言简介则介绍语法。
从这里开始
要了解 Caveat 的作用,请在空目录中给编码 Agent 布置以下任务:
Install the caveat-lang npm package (Node 20 or later) in this empty directory
and run `npx --no-install caveat-lang init`. Read
node_modules/caveat-lang/docs/REFERENCE.md before writing any Caveat source.
In umbrella.cav, raise the rain chance needed to commit the umbrella decision
from 50 to 60. Add a scenario to umbrella.scenarios.json showing that a 55%
forecast leaves the advice at "No decision yet". Run
`npx --no-install caveat-lang check umbrella.cav` and
`npx --no-install caveat-lang test umbrella.scenarios.json`, then run
`npx --no-install caveat-lang explain umbrella.cav events.jsonl` and tell me
what umbrella@1 rests on and why it was reopened. Change no other files.
三个场景均通过,解释仍显示 umbrella@1 依托于 rain_chance@1 及其 forecast_is_old 注意事项;sky 重新打开后也是如此。
| 目标 | 从这里开始 |
|---|---|
| 亲自试用 Caveat | 入门指南 |
| 通过 MCP 向 Agent 提供 Caveat 的工具 | MCP 服务 |
| 将 Caveat 集成到 Agent 或应用中 | Agent 快速入门和Python 客户端 |
| 编写 Caveat 源码 | 语言简介和编写指南 |
| 查看已证明和已测试的内容 | 检查了什么,以及如何检查 |
| 报告 Caveat 缺少的能力 | Agent 功能请求 |
| 查看各个版本的变更 | 发布历史 |
1.0.0 已验证的发布记录标明了经过确切测试的 npm 制品。1.0.0 将兼容性承诺确立为每个 1.x 版本的保证:语言、19 个拒绝代码、CLI、库导出、serve、MCP 工具、命名架构和存档均保持稳定,1.x 小版本只会新增内容。相较于 rc.20,它没有新增语言、架构、操作、字段、CLI 标志、导出或 MCP 工具,Rust 运行时也与 rc.20 保持不变。
恢复存档仍不会验证其历史记录。被拒绝的操作并未完成;宿主必须检查其结果。此软件包没有 npm 运行时依赖。
安装 1.1.0 后,使用 npx --no-install caveat-lang doctor 检查,使用 npx --no-install caveat-lang demo agent 在一次运行中查看观察、评估、纠正和修订。caveat-lang 命令自 rc.7 引入以来一直是首选的无歧义命令;caveat 是受支持的简写形式。请参阅 CLI 名称。
正在集成 Agent? 请遵循 Agent 快速入门和官方 Python 客户端。Caveat 会记录提供的证据和编写的策略;它不会验证证据,也不会授权外部操作。仓库 Agent 指南包含如何报告实际集成中缺少的能力。
它的依据是什么? 检查了什么,以及如何检查区分了 Lean 模型定理(proofs/lean)、带变异控制的原生和 WebAssembly 抽样一致性测试、运行时测试,以及没有任何证明能覆盖的边界。文档还说明了限制:窗口不会限制存档大小,没有任何内容经过身份验证,宿主需自行设定资源预算。
原则与能力
有关 Caveat 背后的理念,请阅读 The Caveatist way。
说明你知道什么,以及依据何在。
如实保留注意事项。
根据不确定性可能造成的后果,给予相应重视。
条件足够时就采取行动。
记住你为何作出选择,并愿意再次选择。
这些是项目的原则,并非额外的许可条件:Caveat 采用 MIT License,使用它并不要求你遵循这些原则。
- 值会携带其证据。 根据观察计算出的每个数字,都会在每次求和、比较和标注时携带其证据及注意事项。
- 解释会根据记录的依赖项进行检查。 程序显示的任何内容都可以说明原因,而运行时会拒绝引用值所记录依赖项之外内容的解释。这并不能证明证据属实或解释完整。
- 决策会留下记录。 决策会记录其依据;当现实与之不符时,决策会重新开启,并保留日志。
- 补充迟来的知识,只需一行。 迟来的限定说明会传递给基于该证据构建的当前值,以及读取该证据的未来值。归档的读数和已做出的决策会保留当时已知的信息。
Caveat 的用途,一页读懂:问题、一个可运行的示例,以及局限性。
体验 glowcap 讲解。 四种相似的蘑菇、一个信念、一项经历做出、受到质疑后又重新做出的信任决策,以及页面上所有内容背后的一个“为什么?”。规则和解释都写在 game/glowcap.cav 中;页面只负责渲染。
从页面顶部的 改变你所知道的内容 开始。单击一次做出决策,再单击一次了解新信息,然后查看发生了什么变化、决策为何重新开启,以及它保留了哪些原始理由。
Trail Rescue 是一项全新的完整机制:花费三个侦察令牌,权衡可能出错的报告,选择一条隧道,并在证据变化或过时时重新考虑。其需求和 24 个场景在实现前就已提交。Caveat 程序负责规则;浏览器页面展示其决策和冻结的解释。使用 npm run build、npm run serve 构建并运行,然后打开 http://127.0.0.1:4173/trail-rescue.html。
这项机制新增了状态限定说明查询:has_caveat(plan_basis, stale) 会检查已保存依据的实际理由,而 reopen route because caveated(plan_basis, stale) 会引用已过时的具体观察。日志现在会保留经过的时间和所选数值,恢复时则会检查它们与承诺和证据是否一致。详见实现记录。
新 Agent 编写程序: 六个全新上下文使用冻结的文档资料包编写了三个指定策略,没有获得私有测试的反馈。首轮提交中有两个通过了已登记语料库,六个最终提交则全部通过:最终源代码共包含 20,512 个事件,恢复操作共 4,788 次。四个首轮失败都暴露出数值边界限制说明不清的问题,现已补充文档。两个最终程序仍存在已知的时钟范围合约违规,但这些情况不在语料库范围内。研究报告记录了这些局限、每次修订和独立验证。
响应式源代码现在可以直接读取运行时的时钟,使用
elapsed():bind hud.elapsed = elapsed();。
它使用与定时限定说明和决策日志相同的时间,支持保存与恢复,也不再需要单独设置有界状态计时器。
四上下文后续研究使用此读取功能和更新后的指南,重复了两项时钟任务。首轮提交中有三个通过,四个最终提交则全部通过:事件分发共 13,704 次,恢复操作共 3,158 次。四个程序都直接使用了 elapsed(),没有单独设置状态时钟。首轮源代码中剩下的一个失败源于不受支持的注释语法,作者已修复。这是针对两项重复任务的证据,并非对一般可靠性的主张。
响应式运行时还提供了结构化调度结果。
dispatch_outcome 可区分作者定义的策略拒绝、无效输入、状态边界错误和执行预算耗尽。未分类的错误仍会导致致命失败。现有调度方法保持原有行为;新集成可以使用显式结果契约,测试事件被拒绝的原因。若宿主根据视图重新绘制,可使用 dispatch_view_outcome(开发套件中的 session.dispatchView):结果相同,只是用视图替代快照。
Caveat 将哪些内容纳入语言
这些机制也可以通过应用代码或库,在通用语言中实现并检查。Caveat 将它们作为语言和运行时功能一并提供;这里比较的是作者需要提供什么,而不是其他语言能够表达什么。
| Caveat | 在通用语言中 | |
|---|---|---|
| 解释 | bind label = "Could be a duskcap" when … because contradiction; 运行时会根据记录的依赖项检查所引用的证据和限定条件。 | 实现依赖项跟踪和引用检查,或使用提供这些功能的库。 |
| 计算中的限定条件 | qualified(1, taste, tasted_in_dark) 会在使用它的计算中携带证据和限定条件。 | 使用感知来源信息的值和操作,传播相同的信息。 |
| 后置限定条件 | qualify taste with taste_faded; 会限定基于 taste 构建的当前值,而较早的决策记录会保留其冻结的限定条件。 | 跟踪依赖项或在读取时解析限定条件,并冻结决策记录。 |
| 会记忆的决策 | commit、reopen 和决策系列修订会保留每个修订的依据,并将其变更发布到 decision_journal。 | 实现决策记录、冻结的依据和有序变更日志。 |
| 依据与溯源链 | 运行时会区分值的内容依据与更广泛的控制溯源链,并强制满足 grounds ⊆ lineage。 | 表示这两类依赖项,并在代码或库中强制执行它们之间的关系。 |
| 原子事件 | reject "already absorbed"; 会回滚事件对 Caveat 会话所做的更改。 | 使用事务、不可变状态或显式回滚,以原子方式发布更改。 |
引用检查只能确认被引用的依赖项已记录;它无法确认所提供的证据或作者撰写的解释文本是否属实。引用可能会遗漏依赖项,因此检查也无法确认其完整性。
证据:glowcap 基准测试
glowcap 基准测试分别使用 TypeScript 和 Caveat 实现了相同的游戏环节:
- 冻结并预先注册的场景套件;
- 十六项变更请求,其中十二项在任一实现针对这些回合发生更改之前已提交;
- 使用种子的差分模糊测试,用于比较已接受和已拒绝的事件、视图以及保存/恢复行为。 | 轮次 | Caveat 与 TypeScript 的变更成本、说明 | 结果 | | --- | --- | --- | | 1 · 首个版本 | 55 vs 57 (CR1–4) | 打平。薄弱环节成了这门语言的待办事项。 | | 3 · 盲测请求 | 97 vs 53 (CR5–8) | TypeScript 胜出。Caveat 的沿袭机制与设计者的意图相悖。 | | 5 · 语言变更后的重放 | 71 vs 110 (CR1–8) | Caveat 胜出,代码为 134 行,对比 164 行。编写时已知晓这些请求。 | | 6 · 盲测请求 | 92 vs 103 (CR9–12) | TypeScript 胜出。Caveat 首次运行通过了四个阶段中的两个,将再生次数限制在 8 次,并超出了 1 ms 的事件预算。 | | 6 · 语言变更后的重放 | 88 vs 103 (CR9–12 加上修正) | 变更成本较低;规模结果不一(168 vs 233 行,12,701 vs 11,586 字节)。首次运行通过了四个阶段中的三个。编写时已知晓这些请求。 | | 7 · 新作者、盲测请求、rc.11 | 186 vs 282 (CR13–16) | TypeScript 胜出。首次运行通过了四个阶段中的两个,对比之下另一方通过四个;回归更多;长时间游玩中,没有任何 Caveat 存档能在快速恢复的同时保持有界。两条决策规则都未满足。 |
第 7 轮留下了待办事项:让存档记住程序忘记的内容、对依据排序、将计时精确到时钟周期,以及适配器胶合代码。本轮结果不足以支持在 README、AGENTS、网站或其他文档中声称 Caveat 优于 TypeScript。
此前的失利促成了基于依据的解释、依据、reject、define、类型化参数、视图、延迟限定以及决策日志。
第 6 轮促成了增量求值、加载时观察顺序检查、接收证据的过程、可续期证据和定时 caveat,以及无需重放事件的存档/恢复。重放通过了全部 38 个场景,以及一项独立的 12 次生命再生检查,超过了旧版 8 次的上限。其证据仍设有明确限制:每个蘑菇最多 1,024 次生命;无限再生的请求仍未满足。首次尝试存档格式时超出了大小限制;这次失败的运行仍保留在结果中。
重放中的首次 2,000 序列模糊测试在约 730 万个事件中发现了 5 处不一致。JSON 解析改变了部分浮点值的最低有效位,导致定时行为跨过边界。精确往返解析修复了这些计时差异。最终审查随后发现,模糊测试通过对决策依据列表排序,掩盖了一个顺序错误。适配器现在使用日志中的有序证据,并由顺序敏感的比较器进行检查。该修正为原先的 86 行增加了两行变更。现在,捕获的 5 个序列和两次更严格的 2,000 序列模糊测试结果均一致:共 14,443,471 个模糊测试事件,差异为零。盲测轮次仍由 TypeScript 胜出;按照相同规则,这次重放并不能证明 Caveat 在采用方面胜出:规模结果不一,只有变更成本明确更低。
坦诚地说,Caveat 仍有以下成本:
- 对重放程序而言,每个事件加视图的中位耗时为 51.6 µs,而 TypeScript 为 2.5 µs;测量在模糊测试后进行;
- Caveat 策略、适配器和运行时经 gzip 压缩后为 482,716 字节(约 483 KB);
- 第 4 轮、第 5 轮以及第 6 轮的重放是在已知请求的情况下编写的;随后进行的第 7 轮是由新作者进行的盲测,结果由 TypeScript 胜出。
初探
event absorb target kind mushroom, sort in glowcap duskcap;
for mushroom as $m {
on absorb when $m_here and $m_consumed == 1 reject "already absorbed";
on absorb when $m_here and sort == sort.glowcap
set support = support + qualified(1, absorb_$m);
on absorb when $m_here and sort == sort.duskcap and committed(trust)
reopen trust because absorb_$m;
on tick when $m_tasted_at >= 0 and now - $m_tasted_at >= 60
qualify taste_$m with taste_faded;
bind $m.label = "Probably a glowcap" when $m_unknown and probably_safe because support;
bind $m.label = "Could be a duskcap — taste first" when $m_unknown and uncertain because contradiction;
};
阅读 Why Caveat,了解并排代码对比和 Caveatist 的工作方式。要编写第一个程序,请从创作指南开始。
MCP 服务
该软件包包含一个本地 MCP 服务 caveat-lang mcp,可将 Caveat 的编写操作作为工具提供给 Agent。它通过 stdio 运行,需要 Node 20 或更高版本,无需 Rust,并已列入 MCP Registry,名称为 io.github.WSattazahn/caveat-lang(server.json)。将其添加到 MCP 客户端的配置中:
{
"mcpServers": {
"caveat-language": {
"command": "npx",
"args": ["-y", "[email protected]", "mcp"]
}
}
}
| 工具 | 输入 | 结果 |
|---|---|---|
caveat_validate | source | 程序是否能加载以及声明的内容 |
caveat_check | source,可选 strict | 编写诊断信息和已抑制的警告 |
caveat_test | source、scenarios | 场景结果、不变量检查和检查警告 |
caveat_explain | source,可选 events | 决策、其确切依据、注意事项和历史记录 |
caveat_dependents | source、subject,可选 events | 对指定证据、流或注意事项存在依赖的内容 |
每个工具都使用内联源文本和提供的事件。该服务不提供文件、网络或持久会话工具,每次调用都会在全新的子进程中运行,时限为 10 秒。它支持 MCP 2026-07-28 和 2025-11-25 配置文件。MCP 设置与限制介绍了协议、结果格式、限制,以及已安装版本的配置。工具生成的报告并不授权执行外部操作,也不能验证其证据的真实性。
发布历史
1.0.1 修复了三种情况:通过守卫的已存记录传递的限定说明在撤回后仍被保留,或后续的 qualify 未能发现它(D012、D013 和 D014)。本次更新未增加任何语言、架构、操作、字段、CLI 标志、导出、MCP 工具或拒绝代码,并可恢复所有 1.0.0 存档。1.0.1 经验证的发布记录标明了经过精确测试的 npm 构件,并说明哪些程序能看到差异。
1.0.2 修复了两种情况:1.0.1 的修复遇到时间窗口或限制时出现问题:未告知离开操作,有证据被后续 qualify 添加到已存记录中(D016);通过已存记录读取的限定说明在其证据离开后无法再撤回(D018)。本次更新同样未增加任何内容,并可恢复所有 1.0.0 和 1.0.1 存档。1.0.2 经验证的发布记录说明了哪些程序能看到差异。
1.0.3 修复了一种情况:1.0.1 对 D014 的修复导致普通 qualify 添加到守卫已存记录上的限定说明在撤回后仍被保留(D020)。本次更新同样未增加任何内容,并可恢复所有 1.0.0、1.0.1 和 1.0.2 存档。1.0.3 经验证的发布记录说明了哪些程序能看到差异。
1.1.0 新增了语言形式(citing、retaining … because、中性和带注释的样例、reading(STREAM, N)、in_basis 等)、紧凑存档格式、可选择启用的 caveat check 警告、serve 选项和工具包辅助工具,以及一个拒绝代码。本次更新更改了一项行为,以兑现 Late Qualification 0.1 的承诺:后续的 qualify 现在会作用于通过决策读取的值(D015)。所有 1.0.x 存档均按记录时的状态恢复。1.1.0 经验证的发布记录列出了每项新增内容,并说明如何查找受到变更影响的程序。
rc.20 说明了各个 MCP 工具的使用时机、输入和结果。它还修复了对以下限定说明的人类可读解释:由决策的依据携带、保留在其冻结依据中,或仅存在于其更广泛的沿袭关系中。本次更新未更改 Rust 运行时、语言或存档格式。
rc.19 开始冻结 1.0 功能:未新增任何语言、架构、操作、字段、CLI 标志或导出。本次更新修复了恢复因限定说明而重新打开某项决策、随后又撤回该限定说明的会话的问题;rc.18 在此状态下写入的存档可在 rc.19 中恢复。
rc.18 新增了 unqualify,可撤回 qualify 对证据所有已持有实例添加的限定说明。撤回操作会被记录,而不会被抹除;决策会保留其依据。使用 unqualify 的程序所生成的存档无法在 rc.17 或更早版本中恢复;其他存档则可以。View 0.2 现在会按绑定的证据首次被观察到的顺序列出证据,而 explain 会指出观察到各项依据的事件和负载。
rc.17 引入了 View 0.2、存档中的源代码摘要以及集成入门套件(caveat-lang/starter);该摘要用于标识源代码,不会验证存档。rc.16 引入了符合条件的已退役历史离开、主机排空的存档,以及不可达撤回组的收集机制;请参阅历史记录集成指南。rc.15 引入了整数时钟、历史窗口,以及先检查每个程序的 caveat test。rc.14 修正了软件包的 MCP 服务名称,改为 io.github.WSattazahn/caveat-lang。rc.13 引入了接口 JSON 和 TypeScript 声明、更严格的恢复检查,并拒绝无效的 id_text 操作。
状态
CAVEAT 0.3 已可执行,而 0.4 游戏配置新增了可执行的知识要求、依赖证据的结果,以及由源文件定义的空间呈现。Rust 参考运行时会解析源文件、评估认知图谱、呈现 CAVEAT 地图,并在终端或 WebAssembly 浏览器会话中运行同一游戏程序。新功能详见 Draft 0.4。
其他可玩的示例包括 Light the Way:一款由全新响应式 CAVEAT 配置驱动的直接操控渡船救援游戏。移动、侦察、碰撞、损伤、得分和结果均由源规则定义。The Last Beacon 仍是独立的 3D 岛屿谜案,其可用决策、证据、保留的不确定性、九种结果、地点、摄像机和路径均定义在 game/the_last_beacon.cav 中。Moon Garden 仍是一款精简的移动优先谜案,同时提供 2D 呈现和独立的 Moon Garden 3D 呈现,两者由同一个 CAVEAT 会话驱动。较早的 The Door 场景仍是世界/动作压力测试。
CAVEAT 3D 0.2 现在会使用规范化的 Rust 动作运行时执行结果(Move、Inspect、Operate、Open、Observe、Stay),并将这些命令映射到语义地点/实体/符号呈现绑定。Moon Garden 不再需要常规的逐动作摄像机编排。详见 spec/caveat3d-0.2.md。剩下的图形问题是美术指导自动化:语义标识符现在可以驱动场景,但要实现出色的摄像机构图和素材,仍需编写呈现绑定。
Light the Way — 立即游玩
游玩 Light the Way。按住并拖动灯塔光束,或使用方向键。操控渡船绕过礁石,驶入绿色港湾。渡船继续移动时,将光束停留在当前标记上即可进行读数。风暴转向时,决定是手动修正旧计划,还是再花一秒钟进行侦察。损伤、采样进度和获救乘客会直接显示在场景中。可立即重试。无需下载,也无需阅读说明面板。
全新的响应式语言配置新增了有界数值状态、类型化事件、算术运算、有序条件规则和原子事件执行。相同的规则可以读取并更改 CAVEAT 的实际证据图谱。在游戏源文件中,发现礁石会记录证据、消耗资源调查相关的 caveat、重新开启初始航线承诺,并让渡船在已知危险附近减速。原始海图主张和相反证据都会保留在图谱中。
state boat_x = ferry.x min -9.5 max 13;
event tick dt min 0 max 0.1;
on tick when phase == 1 set boat_z = boat_z - boat_speed * dt;
响应式 0.2 扩展新增了可复用数值函数、求值后的呈现绑定、显式音效/视觉提示、由源文件声明的控制方式,以及由源文件声明的时钟。救援场景的画面切换、反馈、视觉状态和键盘操控现在都由 Caveat 程序定义。提示只会在其事件提交时发布;计算失败时,图谱变更和反馈会一并回滚。
响应式 0.3会在数值、算术运算、函数调用、比较和条件决策中传递证据与 caveat。使用派生值作出的承诺会自动保留其 caveat,并记录冻结的数值依据以及 relies_on 证据边。由源文件定义的横流观测和操控函数展示了这些语义;浏览器仍会使用普通渲染值。
crosscurrent 展示了这为何不仅对移动代码很重要:有依据的预测支持初始导航决策;相反的观测会重新开启该决策,并在保留未解决的限定说明的同时进行反向操舵。观测改变的是导航者的响应,而非物理洋流。两段证据历史都可供检查。保留 Caveat 的本质记录了不变量以及仍存在的 Rust/浏览器边界。
穿越过程中,洋流变化了两次。此前测得的操舵修正值会保持不变,直到新的样本支持修订计划。明亮的箭头显示表层水流;浅色箭头保留上一次读数,HUD 显示其时间跨度。重新勘察需要立即付出代价:移动中的渡船仍需操舵,同时必须让同一道光持续照在标记上。
Reactive 0.4 增加了有界文本表达式和条件表达式。标准函数 abs、min、max 和 clamp 已在 Caveat 源码中实现,取代了对应的 Rust 算法。源码函数还会格式化游戏时钟、数字和百分比;源码状态负责管理通知的生命周期和船体指示器。Rust 仍负责实现求值器和浏览器桥接。这是首个由源码定义的标准库,并非自托管编译器。
Reactive 0.5 增加了有界读数流和决策序列。每次 sample 都会创建一个独立的证据记录,即使测量数值重复也是如此。latest(flow) 会读取其经过限定的值;决策序列会在先前决策被明确重新开启后,记录新的冻结依据。旧记录仍可在快照和图关系中访问。游戏会在重复的天气变化中使用同一个采样过程和同一个导航序列,取代原先分别处理首次读数和风暴读数的实现。
同样的能力也应用于一个恒温器程序:冷、暖、冷读数会修订供暖指令,同时保留每个读数和未解决的校准限定说明。运行 cargo test --manifest-path runtime/Cargo.toml --test thermostat_history,即可测试其输入历史和回滚行为。这是通用语言功能的另一个独立源码使用者,解释器中不包含任何恒温器逻辑。
Reactive 0.6 通过 history_count、从零开始索引的 history_at 和 fold_history,让源码计算能够使用保留的历史记录。归约器是普通的纯 Caveat 函数:求和、计算范围或选择基于历史记录的策略,都不需要对应的 Rust 算法。结果会保留其中涉及的观测、限定说明和选择依赖项。索引无效、归约器出错或超出有界工作量时,都会回滚整个事件。恒温器会在源码中计算平均值/范围/趋势,而游戏会比较归档读数以报告测得的流向反转。这是有界历史计算,尚未支持任意集合或自托管。
Reactive 0.7 增加了可复用的副作用过程。proc 可以在多个源码事件间共享输入处理,或共享一系列观测与修订步骤。调用会冻结其数值参数和入口守卫,保留每个参数的所有限定信息,并在调用事件的原子事务中运行。游戏会共享键盘清理、按住输入的激活和瞄准移动;恒温器则通过源码过程记录读数并进行修订。Rust 提供有界调用和验证,而行为仍由 Caveat 源码定义。
Explanations 0.1 允许绑定声明它引用的内容:bind label.text = "…" when … because contradiction;。运行时会根据绑定的沿袭检查引用,因此解释可以省略依赖项,但绝不能引用值及其条件未读取过的证据或警示。完整沿袭仍可用于审计。
Explanations 0.2 将值的依据(其根据)与可能影响它的一切(其沿袭)区分开来。规则的守卫条件、跳过的规则、揭示证据的守卫条件,以及决策的前序项,都保留在沿袭中,但不会进入根据。引用读取根据,set x = e because c 会缩小根据的范围,而根据始终是沿袭的子集。
Reject 0.1 添加了 reject "MESSAGE":不被允许的事件会原子性地失败,并显示该消息,无需使用虚设状态或 require 技巧。
Define 0.1 添加了 define NAME = EXPRESSION;,用于定义一个基于状态和图的命名表达式;读取时会将其内联展开,包括在 for 块中针对每个成员的展开。
View 0.1 添加了 dispatch_view:它执行与 dispatch 相同的事务,但只返回宿主在事件后重新绘制所需的内容(绑定及其引用、提示、效果、承诺及其根据、关系),格式为紧凑 JSON。
Typed Parameters 0.1 允许事件按名称接收一个实体(target kind mushroom),或接收名称列表中的一个值(sort in glowcap duskcap)。宿主发送名称;源代码读取位置,并将 sort.duskcap 和 target.pool 作为常量。
Late Qualification 0.1 添加了 qualify EVIDENCE with CAVEAT:事后得知的警示会传递给所有基于该证据构建的当前值,而已作出的决策仍保留其作出时依据的内容。
Decision Journal 0.1 按顺序发布每项承诺和重新开放记录,并按观察顺序列出其所依据的证据。
Observation Order 0.1 会在程序加载时拒绝这样的规则:它用证据限定一个值,而这些证据只能由同一事件中的后续规则揭示;这种用法必然失败。可能在某些调度中成功的用法,则留给运行时处理。
Procedure Symbols 0.1 允许过程按名称接收证据、主张、警示、读取流或决策序列(proc learn(e evidence, sort)),从而让观察事物的各种方式共用一套规则。程序加载时,每次调用都会根据传入的名称进行特化。
Identifiers 0.1 允许事件携带程序在运行时首次获知的文本,例如 commit SHA(event pushed commit id;)。程序会为每段不同的文本获取一个数字句柄,id_text 可再次显示该文本。
Withdrawal 0.1 会记录某项观察不再受到背书(withdraw latest(checks) because recheck;)。不会删除任何内容:决策保留其作出时依据的内容,当前值和后续读取会带有 withdrawn 警示,而 rests_on_withdrawn(D) 允许程序判断撤回对某项决策意味着什么。
Permission 0.1 会记录是什么授权了某项决策,与该决策所依据的内容分开记录(commit merge … permitted by latest(approvals) for head;)。如果授权缺失、已撤回或不匹配,提交会被拒绝为 policy/not_permitted;冻结记录会说明是哪项授权许可了哪个值。
Reopening Triggers 0.1 允许决策序列声明哪些读数会重新开启它(decisions merge limit 8 reopened by pushes, checks opposing ready;),无需在每个此类读数之后手写重新开启规则。重新开启的行为完全由作者编写,并在读取该读数时执行。
Check 0.1 提供 caveat check:针对值得再次审视的模式给出建议性警告,例如多个事件中重复出现、可由同一过程共享的规则,或基于不会触发重新开启的读数作出的决策。警告并不代表已证实存在故障;# caveat check: allow CODE 用于记录有意采用的模式。套件的单页参考简要介绍了该语言,完整示例则通过一个程序演示每条命令,测试也会检查其中的输出。
Renewal 0.1 为事件创建的证据赋予身份:renewable taste_cave limit 256; 和 renew taste_cave 会让这个名称表示一个新的、尚未观察到的实例,同时保留早先实例所指的对象。qualify taste_cave with taste_faded after 60 会按照该实例自己的时钟使其淡出,而 carries(taste_cave, taste_faded) 用于查询它是否已淡出。
Save 0.1 可保存会话并在不重放事件的情况下恢复会话:WebReactiveSession.save() 和 WebReactiveSession.restore(source, saved)。恢复的开销等同于加载的开销加上存档大小。恢复时会验证存档中的名称、值和历史记录;变更测试会检查遭篡改的存档是否会被拒绝,或能否在不崩溃的情况下继续运行。
Incremental Evaluation 0.1 让事件的开销与其触及的内容相匹配:只有绑定所读取的内容发生变化时,才会重新计算该绑定;事务只会复制其效果会写入的内容。第 6 轮中,包含 32 个实体的程序每个事件耗时从 1.1 ms 降至 0.16 ms,结果保持一致;测试套件会在每个事件之后将其与完整求值进行核对。
水流时间和累积降雨现在也由 Caveat 状态提供。由源代码定义的 wrap 函数会将水流限制在边界内;渲染器将这些值映射到现有的波浪着色器和带种子的雨水几何体上。暂停或重放会话时,会保留相应的天气状态。
浏览器会将输入和经过的时间发送给通用的 WebReactiveSession,然后绘制其快照。它不会计算渡轮的移动、碰撞、受损情况、航线规则或救援结果。Rust 实现该语言的解释器;游戏专属规则则由 Caveat 实现。设计说明介绍了控制方式以及源代码、运行时和渲染器之间的边界。
键盘策略也由 Caveat 实现:源代码声明的物理按键控制会分别保留按下和释放状态、合并别名和方向相反的按键,并在源代码时钟周期内控制移动。浏览器会转发这些输入信息。仅修改源代码中的映射即可改变游戏控制方式;观察、检查和重新开启仍遵循相同的限定事件规则。
通过 Rust 和 WebAssembly,可以使用源代码库 API调用纯 Caveat 函数。The Door 的移动时序和转向策略现已写入其 Caveat 源代码;The Last Beacon 的反馈分类和文案也使用源代码函数。两个宿主共用同一个编译后的求值器。完整程序验证和宿主事务边界仍保持显式定义。
对于无头创作,caveat-reactive validate 可检查响应式程序,caveat-reactive replay 则使用带限定信息的快照执行 JSONL 事件历史。创作指南包含命令和恒温器输入样例。开发见解将已演示的行为与有关更广泛用途和 AI 采用情况的假设区分开来。
Slime glow ability policy 是一个小型主机集成消费者:报告蘑菇吸收后会生成一条符合条件的学习回执,而普通能力开关会保留这一依据,不会按输入累积历史记录。发光控制需要单独经过主机验证的渲染器能力;如果没有该能力,源代码只会报告发现蘑菇,不会声称产生了光亮。原生测试和真实 WebAssembly 测试涵盖了 10,001 次就绪状态切换、早期发现、重复吸收、重置以及仅源代码层面的策略变化。Vessel 的世界接触、库存事务和可见发光仍由主机负责。
The Last Beacon — 故事实验
在风暴笼罩的 Saint Orin,三十二名渡轮乘客正驶向一座即将失灵的灯塔。用三个值守时段调查不确定的证据、尝试临时计划,在现实与预期不符时重新审视计划,并在修复灯塔、派出岛上领航员,或让渡轮停泊在近海等待天明之间作出选择。六次互动会产生 324 条合法决策序列,并通向九种结局,分布在三个最终目的地。先前的调查会解锁针对性的准备工作;完成这些准备工作后,同一项最终命令会产生不同效果。参见游戏设计与行动契约。
这款游戏还拓展了语言运行时。通用 Rust GameSession 和 WebAssembly WebGameSession 会原子地应用世界行动与认知效果,公开玩家实际决策所到达的图,并通过重放经过源代码校验的选择来恢复存档。解析器现在支持带引号的分号、转义文本和 Unicode 文本、行注释,以及错误中的源代码位置。这些能力适用于任何 CAVEAT 程序;参见游戏会话规范和源文本规范。
以下是实际的游戏源代码语句:
require bridge_reserve observed reserve_charge;
resolve relight_beacon as beacon_guided when observed measured_pulses;
resolve relight_beacon as beacon_limited when observed hot_cable;
resolve relight_beacon as beacon_limited when observed split_beam;
resolve relight_beacon as beacon_unverified otherwise;
运行时会在执行行动前检查已到达的证据图。已声明但尚未发现的证据不能解锁行动;相互矛盾的证据仍会被记录。浏览器会接收 CAVEAT 提供的可用选项、阻止原因和已选结局,并提供可复用的图形与控件。呈现声明也会布置世界并组合其视图,而无需更改 JavaScript。
游玩之前的故事。这个托管版本可直接在浏览器中打开;下载 HTML 文件并非必需。
构建并游玩
安装 rustup 和 Node.js 20 或更高版本后,在仓库根目录运行。rust-toolchain.toml 固定了编译器版本,rustup 首次使用时会安装该版本及 WebAssembly 目标:
cargo install wasm-bindgen-cli --version 0.2.104 --locked
npm ci
npm run build
npm run serve
构建还会生成 dist/pkg-reactive/:其中包含相同的运行时,但不含顺序、图形和 3D 会话,适用于仅运行响应式程序的宿主(cargo build --no-default-features)。体积约小五分之一。
打开本地体验《Light the Way》。较早的故事实验仍可使用。构建会将 Rust 运行时编译为 WebAssembly,并将游戏源文件、浏览器资源和 Three.js 的本地副本组装到 dist/。现有游戏仍包含在同一构建中。
无需浏览器或 JavaScript,即可在终端中游玩较早的《Last Beacon》故事:
cargo run --manifest-path runtime/Cargo.toml --bin caveat -- --game game/the_last_beacon.cav
如需可选的离线副本,请在构建后运行 npm run package:game。在完整的现代浏览器中打开 dist/Light-the-Way.html(dist/The-Last-Beacon.html 包含较早的故事):该文件嵌入了实际的 CAVEAT WebAssembly 运行时、故事和图形,无需服务器或网络连接即可运行。某些文件预览应用会禁用脚本或模块导入;这些预览无法运行游戏。启动屏幕现已包含浏览器使用说明、重试操作,以及针对导入失败或卡住的超时设置。在较早的故事游戏中,保存在设备本地的存档会保留你的守望进度。使用按钮或按键 1–3 进行选择,按 J 打开日志,按 M 切换环境音。
工作流说明介绍了视频的视觉检查和测试循环如何为此实现提供参考。
验证
cargo test --manifest-path runtime/Cargo.toml
cargo clippy --manifest-path runtime/Cargo.toml --all-targets -- -D warnings
npx playwright install chromium
npm run test:beacon
npm run test:rescue
npm run test:slime-glow
响应式运行时测试会检查原子回滚和格式错误的输入;救援模拟则会验证完整穿越、伤害、时机,以及观察到的证据对运动的直接影响。浏览器救援测试使用真实的鼠标、键盘和触摸输入。故事测试会穷尽所有合法的 Beacon 路径,检查对不可用操作的拒绝、调查成本、保留的限定说明、重新开启、实际目的地、依赖证据的结果,以及存档恢复。浏览器测试会启动自己的本地服务器,测试 WebAssembly 游戏及其呈现效果。请先运行 npm run build;测试不需要单独运行 npm run serve 进程。运行 npm run package:game 后,npm run test:launch 还会测试导入被阻止、模块卡住和脚本被禁用的预览。npm run test:slime-glow 无需浏览器:它会直接驱动已安装的 WebAssembly 运行时,并检查宿主集成策略中的有界切换、已验证的渲染器能力、符合条件的逃逸、原子失败和格式错误的输入。它会在组装 dist/ 的同一个持续集成任务中运行。
仓库结构
spec/— 版本化语言规范runtime/— 参考运行时runtime/prelude.cav— 以源代码定义的标准数学和显示函数tests/— 标准语义测试examples/— CAVEAT 示例程序game/— 可游玩的 CAVEAT 场景,包括《The Last Beacon》、《Moon Garden》和《The Door》web/— 浏览器呈现和通用世界渲染scripts/— 可复现的浏览器构建、本地服务器和游戏验证
不要通过重新定义 CAVEAT 来挽救它。如果计算模型坍缩为某种现有范式,请记录结果。
许可证
Caveat 的代码和文档采用 MIT 许可证。
第三方组件遵循各自的许可证:编译进 WebAssembly 运行时的 Rust crate
及其许可声明列于
THIRD_PARTY_NOTICES.md;网站随附的 three.js 副本
则附带其许可证文件 vendor/THREE-LICENSE.txt。
文化
Caveatism 是围绕机械算命先生 Mr. Caveat 发展起来的哲学;他总会附带一条 caveat。它位于 caveatism/,属于文化,而非语言契约。Archive 和 Atlas 是其文本,而正典则将 Archive 保留为包含场景的 Caveat 程序。

评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。