关于 INVARA
INVARA 根据可观察证据检查已声明的工程约束,判定过程不使用模型。它面向使用支持命令行的编码 Agent 的开发者,可对变更进行范围明确的检查;它不证明软件正确性。
主要功能
- 01在开始工作前封存约束契约
- 02依据文件摘要和命令结果判定约束
- 03记录 PASS、BLOCK 等判定
- 04重放判定并查看仅追加的历史
- 05验证变更前后的行为
- 06逐个单元管理修复
适用场景
- 01在重构期间保护指定文件
- 02变更后检查已声明的条件
- 03比较迁移前后的行为
- 04仅在检查通过时保留修复单元
MCP 相关
本地 MCP 服务提供六个工具,用于封存任务、判定任务、列出和记录判定、重建哈希链及重放判定。它会运行封存契约中指定的检查;判定流程不包含模型。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
6收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| db | string | 否 | 判定数据库。默认为 .runtime/verify.db。 |
| root | string | 否 | 代码库根目录。默认为工作目录。 |
| commit | boolean | 否 | 将判定追加到哈希链。默认值为 false(试运行)。 |
| task_id | string | 是 | 要评判的已封存任务。 |
| timeout_s | integer | 否 | 每项检查的超时时间(秒)。默认值:900。 |
详细介绍
INVARA
面向 AI 构建软件的工程不变量。
INVARA 可与 Claude Code、Codex 以及任何能使用 shell 的编码 Agent 配合使用。它会根据可观察证据验证已声明的约束;但不会证明软件正确。
seal before work -> agent does the work -> judge
|
PASS / BLOCK / UNVERIFIABLE / HUMAN_REVIEW
请先选择符合你环境的方式:
- **Claude Code:**使用
/plugin marketplace add Jujitae/invara添加插件市场,然后运行/plugin install invara,安装打包的编辑器/插件体验。 - **Codex 或其他支持 shell 的 Agent:**运行
uvx --from invara==0.3.0 invara list,或运行python -m pip install invara==0.3.0进行持久安装。 - **告知你的 Agent:**使用 AI Agent 快速入门中的复制粘贴说明,然后保留它收到的原始判定结果。
第一个结果是判定结果,而不是 Agent 的自我报告。PASS 表示所有已声明的检查都按承诺返回结果,且受保护路径保持不变。BLOCK、UNVERIFIABLE 和 HUMAN_REVIEW 就是它们本来的含义;重新解释也不会让它们变成成功。
当前公开版本:0.3.0。状态:Alpha。INVARA Free 公开发行;INVARA Pro 是单独付费的产品。INVARA 不是自主授权机制,也不是企业合规控制。
0.3.0 版本中的转换保障,Gen 1
现在有两种本地 CLI 工作流,可以检查重构或迁移是否符合已声明的行为范围:
invara assure会根据 Equivalence Manifest 比较已有的变更前/变更后版本,并可搜索最小化反例。invara repair会逐个单元管理修复,只有在已声明的检查通过后才保留该单元。
Gen 1 只衡量清单中声明的输入、观测结果、策略和声明。PASS 仅适用于该范围;它不是对正确性、安全性或软件没有缺陷的普遍证明。这些工作流会以用户的权限运行用户指定的命令。它们不会发起出站网络请求;HTTP 探测只能连接到清单为本次会话启动的本地回环服务。
请从 CLI 指南和清单指南开始。合成示例和展示报告位于 fixtures/ 和 docs/transformation-assurance/samples/ 下。
它不是什么
请在安装前阅读本节。本节刻意写得很简短;上文承诺中起关键作用的词是可验证,而不是正确。
INVARA 不会证明软件正确。 它会根据可观察证据验证已声明的约束。
具体来说:
- **它不会检查你的代码库。**它从不判断代码是否优秀、架构是否站得住脚,或测试是否恰当。如果你在垃圾之上再盖一层楼,而这层楼符合已声明的规范,判定结果就是
PASS。 - **它不会查找缺陷。**运行测试套件的完成检查,能力仅取决于测试套件本身。INVARA 会报告退出代码;它不会评价测试覆盖率。
- **它不会决定本应作出什么承诺。**契约由你编写。薄弱的契约只会得到薄弱的
PASS,而且契约会原样存储,任何人都能看出它有多薄弱。 - **它不是沙箱。**完成检查就是命令,而且会以你的权限运行。没有读过的契约不要封存。
- 它不会评判意图。
intent是散文;没有任何机制会检查工作是否符合意图。真正起约束作用的是检查项。 - **它不是 AI 代码生成器,也不是 LLM 代码审查机器人。**判定流程中完全没有模型。
其狭义主张,也就是机器实际会做的事:
它会独立判断这项变更是否兑现了自身作出的承诺。
CLI 优先的结论,详述如下
无需配置。无需 API 密钥、服务或账户。需要 Python 3.12+ 和 uv。
uvx --from invara==0.3.0 invara list
或者,若要保留安装:
python -m pip install invara==0.3.0
该软件包声明了 零个运行时依赖项,因此这里只会使用标准库。固定版本的安装会报告已安装的 INVARA 版本,而 pip list 则显示没有额外的运行时软件包。
从代码库检出版本使用的是同一个程序,但需先安装——源代码位于 src/ 下,因此在代码库根目录直接运行 python -m invara 会找不到可运行的内容:
pip install -e .
python -m invara list
发布候选版本发布前的验证
打包的插件和可分发的软件包必须提供相同的六个 MCP 工具。维护者发布新软件包版本前,必须先构建其 wheel,并运行代码库提供的干净环境验证。该验证会创建全新的虚拟环境,在不使用软件包索引的情况下仅安装该 wheel,通过 stdio 启动 MCP 服务,核实工具列表完全一致,然后执行密封、评估、列出、记录日志、重建链并重放判定。
python -m pip wheel --no-deps . --wheel-dir .runtime/invara-dist
python scripts/verify_fresh_install.py --wheel-dir .runtime/invara-dist --plugin-root plugin
这是发布候选版本验证,不是发布命令。对于每个候选拉取请求,CI 工作流都会分别在 Windows 和 Ubuntu 上独立运行该验证。
1. 在开始工作 之前 写好契约
在你将要修改的代码库旁创建 task.json:
{
"task_id": "2026-08-17-tidy-the-parser",
"intent": "Speed up the CSV parser without changing what it accepts",
"constraints": [
{
"kind": "paths_unchanged",
"paths": ["tests/test_parser.py"],
"reason": "a speedup that edits its own test is not a speedup"
}
],
"done_when": [
{
"id": "suite",
"command": ["python", "-m", "pytest", "-q"],
"expect_exit": 0,
"reason": "the whole suite"
}
]
}
invara seal task.json
密封操作会在此刻获取受保护路径的摘要,此时还没人知道判定结果会是什么。这个顺序就是全部保障。
2. 开展工作。
3. 评估
invara judge 2026-08-17-tidy-the-parser # dry run
invara judge 2026-08-17-tidy-the-parser --commit # record it
BLOCK: 1 protected path(s) changed: tests/test_parser.py: changed
(a speedup that edits its own test is not a speedup)
decided by: constraint_breaks
这是首次判定。以下内容都是细节。
四种判定结果
| 判定 | 含义 | 退出码 |
|---|---|---|
BLOCK | 受保护路径发生变化,或完成检查失败 | 1 |
UNVERIFIABLE | 检查完全无法运行。未检查不等于通过 | 2 |
HUMAN_REVIEW | 机器检查通过;有事项被标记为需要人工审查 | 0 |
PASS | 每项检查都返回了预期结果,所有受保护路径的字节内容完全一致 | 0 |
违反约束的情况优先级最高。一次运行若触碰了它承诺不会触碰的内容,就不能算部分合格。
BLOCK 是一个词涵盖两条规则——受保护路径发生变化,与检查结果不符,并非同一种指控。因此,判定结果还会记录是哪条规则作出了决定,并根据所依据的证据命名(constraint_breaks、failed、unrunnable、needs_human、passed);judge 和 log 会将其打印出来。在此功能出现之前记录的判定结果没有此字段,也不会事后补上。
密封操作宁可拒绝,也不勉强接受
seal 不会写入无法判定工作是否失败的契约。它会拒绝缺少完成条件的任务、没有对应检查命令的条件、没有受保护路径的契约(“允许更改任何内容的任务,就谈不上遵守任何要求”)、重复的检查 ID、不存在的受保护路径,以及——最重要的一种情况——所有条件都交由人工判断的契约。
最后这一条就是它并非走形式盖章的原因:如果唯一的证据只是某个人说“是”,那就不存在契约。
其他命令
invara init print a task.json template for this repository
invara list sealed tasks and their latest verdict
invara log <task_id> every verdict this task has ever had
invara show <task_id> the contract, exactly as sealed
invara replay <task_id> recompute a recorded verdict and compare it
invara chain rebuild both hash chains
invara replay 用来回答“这个判定结果能否复现?”——它会根据当时存储的观察结果重新计算。对于不支持重放时记录的判定结果,该命令会以 no_current_stored 拒绝,而不是进行猜测。
判定结果存放在 .runtime/verify.db 中(使用 --db 更改位置)。契约只密封一次,但可以多次评估;历史记录采用仅追加方式,并以链式结构关联。
在编辑器中
这个产品面向的买家不会打开终端。因此,同一个软件包也会以 Claude Code 插件的形式提供自包含的 MCP 服务:
/plugin marketplace add Jujitae/invara
/plugin install invara
该插件打包了 INVARA 源码,并通过 python -m 运行,只需要 Python 3.12+——无需 uv、无需网络,也没有任何运行时依赖。如果服务无法启动,/invara:doctor 会诊断环境,而不会假设 Python 已经安装——已知的无提示故障情况是 Windows 未安装 Python:Microsoft Store 的 python 别名会启动后立即退出,退出代码为 9009,stderr 只有 7 个字节(Python );在此之前,任何 INVARA 代码都还没有运行。插件写入的配置如下:
{
"mcpServers": {
"invara": {
"type": "stdio",
"command": "python",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/src"
},
"args": ["-m", "invara.mcp"]
}
}
}
六个工具——invara_seal、invara_judge、invara_list、invara_log、invara_chain、invara_replay。它们就是上面的命令,不会改变判定结果的含义:判定结果仍根据文件摘要和退出代码计算,运行的检查仍是已封存的契约中列出的检查,并且仍然没有任何字段可供 Agent 声称工作已完成。Agent 可以在这里请求判定结果,但不能给出判定结果。
这里的 invara 是一个本地标签——你喜欢叫什么都行。服务的实际标识是 io.github.Jujitae/invara,它在 MCP 注册表中的登记名称就是这个,客户端也会通过它在注册表中找到该服务。它不能用作上面的键:claude mcp add 会提示 Names can only contain letters, numbers, hyphens, and underscores。
这不是沙箱,也不会让它变成沙箱。invara_seal 接收一个任务文件,该文件列出命令,而判定操作会运行这些命令。能够编写任务文件的 Agent 可以让这些命令运行——这并不比它现有的 shell 权限更多,但在这里说清楚,总比之后才发现要好。
确定性
同一仓库状态、同一契约、同一环境 → 同一判定结果。判定结果是文件摘要和命令退出代码的函数,不受其他因素影响;决策过程中没有模型,也没有时钟。
以下数据来自实测,而非断言,日期为 2026-08-17:契约
2026-08-17-route-discovery 在未更改的代码树上间隔 4 分钟判定了两次——每次均有 7 项检查,其中包括一个包含 2,021 个测试的测试套件。两次运行返回的状态和原因字符串完全相同,两条记录也都在链中:
$ invara log 2026-08-17-route-discovery
2026-08-17 09:17 UTC PASS
7 check(s) passed and 6 protected path(s) are unchanged
2026-08-17 09:21 UTC PASS
7 check(s) passed and 6 protected path(s) are unchanged
在相信它对我们的判断之前,先用你自己的契约亲自运行一次。
这里真正起作用的是 环境 一词。请看下面第一个失败案例:某契约在本地通过、在 CI 中失败,并非因为不确定性——而是因为环境不同,INVARA 对两种环境都做出了正确报告。如果你希望判定结果可复现,就要让完成命令也可复现。
失败案例
这些都是真实经历,来自构建和使用此工具的过程。之所以列出这些案例,是因为一个只展示成功结果的验证工具,恰恰要求你相信它明明告诉你不要轻信的东西。
环境污染。 一份契约在编写它的机器上通过了验证,却在 CI 中失败。工作区是干净的,环境却不是。Shell 中设置了 PYTHONIOENCODING,子进程继承了它,完成命令也正是因此才能正常工作。现在,验证运行会使用 env -u PYTHONIOENCODING。工作区干净,不代表环境干净。
自毁的封印。 新克隆的仓库在检出时把一个已封印的本体文件改写成了 CRLF,导致其 SHA-256 不再匹配。这个唯一职责就是证明一切未变的文件,没能通过自己的封印验证。修复是在 .gitattributes 中进行的,而不是修改摘要规则——摘要是正确的。
第一次判定是 UNVERIFIABLE,而且判得没错。 找不到完成命令,因为 subprocess 不会用 cwd 来解析可执行文件。判定没错,但工具毫无用处。这两件事都被记录了下来;其中只有一件是 bug。
它没能通过构建它的任务。 INVARA 封存的第一个契约,就是构建 INVARA 这项任务。它先返回 UNVERIFIABLE,然后返回 PASS,接着又返回 PASS。这三个结果仍保存在 .runtime/verify.db 中,运行 invara log 就能看到。
它的由来
其形态借鉴自同一私有仓库中的一个同系列引擎:在证据出现之前封存契约,拒绝创建任何无法销毁的东西,只对观察到的记录评分,并将结果串联起来。把“对世界的声明”改成“Agent 的工作”,同一套机制就适用了。
INVARA 是在一个私有工作仓库(WIE)中构建并用于自我验证的;有关这对本项目源代码意味着什么,请参阅 PROVENANCE.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。