关于 judgment-pack
judgment-pack 是用于验证 Judgment Pack Specification 文档的厂商中立参考运行时,面向构建和测试决策包的团队。它还提供实验性评估与一致性测试接口,并明确结果不会授权行动或证明事实。
主要功能
- 01按声明的 JPS 版本验证文档
- 02评估决策包与事实数据
- 03运行内置评估语料库
- 04测试包、用例与图结构
- 05通过 stdio MCP 提供离线操作
适用场景
- 01分发前验证决策包
- 02依据输入事实评估决策
- 03使用语料库测试决策包行为
- 04让 MCP 客户端离线验证文档
MCP 相关
stdio MCP 服务提供与命令行工具相同的离线操作,包括文档验证及实验性评估和测试工具。MCP 客户端可调用这些操作,但处置结果不代表行动授权。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e JPACK_CONFIG ghcr.io/judgment-pack/judgment-pack:0.39.0JPACK_CONFIGPath to a jpack.json project configuration (ADR-0012). Optional: without it the server reads jpack.json from its launch directory (/project in this image; mount a project there), and a project that does not use the convention still validates and evaluates pack documents passed over the wire.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/judgment-pack/judgment-pack:0.39.0stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
原文在翻译后有更新,译文可能不是最新。
judgment-pack
状态:1.0 之前
只有在本仓库的 GitHub Releases 页面上附有
checksums.txt的已标记二进制文件,才是官方版本。 开发检出版本可能会暂时嵌入尚未发布的 JPS 快照,但发布工作流会拒绝此类版本。
judgment-pack 是 Judgment Pack 规范(JPS)的供应商中立参考运行时。它是参考实现,但不是唯一有效的实现:规范性规范、架构和一致性语料库由独立的
judgment-pack-spec 仓库维护;对独立实现的评判依据,是其声称所属一致性类别的完整规范性要求,而不是此运行时。要支持此类声明,必须提供针对其所指确切版本发布的语料库结果作为证据;但这些结果并非该声明的详尽证据(§3.4.1)。
运行时验证文档。它不会获取源、授权操作,也不会确立事实、组织权威、安全性或运行适用性。它捆绑了两个规范版本:0.1.0-draft 和 0.2.0-draft,并根据文档声明的确切版本验证文档;0.1.0-draft 仅定义载体、结构和语义层面的文档一致性,而 0.2.0-draft 不改变文档格式的任何部分。
根据 ADR-0007,同一个评估器会对每个项目应用规范 §§7–8 中的解析模型,十种入口均使用它:jpack experimental evaluate 和 evaluate-corpus、项目遍历命令 jpack packs test、图操作命令
jpack experimental graph evaluate 和 graph test、版本比较命令
jpack experimental compare,以及 experimental_evaluate、
experimental_test_packs、experimental_test_cases 和 experimental_test_graphs MCP 工具。experimental 命名空间表示稳定性声明:此类入口可能会更改或移除,且不提供兼容性承诺。这并非关于一致性的声明。该评估器根据
ADR-0010 和
ADR-0011,实现 Core 0.2.0-draft 新增的评估器一致性类别:§8.2 输入预检、§8.3 可移植处置及其 RFC 8785 字节一致性、§8.4 错误类别及其固定优先级,以及 §10 的限制。只有声明 specVersion
0.2.0-draft 的包才会被评估:§11 要求声明值必须完全匹配,并要求未编辑的 0.1.0-draft 包在实现声称支持此草案后进行重新声明——只需修改一处,即 specVersion 字符串,文档的其他部分不得更改。任何其他版本都会在 preflight 阶段被拒绝,并标记为 pack-not-conformant。
本运行时的一致性声明完整且仅见于
CONFORMANCE.md。 JPS §3.4.1 规定了此类声明唯一允许采用的完整形式——类别、一个确切的 specVersion、语料库版本、取得的结果,以及声明中必须明确写出该语料库版本的每一行均已通过。因此,本 README 不陈述该声明的任何部分,其他入口也同样不会陈述:部分重述会构成 §3.4.1 禁止的部分声明。请阅读该文件,了解声明、版本范围、证据以及声明未涵盖的所有事项,包括关于某个包、其事实或根据某项处置采取行动是否明智的任何内容(§3.5)。
jpack experimental evaluate-corpus 会运行捆绑的评估语料库并报告其中的各行结果——这是 §3.4.1 要求此类别声明提供的证据,但明确不构成该声明的详尽证据;请参阅 CONFORMANCE.md。
该命令还提供一个可选开关 --rfc0008-quantifiers,根据 ADR-0009,它属于草案 RFC 原型:该开关允许使用规范 RFC 0008(草案)提出的集合量词 exists、every 和 uniform。这些运算符不属于任何已发布的 JPS 版本。使用其中任何一个的 pack 在 JPS 0.1.0-draft 下都无效,spec validate 会拒绝它,未启用此开关的求值器也会拒绝它;而启用此开关后生成的每个成功求值载荷都会通过 draftPrototype 成员明确标示这一点——拒绝操作属于运行错误,不会携带该成员。该开关仅适用于 CLI;MCP 工具不提供此开关。
第二个可选开关 --rfc0016-outcome-values 依据 ADR-0039,同样属于草案 RFC 原型。它允许使用规范 RFC 0016(草案)提出的值声明:一个结果会在 org.judgmentpack.outcome-values 下声明命名值,每个值可以是常量,也可以是某个事实的副本;该结果的处置会通过 value 成员携带这些值。该成员属于草案内容,不属于 §8.3 中的任何成员。如果某个已声明的值无法解析,则不会提供该结果,结果将为 unresolved,原因是 unknown。由于该名称已被保留,携带值声明的 pack 在任何已发布的 JPS 版本下都无效,spec validate 会拒绝它,未启用此开关的求值器也会拒绝它。从事实中提取的值是该事实的副本,不会经过验证。两个开关不能同时使用;此开关也仅适用于 CLI。
命令二进制文件名为 jpack。项目、仓库和发行版归档仍使用 judgment-pack 名称;其中包含的可执行文件名为 jpack。
已实现的命令
jpack version
jpack artifact version --base <x.y.z> [--candidate <x.y.z>]
jpack dialect contract
jpack dialect init [--dialect-version 2|3]
jpack dialect canonicalize <dialect-or->
jpack dialect digest <dialect-or->
jpack dialect validate <dialect-or->
jpack dialect schema [--dialect-version 2|3]
jpack dialect reference
jpack dialect check <dialect-or-> --pack <pack-or->
jpack spec validate <pack-or->
jpack spec test-conformance [suite] [--strict]
jpack spec schema <spec-version>
jpack spec examples [name] [--spec-version V]
jpack packs list (jpack.json project convention; ADR-0012, not part of the spec)
jpack packs validate [--id X]
jpack packs test [--id X] [--require-matrix] (EXPERIMENTAL SURFACE; claim: CONFORMANCE.md)
jpack packs suggest [--id X] [--base ROW] [--write F|-] [--max N] [--include-hugs] (candidate row INPUTS, never rows; ADR-0024)
jpack packs lock (declare the current documents as the project's reviewed set; ADR-0019)
jpack packs verify (check the project against that reviewed set)
jpack packs lint [--producers M] (every consulted pointer has a producer; ADR-0022)
jpack packs schema
jpack mcp
jpack experimental evaluate <pack-or-> (EXPERIMENTAL SURFACE; claim: CONFORMANCE.md)
jpack experimental evaluate --pack-id X (EXPERIMENTAL SURFACE; resolves one decision id through jpack.json)
jpack experimental evaluate <pack-or-> --rfc0008-quantifiers (DRAFT-RFC PROTOTYPE; not an input the class defines)
jpack experimental evaluate <pack-or-> --rfc0016-outcome-values (DRAFT-RFC PROTOTYPE; a pack that declares values is not an input the class defines)
jpack experimental evaluate-corpus (EXPERIMENTAL SURFACE; corpus results, the evidence §3.4.1 requires)
jpack experimental compare <old-pack> <new-pack> --inputs <file> (EXPERIMENTAL SURFACE; the inputs two versions decide differently; ADR-0045)
jpack experimental graph list (EXPERIMENTAL: the configured graphs, resolved; ADR-0029)
jpack experimental graph validate <graph-or-> (EXPERIMENTAL composition prototype; spec RFC 0002, Draft; ADR-0015)
jpack experimental graph evaluate <graph-or-> [--inputs <file-or->] [--rehearsal] (EXPERIMENTAL SURFACE; claim: CONFORMANCE.md)
jpack experimental graph explain <graph-or-> (the evaluation plan; nothing is evaluated)
jpack experimental graph test <graph-or-> --rows <file-or-> (EXPERIMENTAL SURFACE; claim: CONFORMANCE.md)
jpack experimental graph schema
jpack experimental policy contract
jpack experimental policy init --kind policy --format-version 0.0.2 --id <id> --version <artifact-version>
jpack experimental policy schema --kind policy --format-version 0.0.2
jpack experimental policy canonicalize <document-or->
jpack experimental policy digest <document-or->
jpack experimental policy validate <document-or->
jpack experimental policy check <document-or-> --materials <materials-or->
pack 参数与 --pack-id 不能同时使用:只能指定一个 pack 和一个来源,同时提供两者或两者都不提供都属于调用错误,而不是优先级规则。--pack-id 与其他读取配置的命令一样,会遵循 --config 和 JPACK_CONFIG。
命名空间是 jpack spec,而非 jpack jps。JPS 仍是该规范的名称,也是其临时诊断代码的前缀。
mcp 命令会通过 stdio 向 Model Context Protocol 客户端提供相同的离线操作,因此 Agent 可以通过工具调用验证文档;各客户端的设置说明见 docs/mcp-clients.md,Agent 驱动的测试协议见 docs/agent-testing.md。
安装标记版本的发行版
从 GitHub Releases 下载适用于你的操作系统和架构的归档。每个归档都包含 jpack 二进制文件、README、该源代码版本所附带的 CONFORMANCE.md 声明、Apache-2.0 许可证、署名声明和第三方声明。
资源名称遵循以下模式:
judgment-pack_<version>_<os>_<arch>.tar.gz
judgment-pack_<version>_windows_<arch>.zip
例如,v0.1.0 发行版使用 judgment-pack_0.1.0_linux_amd64.tar.gz。Linux 和 macOS 用户可以解压归档,并将二进制文件安装到已加入 PATH 且归用户所有的目录中:
tar -xzf judgment-pack_0.1.0_linux_amd64.tar.gz
install -m 0755 jpack "$HOME/.local/bin/jpack"
jpack version
在 Windows 上,解压 .zip 文件,将 jpack.exe 移到已加入用户 PATH 的目录中,然后运行:
jpack version
提取归档前请先验证归档。在 Linux 上:
grep ' judgment-pack_0.1.0_linux_amd64.tar.gz$' checksums.txt | sha256sum --check
在 macOS 上:
grep ' judgment-pack_0.1.0_darwin_arm64.tar.gz$' checksums.txt | shasum -a 256 --check
在 Windows PowerShell 上:
(Get-FileHash .\judgment-pack_0.1.0_windows_amd64.zip -Algorithm SHA256).Hash
Select-String -Path .\checksums.txt -Pattern ' judgment-pack_0.1.0_windows_amd64.zip$'
两个 Windows 哈希值必须一致。发行版归档还附带 GitHub 构建来源证明,可使用当前版本的 GitHub CLI 验证:
gh attestation verify judgment-pack_0.1.0_linux_amd64.tar.gz --repo Judgment-Pack/judgment-pack-runtime
目前尚未发布 Homebrew、Scoop、apt 和 go install 软件包。特别是,通过 go install 从源代码安装不会获得发行版链接器元数据,因此如果需要准确报告运行时版本,请使用发行版归档。
评估一项决策
只要 jpack 位于你的 PATH 中,整个流程就只需要一个规则包、一份事实文档和一个处置结果。
保存一个规则包:除非费用金额超过 5000,否则批准该费用:
cat > pack.json <<'EOF'
{
"specVersion": "0.2.0-draft",
"id": "https://example.invalid/judgment-packs/expense-approval",
"version": "0.1.0",
"title": "Expense approval",
"decision": {
"intent": "Approve ordinary expenses without review.",
"question": "May this expense be approved?"
},
"outcomes": [
{ "id": "approve", "label": "Approve" },
{ "id": "decline", "label": "Decline" }
],
"rules": [
{
"id": "over-limit",
"description": "An amount over 5000 is declined.",
"when": { "op": "fact", "path": "/expense/amount", "operator": "greater-than", "value": "5000" },
"outcome": "decline",
"onUnknown": "escalate"
}
],
"fallbackOutcome": "approve",
"escalation": {
"triggers": ["unknown"],
"target": { "kind": "human-role", "name": "Finance reviewer" }
}
}
EOF
jpack spec validate pack.json
提供一笔费用的事实并进行评估。金额是十进制字符串,这是规范对规则进行数字比较时的要求:
$ echo '{"expense": {"amount": "120"}}' > facts.json
$ jpack experimental evaluate pack.json --facts facts.json
EXPERIMENTAL SURFACE evaluation (claim and scope: CONFORMANCE.md; this result authorizes nothing)
disposition: outcome approve
trace: rule over-limit: false
artifacts: immutable-git-ref · sha256 081cf18af9fe667a5da5acab465f4cf6118a00742bb6e5527d4d45fc09f25185
现在移除金额。规则无法判定,其 onUnknown 为 escalate,且规则包指定了由谁接手此案例,因此答案是移交,而不是猜测。跟踪行会指出缺失的事实:
$ echo '{"expense": {}}' > facts.json
$ jpack experimental evaluate pack.json --facts facts.json
EXPERIMENTAL SURFACE evaluation (claim and scope: CONFORMANCE.md; this result authorizes nothing)
disposition: unresolved (unknown)
handoff: requested -> human-role "Finance reviewer" (triggered by unknown)
trace: rule over-limit: unknown onUnknown=escalate [fact /expense/amount absent]
artifacts: immutable-git-ref · sha256 081cf18af9fe667a5da5acab465f4cf6118a00742bb6e5527d4d45fc09f25185
在 0.23.1 及更早版本中,最后一条跟踪行不会打印用于标明缺失事实的方括号。两次运行的退出码都是 0:无论处置结果是什么,生成处置结果就算成功。--format json 会以载荷形式给出相同结果,其中的处置结果采用规范形式。处置结果是数据,不会授权任何操作,是否据此采取行动由调用方决定。
接下来,docs/building-with-packs.md 介绍由多个规则包组成的项目、这些规则包的测试矩阵和审计跟踪;jpack spec examples --spec-version 0.2.0-draft 会列出评估器从 0.24.0 开始接受的更大型起始示例。
在本地构建并试用
从源代码构建需要 Go 1.24 或更高版本:internal/fssecure 通过 os.Root 将每个项目文件的读取绑定到目录句柄,而 os.Root 是 Go 1.24 标准库中的类型。
如果较旧的 WSL 环境中持久设置了 GO111MODULE=off,请运行一次 go env -u GO111MODULE 将其清除。以下命令会显式启用模块模式,作为兼容性措施。
env GO111MODULE=on CGO_ENABLED=0 go build -trimpath -o ./bin/jpack ./cmd/jpack
./bin/jpack --help
./bin/jpack version
从同级目录中的 judgment-pack-spec 检出版本验证一个合成示例:
./bin/jpack spec validate ../judgment-pack-spec/examples/minimal-expense-approval.json
./bin/jpack spec validate --format json ../judgment-pack-spec/examples/minimal-expense-approval.json
可以显式使用 - 接受标准输入:
./bin/jpack spec validate --format json - < pack.json
运行捆绑的文档一致性测试语料库——默认使用 0.1.0-draft,也可以指定一个精确的捆绑版本:
./bin/jpack spec test-conformance
./bin/jpack spec test-conformance --format json
./bin/jpack spec test-conformance --spec-version 0.2.0-draft
./bin/jpack spec test-conformance --strict
默认情况下,只要预期的诊断出现在报告的诊断中,案例就算通过;--strict 还会在案例报告了其清单条目未预期的诊断时判定失败,并逐一列出这些诊断,这是语料库的单缺陷规则所要求的。
通过实验性评估器运行捆绑的 JPS 0.2.0-draft 评估语料库。每一行都会按照 §8.3 的定义,通过处置结果相等性进行比较——该行的预期结果和生成的处置结果都会经过同一个 RFC 8785 规范化器,因此集合中存储顺序不同不算差异——或者按照预期的 §8.4 错误类别和阶段进行比较。
这会报告结果:这是 CONFORMANCE.md 中所述声明所必需的、但并非穷尽的证据,而不是该声明本身。某一行不匹配本身无法得出任何结论,因为根据 §3.4,差异同样可能是该行的缺陷,也可能是此实现的缺陷;只有项目发布的勘误才能豁免某一行:
./bin/jpack experimental evaluate-corpus
./bin/jpack experimental evaluate-corpus --format json
./bin/jpack experimental evaluate-corpus --spec-version 0.2.0-draft
无需网络连接即可检查或复制捆绑的架构:
./bin/jpack spec schema 0.1.0-draft
./bin/jpack spec schema 0.2.0-draft
./bin/jpack spec schema 0.1.0-draft --write schema.json
./bin/jpack spec schema 0.1.0-draft --write -
架构命令会拒绝覆盖已有文件。这与下文的审计跟踪写入方式不同:后者会追加到项目自身配置指定的文件中,绝不会替换已有文件。
验证行为
验证会按以下顺序短路:
- 严格解析 UTF-8 JSON 载体,包括拒绝重复成员;
- 精确分派
specVersion; - 使用 URI、日期和日期时间断言进行 Draft 2020-12 结构验证;
- 规范性语义引用和扩展声明检查;以及
- 必需扩展的能力协商。
语法上可用但未知的 specVersion 属于 unsupported,而非 invalid。一致性测试运行器会有意将每个用例固定到测试套件声明的规范版本,因此违反该固定模式的 fixture 仍属于结构性反例。
--through carrier 和 --through structural 会产生明确标注为部分结果的输出。它们绝不会输出不带限定语的“有效文档”消息。
公开的 MVP 不支持任何 JPS 扩展。因此,结构和语义均符合规范但需要扩展的文档会报告为 unsupported。验证期间绝不会发现、下载、安装或执行扩展代码。
实验性评估行为
此评估器实现 JPS Core 0.2.0-draft 的评估器一致性类别。有关它的一致性声明,完整且仅在 CONFORMANCE.md 中给出,其中包含其证据、版本范围以及它未作出的所有断言;本节不陈述其中任何内容:本节说明的是行为。
只有声明 specVersion 为 0.2.0-draft 的包才会被评估。 §8.2 的预检、§8.3 的处置结构和 §8.4 的错误类别均属于该版本;§11 规定,声明的版本必须精确匹配:“未经编辑的 0.1.0-draft 包在结构上不符合 0.2.0-draft,声称实现此草案的实现必须先重新声明版本,才能对其进行评估。”因此,声明任何其他版本的包(包括 0.1.0-draft)都会在 preflight 阶段被拒绝为 pack-not-conformant(JPS-EVALUATION-PACK-SPEC-VERSION),且消息会引用该规则并说明补救方法:只编辑一处,即 specVersion 字符串,文档中的其他内容保持不变,因为 §11 指出 0.2.0-draft 不会更改文档格式的任何部分。不存在第二条未经声明的旧版路径。文档验证不受影响——spec validate 仍会根据 0.1.0-draft 自身发布的模式验证该版本的包;文档一致性不需要评估器(§3.4)。
每个评估载荷仍会同时列出两个版本——specVersion 是包自身的版本,evaluatorSpecVersion 是契约的版本——因为这是两个不同的事实,使用方应读取所应用的契约,而不是自行推断。拒绝响应也会在 evaluationError.evaluatorSpecVersion 中注明契约。载荷还带有一个 conformanceClaimReference 成员,其值为 CONFORMANCE.md:这是一个定位符,而非一致性声明。
在解析任何内容之前,先准入输入(§8.2)。 输入按一个固定顺序进行验证——先是包,然后是事实文档,再是证据可用性文档,最后将包的 metadata.requiredExtensions 与调用方的 --supported-extension 集合进行比对——且此验证会在 §8 第 1 步运行之前完成。省略 --evidence 文档时,会隐式使用空对象,这会使每个已声明的需求都成为 unknown;缺少该文档只允许以这种形式出现,且不属于错误。若证据输入不是 JSON 对象、包含未声明的需求,或所携带的值不属于 present、absent 和 unknown,则会被拒绝。
生成的结果就是可移植的裁定(§8.3)。 在使用 --format json 且不带 --pretty 时,disposition 成员会以 RFC 8785 规范形式写入:成员按名称排序,两组集合均已排序且不含重复项,不存在的成员会被省略,而不是序列化为 null,并且不含空格。--pretty 会缩进整个负载,该缩进也会延伸到此成员内部,因此成员顺序和两组集合仍保持规范,但输出不再包含完全相同的字节序列。§8.3 要求“在需要进行字节比较时”进行规范化,因此与其他实现进行字节比较时,必须对任一方未自行生成的内容重新规范化;使用 --pretty 时,必须重新规范化。包中配置的升级目标会与裁定并列报告在 handoffTarget 中,绝不会包含在裁定内部。人类可读输出仍为原有文字。
拒绝是评估错误,绝不是裁定(§8.4)。 对于此运行时拒绝的每次评估,都会在 evaluationError.class 中报告且仅报告一个类别,并包含 evaluationError.phase 和 evaluationError.evaluatorSpecVersion,完全不返回裁定,哪怕是部分裁定也没有。这包括所有界面上的每一项 §8.2 预检条件:超出字节限制的文档和提供的空证据文档,都与其他情况一样进行分类并排序,不会在预检前被拒绝。更具体的 JPS-* 代码会与类别一同作为详细信息报告。未能成为一次评估的调用,例如缺少标志,或此运行时无法将输入读取为有界常规文件,则属于普通操作错误,不附带类别,因为 §8.4 对评估条件进行分类,而传输方式未作定义。这四种类别按照 Core 固定的顺序评估,即上文的预检顺序:
| 类别 | 触发条件 |
|---|---|
pack-not-conformant | 包输入在任意层面都不是语义上符合要求的文档 |
malformed-input | 输入未通过预检:JSON 不可用、证据文档不是对象或无效、证据键未声明,或接纳输入时达到文档限制 |
unsupported-required-extension | 包要求调用方不支持的功能 |
resource-exhaustion | 评估已接纳的输入时达到 §10 中有文档说明的限制:此运行时的评估工作量限制,无论是普通 Core 路径还是使用 --rfc0008-quantifiers 时 |
阶段划分遵循 §10 的规定:接纳输入时达到的限制属于 malformed-input,因为输入遭到拒绝,而非部分处理;resource-exhaustion 则专用于评估已接纳输入时达到的限制。此运行时的接纳限制列于安全默认值下方。其中一项限制是 250,000 个节点上限,§10 中的类别也会明确说明,而非留作暗示:这是针对整个已解析文档的预算,因此属于文档大小限制,和字节数与深度限制一样,在接纳输入时触发,并在 preflight 阶段报告为 malformed-input。它同时也是此评估器的集合大小上限,原因见下一节:含有 n 个成员的集合会解析为 n+1 个节点,因此针对节点的文档大小预算也能限制其中的每个集合。
所声称类别的两项 §10 限制
§10 要求声称属于此类别的实现至少定义并记录集合大小限制和评估工作量限制,并规定在评估期间达到其中任一限制时,结果应为 resource-exhaustion,而非处置结果。两项限制均在此定义,并在
internal/evaluation/limits.go 中强制执行:
-
评估工作量限制:每次评估 20,971,520 个工作单位。 一个单位对应一个已访问的条件节点、一次 §8 对编写的证据要求、例外或规则的迭代、一次指针解析步骤,或比较必须读取的路径、对象成员名称或标量令牌中的一个字节。每棵条件树的工作量会在其中任何谓词运行之前全部计入,§8 自身的迭代也会在步骤 1 之前计入,因此总量不受评估顺序影响;达到限制时绝不会截断处置结果,而是在
evaluation阶段产生resource-exhaustion,且完全不产生处置结果。这个数值并非随意选定,而是在代码中推导得出:它恰好是 10 MiB 的两倍,而 10 MiB 是每份获准输入都必须满足的文档字节上限;
limits.go根据该常量计算此值,因此两者不会偏离。这个比率只是两个数字之间的算术事实,仅此而已:它不能保证任何一次完整评估。 获准的文档可能有三份,而非两份——数据包、事实文档以及可选的证据可用性文档——每份都遵循相同的上限;并且工作单位按使用次数计费,而非每个获准字节只计一次,因为每次条件读取指针和所选值时,这些字节都会再次计费,此外还有 §8 固定的节点和迭代费用。本节的早期版本根据该比率推断“完整读取每个获准字节一次总是能通过”,并据此认为一次跨文档最大比较恰好达到上限;这两项说法均已撤回——在这种计费模型下,前提无法限定任何情况,而且通过计费路径对获准输入进行测试时,也没有验证过这两项说法(ADR-0011 记录了这项更正)。实际上,该限制要阻止的是放大行为——每次对in候选项或每个条件进行评估时,都重新读取同一个大型选定值——但此运行时并未声称只会拒绝放大行为。对于 100 KB 的事实文档,该限制仍允许进行约两百次完整文档比较;随附评估语料库中的每一行计费都低于 1,000 个单位:这些只是针对这些输入的测量结果,并非对任何未包含在语料库中的输入作出限制。调用方可以为每次评估配置更低的限制;RFC 0008 草案原型使用自身较小的 100,000 个单位预算(ADR-0009),而 RFC 0016 草案原型则受此限制约束(ADR-0039)。 -
集合大小限制:250,000 个成员——即上述 250,000 个节点的载体上限,明确作为 §10 限制。每份输入都在该上限内获准,因此获准文档中的集合都不会更大;此评估器遍历的每个集合也都来自获准文档:Core 不会自行构造集合,也没有会迭代集合的运算符。由于此限制是在输入获准时强制执行的,达到限制时会在
preflight阶段产生malformed-input——§2.1 会拒绝整份此类文档,而非只处理其中一部分——这比在评估阶段检查相同限制更严格,而非更宽松。因此,此运行时会记录这项判定,而不是再添加一种只能报告预检已拒绝内容的机制。
限制不具可移植性:不同实现可以设置不同的限制,超过任一实现限制的输入都不在可移植声明范围内(§10)。因此,评估语料库中的每个用例都远低于任何合理的限制,而不是用于探测限制边界。
jpack.json 项目约定
一个拥有多个 pack 的项目,需要为每个 pack 命名,并确保从 shell、CI 和 Agent 的工具调用中使用的名称一致。jpack.json 就是这个索引——它是此运行时的一项约定,并非 Judgment Pack Specification 的一部分(ADR-0012)。
其他实现没有义务理解它,而从未编写过该文件的项目也不会因此损失任何功能:每条命令仍然通过路径接收 pack,每个 MCP 工具仍然通过文本接收 pack。
{
"configVersion": "1",
"packs": {
"expense-approval": {
"path": "packs/expense-approval-1.2.0.pack.json",
"matrix": "packs/expense-approval.matrix.json",
"description": "May this expense be reimbursed without a manager's sign-off?",
"expectedVersion": "1.2.0",
"facts": { "/expense/amountUsd": { "source": "Snowflake FINANCE.EXPENSES", "hint": "amount_usd as a decimal string" } },
"evidence": { "itemised-receipt": { "source": "SharePoint /Finance/Receipts" } }
}
}
}
文件的选择顺序为 --config、JPACK_CONFIG,然后是 ./jpack.json。其 schema 是封闭的,可通过 jpack packs schema 输出:任何未列出的成员都会被拒绝。
configVersion 是以字符串表示的单个整数,遵循 outputVersion 的先例,而非语义化版本规范;"1" 是不含图的结构,"2" 是含图的结构(ADR-0017),"3" 是还可以要求审计跟踪的结构(ADR-0018),"4" 是还可以要求经审查集合的结构(ADR-0044),"5" 是还可以要求可比较事实的结构(ADR-0046),"6" 是其审计成员还可以说明跟踪是否经过链式链接的结构(ADR-0047),"7" 是其审计成员还可以指定预期与其签名密钥对应的公钥的结构;此运行时支持全部七种结构。
没有模板化、没有目标或环境区块,也没有选择机制。模板化的 pack 从来不是任何人审查过的 pack;按照约定,每个环境使用一个文件(jpack.staging.json、--config);而选择要询问哪个决策属于应用程序,因为适用性并不等于授权。你的拉取请求就是审批——文件中没有审批状态。
**pack 的身份只在 pack 文档的 id 和 version 成员中声明一次。**其他所有用于标识版本的内容都是对该声明经过验证的引用,绝不是第二份声明:
expectedVersion 是 packs validate 会进行比较的固定版本;可选的 <decision-id>-<semver>.pack.json 文件名会在跟随引用时进行交叉核验,不跟随时则跳过;每个评估负载上的 packId 和 packVersion 成员则是从被评估文档中读取的回显值。这三者中的任何一个都可能与文档不一致,而不一致就是错误——它们都不能覆盖文档中的声明。
facts 和 evidence 提示是为收集输入的 Agent 提供的非规范性指导:它们用你的话说明某个值存放在哪里。运行时绝不会读取任何来源——它不持有凭据,也不会打开网络连接——并且约定中指定的每个文件,都是通过绑定到配置文件所在目录已打开句柄的读取器读取的。路径包含性通过两项检查保证,二者不能互相替代:词法检查会在读取任何内容之前拒绝绝对路径或逃逸路径;读取时相对于已持有的目录进行解析,则会拒绝通过符号链接组件指向目录外部的路径,这是词法检查无法发现的。第二项检查使用的是句柄而非路径名,因此能在整个打开过程中保证包含性:若先检查路径、再按路径名打开,中间目录就可能在两者之间被替换为指向外部的符号链接;相对于句柄进行解析会让这种情况无法发生,而不只是降低其发生概率。无论最终组件指向何处,只要它是符号链接就会被拒绝,且只读取常规文件。所有通过配置访问 pack 的入口都使用这同一个读取器,包括 --pack-id;不会将路径名交给任何入口,让它自行打开。
此文件唯一能要求运行时写入的内容,是一条关于其评估结果的记录
(ADR-0018)。在 configVersion "3" 下,audit
成员指定相对于配置文件的目录 — "audit": { "dir": "audit" } —
每次完成 experimental evaluate 和 MCP experimental_evaluate
工具的评估后(除非声明为演练,见 ADR-0028),都会向其中的
evaluations.jsonl 追加一行 JSON;每次完成 experimental graph evaluate 后,除非声明为演练(见 ADR-0041),也会为每个节点和组合结果分别追加一行。每行包含
包的 id、版本、specVersion 及其精确字节的摘要、评估时使用的事实和证据
文档,以及规范形式的处置结果。测试运行绝不记录 — packs test、
experimental graph test 和 experimental evaluate-corpus 是对包的检查,
而非任何人做出的决定 — 被拒绝的评估不会留下记录,因为没有处置结果可供记录,而
无法写入记录则会拒绝此次运行(退出码 4),而不是报告一个没有留存记录的处置结果。写入操作与每次读取一样,通过同一个已持有的句柄进行,写入项目自己的目录树,不会写到其他任何地方。不声明 audit 成员,就完全不会写入任何内容。在这样的项目中提供的引文,无论通过 --cites 还是 MCP 工具的 cites 提供,都会在评估任何内容之前被拒绝(JPS-INVOCATION-CITES,退出码 3),而不是被接受后却无处记录;但演练除外
(ADR-0051)。
如果评估的跟踪记录提到了跨 JSON 类型的比较或未知值的成因,
记录也会包含从跟踪记录中收集的 typeMismatches 和 unknownCauses:指针、类型
和成因,而非值(ADR-0046)。图运行的节点记录包含各自节点的注释,组合记录则不包含注释。没有任何注释的记录,其字节与原记录完全相同。
记录链会相互链接(ADR-0047 §1)。每条
记录还包含 trail(记录链的标识,128 位随机数,以十六进制表示)、sequence(行号,从 1 开始)和 previous(前一行精确字节的 SHA-256,不含换行符)。链式记录启用之前写入的记录永远不会被改写:第一条链式记录一次性提交之前的整个文件,因此它的
previous 是文件当时状态的 SHA-256。除此之外,记录的字节完全不变,且
recordVersion 仍为 "1"。写入程序会在记录链上持有排他性的协作锁,在读取最后一行、为待写入行编号(图运行中先为节点编号,再为组合结果编号)、写入内容以及同步文件和目录时均持有该锁。遇到末行没有换行符(表示写入未完成)、必须读取的行超过 128 MiB、记录本身超过 128 MiB,或因可能只是暂时性的原因无法获取锁时,程序会拒绝追加(JPS-AUDIT-WRITE,退出码 4,并说明原因)。只有在平台或文件系统完全不提供锁的情况下,才会写入非链式记录。不需要记录链的项目可在 configVersion "6" 下设置 "audit": { "dir": "audit", "chain": false }。重新计算每个 previous,即可检查截至最后一条链式记录的已提交前缀。其后的非链式行不受覆盖,位于此前缀之外;没有链式记录的文件则没有链式历史。在此前缀内,编辑、插入、删除或移动某行,都会破坏后续链式记录的链接。这并不构成经过认证的历史。编辑最后一条链式记录不会破坏任何链接;截短记录链,或从任意一行开始重写并重新计算链接,都能得到与真实记录链同样一致的结果;只有由操作员以外的人持有、且覆盖这些行的承诺,才能区分二者。保留记录链及其任何副本时,必须逐字节保持不变:解码后再重新编码的行,其字节会不同,摘要也会不同。
核验审计轨迹。 jpack audit verify 会读取项目的审计轨迹,或通过 --trail <file> 指定的文件,按其
精确字节进行读取,并从第一条链式记录开始检查每条记录的 trail、sequence 和 previous;任何一项检查失败时都会以状态码 1 退出,并在报告中逐项列出,否则以状态码 0 退出。它会在写入器的共享锁下读取文件大小,因此读取到的大小会介于两次写入之间;读取该位置之前的字节时不会加锁:写入器只会追加,因此核验既不会拖慢写入器,也不会与其发生竞争。未提供 --expect 时,报告反映的是所提供链条的完整性,范围仅限于截至最后一条链式记录的已提交前缀,并会说明它无法证明的事项:最后一行链式记录,或从某处开始重写并重新计算链接的各行,是最初写入的那些行,或审计轨迹是完整的。报告会将未链式连接的后缀标记为未覆盖,并说明它位于该前缀之外。jpack audit checkpoint 会打印最后一条链式记录的检查点,即一行规范 JSON,其中包含审计轨迹的身份、该记录的序号以及其精确字节的
SHA-256,以便交给将其留存的人。jpack audit verify --expect <checkpoint> 还会在审计轨迹较短、身份不同,或该序号对应的记录不同的情况下报错,并将截至该记录的各行报告为已由检查点覆盖。
无论是否提供 --expect,每份报告还会说明:审计轨迹记录的是决策,而不是尝试,因此其中没有记录,并不能证明某项评估没有在关口被拒绝、经过演练或在形成处置结果前失败(ADR-0048)。
写入未完成后,jpack audit repair 会保留损坏字节,并将其单独作为一行,然后追加一条不连续性记录,其中注明这些字节的摘要并跨过它们建立链接,以便写入器继续运行(它不会修复被截断的不连续性记录,因为修复不会修复另一条修复记录);
verify 随后会将审计轨迹报告为多个片段,不会将断点前后的内容视为完整连续。 不连续性行不记录决策:其 kind 为 "discontinuity",且不含 pack、输入或处置结果。
向持有人交付检查点。 jpack audit checkpoint --since <sequence> 会为指定序号之后的每条链式记录打印检查点,每条记录一行,供交付方(Desk、作业、钩子)交给操作员无法控制的持有人:交易对方、审计员或存储方。交付方会轮询并记住进度;记录决策绝不会等待交付方,而尚未由持有的检查点覆盖的记录会报告为未见证。检查点由其记录的字节决定,因此重试时交付的内容相同。运行时不会记录哪些内容已交付,因为操作员可能会重写这些记录;持有人的副本才算数。jpack audit verify --expect <file> 会读取持有人提供的检查点文件,每行一个,将审计轨迹核验到其中的每个检查点,并将截至匹配的最高检查点且此前没有任何检查失败的记录报告为已见证,其余报告为未见证;如果截至 --require-checkpoint-through <sequence> 指定的序号仍有任何记录未见证,则核验失败。对于信任持有人副本的人,持有的检查点表明其覆盖的记录在该检查点交付时确实已经存在。但它无法说明之后的记录、持有人未留存的检查点,也无法说明时间。
为检查点添加时间戳。 项目可以指定 RFC 3161 时间戳机构,
在 configVersion "6" 下设置 "audit": { "dir": "audit", "timestampAuthority": "https://…" },然后由调度程序、Desk 或人员运行的
jpack audit stamp 会请求该机构为当前检查点的 SHA-256 添加时间戳,并将令牌保存在轨迹旁的 stamps.jsonl 中(ADR-0047 §2a)。决策流程不会向该机构发出请求:先追加决策,尚未添加时间戳的记录处于待处理状态;如果机构无法添加时间戳,轨迹和所有决策都保持原样。已添加时间戳的检查点不会再次提交。jpack audit verify --tsa-roots <file> 会根据验证者信任的根证书检查每个令牌:其摘要、签名、证书的时间戳用途,以及令牌所述时间点的证书链、策略(--tsa-policy),并根据通过 --tsa-crls 提供且适用于时间戳时刻的吊销列表检查其状态;无法检查的会报告为未检查。如果某个可信时间戳对应的检查点已不在轨迹中,则表明轨迹自那之后被改写。报告会列出已添加时间戳的记录,以及每条记录的 at 与覆盖它的首个时间戳之间的延迟。已添加时间戳的 through 表示从第 1 行起不中断的前缀;可信时间戳计数则会单独计入与某个独立记录检查点匹配、但位于较早的链断点之后的情况。若截至 <sequence> 的记录尚未添加时间戳,--require-stamped-through <sequence> 就会失败。时间戳证明检查点在该机构所述时间之前已存在,前提是该机构的证明可信。它不能证明记录何时创建:at 仍由操作员自行声明。若机构并不独立于操作员,它便无法提供任何证明;未检查吊销状态时,也无法证明未被吊销。令牌仅使用标准库解析和验证;指南列明了所有规则。
阅读见证方的声明。 见证方是由轨迹操作员以外的一方运行的网关,它会为提交给它的检查点签名,并按轨迹串联其声明(网关 ADR-0013;目前尚无网关版本提供这些声明)。jpack audit verify --witness-key <file> 会读取你从该网关获取的声明(--witness <file>)和头部(--witness-head <file>),并使用你信任的密钥进行验证:检查每条声明是否由该密钥签署,链是否从索引 0 开始读取、从未滞后,并延伸至头部。这样,读取结果就是截至你获取头部时的最新状态;没有头部时,结果仅代表历史状态。每条通过验证的检查点声明中所含的检查点,都会像轨迹中保留的检查点一样得到保留;若链中没有见证方发现的问题,则该链会被认可:覆盖信息中的 countersigned 表示覆盖范围,若截至 <sequence> 的记录尚未获得会签,--require-countersigned-through <sequence> 就会失败。冲突声明包含一个已提交但遭拒的检查点,不会因此获得任何认可。更长的链会分步读取,使用 --witness-save 和 --witness-resume;--witness-save 会拒绝将目标设为验证过程中读取的文件(恢复所用的续传文件除外),也会拒绝任何已存在且并非续传文件的目标;它绝不会因拒绝操作而隐藏发现的问题(指南说明了该检查无法防范哪些情况)。一条获认可的检查点声明表明,其中检查点之前的各行就是见证方签署声明时已存在的内容,前提是见证方独立于操作员;但它不能证明是谁提交的,时间则依据见证方自己的时钟。
为追踪记录签名。 项目可以通过在 configVersion "6" 下配置 "audit": { "dir": "audit", "signingKey": "<absolute path>" },或设置环境变量 JPACK_SIGNING_KEY,指定一个保存在项目外部的 Ed25519 种子;之后,每条链式记录都会被签名(ADR-0047 §2b):写入记录后,在同一把锁的保护下,会在追踪记录旁边的 signatures.jsonl 中追加一行,将记录的 trail、sequence 及其确切字节的 SHA-256 绑定在一起。记录行不会更改。密钥必须使用其真实路径指定,路径中不得包含符号链接,且必须位于项目目录之外(打开密钥时通过设备号和 inode 进行比较);它必须是一个只有一个名称的文件,由运行时所用的用户拥有,且其他用户不可读取;所在目录必须由 root 或该用户拥有,且其他用户不可写,除非目录设置了 sticky bit。不符合要求的密钥不会进行签名(被拒绝的目录会被指出:对于其他人可写的目录,执行 chmod go-w 即可修复;如果目录由另一用户拥有,则必须将其移交给 root 或该用户,或将密钥移至路径上的每个目录都符合要求的位置)。在 Windows 上,由于运行时不会读取 ACL,因此不会有任何密钥进行签名。环境变量的作用范围是整个进程:如果该变量已继承,那么无论 configVersion 如何,进程记录的每条链式追踪记录都会被签名,包括从未指定密钥的项目。可以在密钥路径旁边,通过 configVersion "7" 下的 "signingPublicKey": "<64 lowercase hexadecimal characters>",或通过环境变量 JPACK_SIGNING_PUBLIC_KEY,指定预期的种子公钥;环境变量优先级相同,但会按原样读取,不会去除任何字符。此时,如果种子的公钥与预期公钥不同,那么每次即将为记录签名时都会拒绝该种子;因此,即使把种子放在密钥路径上,也不会进行签名。无论在哪处指定,格式不符的预期公钥都会在读取任何种子之前被作为密钥拒绝,且其值绝不会被打印出来。无论何种情况,packs validate 都会说明原因(audit-signing-key);对于预期公钥,它既不会指出路径,也不会显示任一密钥。签名不会导致决策失败:无法写入签名时,记录会保持未签名状态。jpack audit key generate 会生成密钥并打印其公钥;jpack audit key public 会打印密钥的公钥;jpack audit key rotate --next <seed> 会通过一行由当前密钥签名的记录,将签名工作移交给新密钥。jpack audit verify --public-key <file> 会检查每个签名和密钥轮换,报告签名能够认证的连续前缀长度,以及自身签名有效的单条记录数量(包括链中较早位置已断裂之后的记录)。如果存在无效签名、针对其他记录的签名、未对应任何记录的行、未由当时生效的密钥签名的轮换、已撤销密钥的行,或顺序错误的行,命令会失败;如果签名未覆盖到指定序号,--require-signed-through <sequence> 也会导致命令失败。撤销由验证方控制:--revoked <file> 用于指定从某个序号起不再信任的密钥;每个密钥各提供一次 --public-key,即可固定追踪记录可轮换使用的密钥。签名只能证明持有密钥的人签过名。它无法证明任何关于持有密钥的操作员的事情;密钥被复制或盗取后,它也无法证明之后发生的任何事情。侧文件格式及验证规则(含测试向量)见 docs/building-with-packs.md。
绑定调用方自己的材料。 experimental evaluate --binding <file> 和 MCP
experimental_evaluate 工具的 binding 参数,必须严格采用 {"kind": "<scheme>", "digest": "sha256:<64 lowercase hex>"} 格式:这是配套方对其自身材料的承诺,运行时永远不会看到这些材料,例如 Runner 在运行前所做的准备
(ADR-0050)。kind 必须由 1 到 128 个字符组成,字符限于
a-z、0-9、.、_、/ 和 -。记录会按原样携带该字段,将其作为 binding 放在 cites 旁边,并将 kind 排在前面;因此,链和记录签名会像涵盖其他所有成员一样涵盖它;不带该字段写入的记录与之前逐字节相同,recordVersion 仍为 "1"。
运行时会记录绑定,但不会解读它:它永远不会验证或重新计算摘要,评估也不依赖它。配套方自己的验证器会根据材料检查其值。形状不符、大小超过 1 KiB,或与 --rehearsal 一起提供,或在不保留轨迹的项目中提供(这两种情况下都不会记录任何内容)的文档,都会在评估任何内容之前被拒绝(JPS-INVOCATION-BINDING,退出码 3),且不会写入任何内容。audit verify 只检查形状:格式错误的已记录绑定会被标记为 binding-malformed,导致验证失败且不增加覆盖率;格式正确的绑定则不会被提及。对于持有签名密钥的运营方,绑定所能确立的内容不超过签名本身。
拒绝任何比较都无法匹配的事实。 JSON 类型之间不会进行强制转换:发送为 "true"、1 或 null 的标志会使 equals true 的结果为 false,而不是 unknown,因此 onUnknown: escalate 不会接收到它,检测器会继续执行其回退逻辑。jpack.json 中设置了 "requireComparableFacts": true(configVersion "5",ADR-0046)的项目,其 experimental evaluate、MCP experimental_evaluate 工具,以及 experimental graph evaluate 的每个节点,都会在评估前拒绝这类输入(JPS-FACTS-COMPARABLE-REQUIRED,退出码 1,不生成记录)。当某个事实存在,且其类型是该 pack 中任何比较都永远无法匹配的类型时,运行会被拒绝:即没有任何 equals、not-equals 或 in 操作数采用的类型;对于有序比较,则只能是十进制字符串,因此不符合十进制语法的字符串和 JSON 数字都会被拒绝。检查会涵盖所有比较,包括评估不会触及的比较。检查工作量受评估工作量限制约束;如果检查会超过该限制,则无论 pack 中比较什么,都会依据同一代码拒绝,因为此时无法断定这些事实是否可匹配。该拒绝属于项目层面,而非评估错误,因此不附带 §8.4 类别。缺失的事实不会被拒绝,因为它是 unknown,且由 onUnknown 决定如何处理。声明的 rehearsal 也会被拒绝。packs test、experimental graph test、experimental evaluate-corpus、experimental compare 和 MCP 测试工具则不会拒绝,因为它们的行可能正是有意用于探测此类事实。拒绝信息会列出每个指针、事实的类型以及比较可以匹配的内容,绝不会包含事实值。
已审核集合
jpack packs lock 会在配置文件旁写入 jpack.lock.json:其中包含配置文件精确字节内容以及配置声明的每个 pack 和图的摘要
(ADR-0019)。运行该命令就是修订——项目借此在审阅者可以逐差异检查的文件中表明,规则已按计划更改——但它不会批准任何内容:
你的拉取请求仍需获得批准。该文件为生成文件且具有确定性,因此对未更改的树重新运行不会产生差异。jpack packs verify 会列出与其相比的所有差异:
config-drift、document-drift、document-missing、lock-entry-missing、
locked-but-undeclared 和 path-mismatch。
它通过文件是否存在实现选择启用:依据约定发现,而非显式声明;不会调整 configVersion,架构也不会改变,没有锁文件的项目行为与以往完全相同。有锁文件时,负责做出决策的界面——experimental evaluate、experimental graph evaluate 和 MCP experimental_evaluate 工具——会遵循即将应用于该项目的规则(已声明的演练除外,参见 ADR-0028、ADR-0041),并拒绝不匹配的情况(JPS-LOCK-VERIFY,退出码为 1),同时提供两条坦诚的处理方式:声明修订,或恢复经过审核的字节。packs test、experimental graph test 和 experimental-evaluate-corpus 从不查阅锁文件:作者的工作循环不受限制,而决策则会被分类。按路径指定的包,或通过 MCP 以文本形式传入的包,属于草稿——可以评估,不会因未锁定而被拒绝,并会记录为草稿。如果已配置审计跟踪,每条记录都包含 reviewed:所有应用的文档都已声明且匹配时为 true;草稿为 false;项目未声明锁文件时则省略。评估载荷也包含相同的 reviewed;当其值为 true 时,reviewedSet 会注明锁文件的修订版本,让调用方无需读取审计跟踪即可知晓(ADR-0044)。演练不查阅锁文件,也不会包含这两个字段。
要求启用。 如果项目的 jpack.json 设置了 "requireReviewed": true(configVersion "4",ADR-0044),那么负责做出决策的界面会在评估前拒绝所有应用草稿的运行,以及项目尚无锁文件时的所有运行(JPS-LOCK-REVIEW-REQUIRED,退出码为 1)。已声明的演练不属于决策,因此不会被拒绝。这会约束既不选择运行读取的配置,也无法编辑该配置或其锁文件的调用方,例如只能使用其他人启动的 MCP 服务所提供工具的 Agent。它无法约束选择配置的人(--config、JPACK_CONFIG、工作目录),也无法约束能够编辑 jpack.json 或锁文件的人;而关闭此设置本身也是一次会被锁文件记录的编辑,因此按 ID 运行会一直被拒绝,直到项目重新锁定为止。
它不是什么。 它不是一道屏障。任何能够编辑包的人都可以再次运行 packs lock,而此运行时无法分辨这是有意修订策略,还是其他操作——两者本质相同。锁文件的作用是让修订不再悄无声息。
七条命令、一行 CI 配置,以及一个修订步骤:
jpack packs list # the resolved inventory
jpack packs validate && jpack packs lint && jpack packs test && jpack packs verify # the CI gate
我们特意没有将 packs lock 放入那一行中。它用于修订规则——只有在有意更改规则时才运行,并将其输出与所固定的更改一同提交。若在 packs verify 之前立即运行它,验证就会失去意义;这正是让此约定倒退的唯一方式。
packs validate 会针对每个 pack 报告六项具名检查——路径包含关系、文档验证、expectedVersion 固定值、文件名交叉校验、提示键和矩阵格式正确性;每项结果为 passed、failed 或 skipped。packs test 会通过实验性评估器运行每个 pack 的实例矩阵,并按与内置评估语料相同的方式比较每一行:逐字节比较 RFC 8785 规范化的 §8.3 disposition,或比较预期的 §8.4 错误类别和阶段;此外,还会检查每行一项可选断言,确认升级目标符合 §8.3 中置于 disposition 之外 的规定(expectedHandoffTarget,需要 matrixVersion: "2")。一行还可包含 cites(需要 matrixVersion: "3"):网关会为其所依据的事实生成收据;加载矩阵时会验证这些收据,并将其作为值附加到该行的结果中——这些元数据不由比较器读取(ADR-0034)。这两种载体包含比较器会读取的相同字段,因此比较逻辑可以共用一个实现;这并不意味着行可以不经处理地在两者之间转换。语料库准入还要求包含其自身的成员(pack、origin、supportedExtensions、focus、specSection),且其封闭 schema 禁止使用 expectedHandoffTarget 和 cites,因此要将项目行纳入语料库,必须补上这些成员,并移除任何目标断言和引用。任一命令遇到失败都会以 1 退出;没有矩阵的 pack 会报告为 skipped,而非默认通过(使用 packs test --require-matrix 时则报告为 mismatch;ADR-0042);若 packs test 运行时没有执行任何行,也会报告为 skipped 并以 1 退出,除非发现了 mismatch:零行通过的门禁会让人误以为项目已测试,实际却什么都没做。新项目可以从空的 packs 对象开始:清单检查和结构验证会接受它,而 packs test 仍会报告为 skipped 并以 1 退出。packs lint 会弥补两者都未覆盖的缺口:如果 pack 查询的指针没有任何来源提供值,任何地方都不会报错——这种情况无法判定,因此相关规则会升级,或在 onUnknown: ignore 下跳过,并在不考虑该指针的情况下使用回退答案——所以 lint 会要求每个被查询的指针都对应一个生产者声明(配置自身的提示,或显式的 --producers 清单),并在其他检查无法发现此类问题时让构建失败(ADR-0022)。
在 shell 中,jpack experimental evaluate --pack-id expense-approval --facts facts.json 会通过相同的名称访问同一个 pack。通过 MCP,使用 list_packs 获取相同的清单,使用 get_pack 获取一份文档,而 experimental_evaluate 接受 pack_id,无需粘贴 pack 文本;图谱约定也采用同样的一对工具:experimental_list_graphs 和 experimental_get_graph,对应 CLI 的 experimental graph list(ADR-0029)。未配置时,list_packs 会返回空结果,并说明运行时检查过哪些位置,而不是直接失败。
docs/building-with-packs.md 是面向构建者的指南,介绍 packs-as-code 生命周期、三方所有者模型(应用负责选择,Agent 负责收集且绝不编造,pack 负责判断)、提示在实践中的用法,以及将数据充分性作为另一个 pack 的模式。
进程契约
| 退出码 | 含义 |
|---|---|
0 | 命令成功;验证通过了所报告的范围。 |
1 | 文档无效、某项预期不匹配,或命令执行的检查失败——包括符合性不匹配、与已审阅集合存在差异,或导致其失效的规则。 |
2 | 不支持指定的 JPS 版本或必需扩展。 |
3 | 调用或套件配置无效。 |
4 | 输入/输出或资源限制导致失败。 |
5 | 内部运行时或捆绑构件失败。 |
对于正常、有效、无效、不受支持、不匹配以及已处理的操作结果,--format json 会向标准输出写入且只写入一个带版本号的 JSON 对象,并附加换行符。该输出流中不会混入面向用户的文本或 ANSI 控制字符。结果包含 diagnosticsTruncated,以便自动化工具检测是否已达到输出上限。--quiet 仅适用于人类可读输出。
文档结果(包括 invalid 和 unsupported)会写入标准输出。调用、输入/输出、资源和内部错误会写入标准错误。
安全默认设置
当前实现:
- 在评估或获取输入时不会获取任何内容,也不会解析文档定位符;唯一的例外是请求时间戳时,此时会向时间戳颁发机构请求并接收其令牌;
- 仅接受一个明确指定的常规文件或标准输入,不接受 URL 或特殊文件;
- 只会在指定的位置以以下三种方式写入内容,不会采用其他方式:将捆绑的架构或示例复制到操作员通过
--write指定的目标位置,且拒绝覆盖现有文件;每完成一次非演练评估,就追加一条记录(ADR-0028);对于非演练图评估,则为每个节点和合成结果各追加一条记录(ADR-0041),前提是项目的jpack.json声明了audit目录(ADR-0018),写入该目录时通过在配置所在目录上保持打开状态的句柄进行;当审计记录链式连接时,在记录文件本身上使用建议锁(ADR-0047)——记录不是诊断信息,且会包含项目要求记录的文档;以及当操作员运行该命令时,jpack packs lock会在配置文件旁生成已审阅集合锁(ADR-0019),通过同一句柄原位替换;如果该文件将落在配置声明的文档上,则会直接拒绝; - 在任何嵌套深度下都拒绝重复的解码后成员名称、无效 UTF-8、尾随 JSON 和非 JSON 常量;
- 将文档大小上限设为 10 MiB、嵌套深度上限设为 128、解析节点数上限设为 250,000,诊断信息上限设为 100;
- 将本地符合性套件的用例数上限设为 10,000,总大小上限设为 100 MiB;
- 将单个符合性结果中保留的诊断信息上限设为 1,000;
- 在解析测试夹具之前验证套件元数据,并拒绝路径遍历和符号链接路径;
- 将扩展值视为惰性数据;以及
- 输出经过净化、不含值的面向用户的诊断信息。
有关报告方式和边界的详细信息,请参阅 SECURITY.md。
制品溯源
运行时验证仅使用嵌入二进制文件中的文件,并根据每个捆绑规范版本对应的一个锁文件进行验证:
internal/artifacts/jps/0.1.0-draft/lock.json 和
internal/artifacts/jps/0.2.0-draft/lock.json。
每个锁文件都会记录源代码库、确切的提交/引用和源状态,以及每个导入文件的 SHA-256 和大小元数据:0.1.0-draft 有 50 个,0.2.0-draft 有 56 个;后者的捆绑包增加了 §3.4.1 的评估语料库(其清单、该清单的架构,以及清单行中列出的 4 个包固定样例)。发布门禁会检查每个捆绑包:开发快照会明确标记为 unreleased-local-snapshot,且无法通过检查。
溯源说明。
0.2.0-draft捆绑包固定到规范标签v0.2.0-draft。0.1.0-draft捆绑包固定到确切提交,而不是其标签:v0.1.0-draft标签中的架构$id使用临时的仓库托管 URL,而永久的https://judgmentpack.org/schema/标识符是在此之后才加入的;规范的发布工具要求标签字符串与specVersion相同,因此不能使用第二个0.1.0-draft标签发布。这里明确支持使用完整长度的提交摘要作为不可变引用,发布门禁也接受这种方式。
制品捆绑包和一致性语料库摘要使用 sha256-length-prefixed-v1:每个已排序的路径和文件正文都编码为一个无符号 64 位大端字节长度,后接相应的确切字节。
语料库摘要涵盖 manifest.json、manifest.schema.json 和清单中的每个固定样例,因此等效的捆绑语料库与本地语料库会产生相同的值。人类可读的一致性输出和 JSON 一致性输出都会报告该值。
每次发布前,必须从经批准的不可变规范提交或标签重新导入这些文件。锁文件必须注明 immutable-git-ref、记录干净的源工作树,并标识确切的引用和提交。可变的 main 绝不能作为运行时验证依据。
维护者可以使用以下命令创建一个新的、初始不存在的快照目录:
env GO111MODULE=on go run ./tools/sync-spec-artifacts \
--source ../judgment-pack-spec \
--destination ./internal/artifacts/jps/<exact-version> \
--allow-dirty
对于未发布的快照,必须使用 --allow-dirty。发布候选版本则使用 --source-ref <exact-commit-or-tag>;该模式会验证官方仓库源、干净的工作树,以及该引用是否解析为当前检出的 HEAD。制品更新属于经过审查的源代码更改;运行时绝不会执行此工具。
公共与商业功能边界
本仓库旨在始终作为一个自包含的 Apache-2.0 公共核心。它必须能够在不依赖私有仓库、凭据、服务、软件包索引或功能标志的情况下构建、安装、验证并运行一致性测试。
商业功能应放在独立的私有仓库中;本公共仓库绝不能依赖这些仓库。目前受支持的集成边界是 jpack 可执行文件及其带版本的 JSON 输出。Go 包有意设为 internal,目前尚无稳定的进程内 SDK 或插件 API。在将商业命令组合进同一个二进制文件之前,公共项目必须审慎地定义并版本化该契约。未来的命令应使用独立的命名空间,例如 jpack cloud 或 jpack org;不得覆盖 jpack spec 的一致性语义,也不得在验证期间自动加载。
规范性规范、架构和公共语料库仍保存在独立的 judgment-pack-spec 仓库中。
开发
env GO111MODULE=on go fmt ./...
env GO111MODULE=on go vet ./...
env GO111MODULE=on go test ./...
env GO111MODULE=on CGO_ENABLED=0 go build -trimpath ./cmd/jpack
请参阅 CONTRIBUTING.md、docs/architecture.md 和维护者发布操作手册。
在 VS Code 中,终端 → 运行任务 → judgment-pack: Build CLI 会构建 bin/jpack;测试和捆绑一致性任务也可从同一菜单中使用。这些任务会明确启用 Go 模块模式,以兼容较旧的 WSL 配置。
许可证
Apache License 2.0。请参阅 LICENSE。
图评估修订
实验性图评估包含 graphSha256、configSha256,以及每个节点的 packSha256。这些值用于标识本次运行加载的确切字节;它们不能证明内容经过审查,也不能证明项目快照具有原子性。有关扇入、扇出、重复 pack 和未解析结果,请参阅 ADR-0049 和组合测试夹具。
方言文档工具
jpack dialect 提供离线文档编码和按版本限定的验证工具,用于配套草案方言;该方言固定在 Spec 提交 b7cc8906c23d92c63f4e42c4706cc1e21b9d324f。
使用 jpack dialect contract --format json 查看已实现的操作、编码和验证版本及其限制。这与 jpack version 报告的 Core 版本相互独立。
jpack dialect init --dialect-version 2 > draft.dialect.json
jpack dialect canonicalize draft.dialect.json > canonical.dialect.json
jpack dialect digest canonical.dialect.json
jpack dialect validate draft.dialect.json --format json
jpack dialect canonicalize draft.dialect.json --format json
此起始模板不包含源或字段副本,其版本拼写遵循参考 Runner。JSON 报告会通过 starterTemplate: true 标识它。
保存和编辑属于客户端操作。编码会检查严格 JSON、安全整数文本、声明的版本和版本 3 的身份拼写;但不会验证完整的方言架构、将其映射到 pack、确认可执行源支持或验证准备情况。报告会标记为 encoded,并显示 fullDocumentConformance: false。单独的 validate 操作会检查版本 2 和版本 3 文档格式及内部引用:封闭成员、参数和依赖顺序、模板、读取、条件、目标冲突、准入项和文档限制。通过时会标记为 document-valid,并显示 validationScope: "version-2-document" 或 validationScope: "version-3-document";这并不代表符合准备验证器要求。不会检查依赖配置文件的兼容性(包括请求/适配器匹配)、获取和准备验证。
声明的 pack 清单覆盖情况可通过单独的 check 操作获取。
两种格式都支持 operation 和 selected-file 源。版本 3 还会检查未绑定的操作声明(platform、operation、shape、record),但不会解析或验证其绑定。部分声明以及混合的未绑定名称/配置文件固定项会被拒绝。版本 3 还会检查 research 问题、参数、带类型的请求字段、功能声明、配置文件分配结构和封闭的协调读取。版本 3 中的 http、sql 和 web 类型会返回不支持;未知类型会返回格式错误的文档错误。对于不支持的源,不会返回部分覆盖结果。
合约发现会公布 validationVersions、schemaVersions 和 packCheckVersions: [2, 3]、validationSourceKinds: ["operation", "selected-file", "research"]、unboundOperationValidation: true 以及 bindingVerification: false。
绑定和准备仍由 Runner 负责。这些整数格式版本并非制品发布版本。命名格式会单独公布为 formatVersions: ["2.0.0", "3.0.0"];它们要求提供 id 和字符串类型的制品 version。两种命名格式都使用严格的省略规则,并在规范字节中保留所有身份字段。它们对应的准备系列仍分别为整数 2 和 3。
jpack dialect init --format-version 3.0.0 --id urn:example:dialect:companies --artifact-version 1.0.0
jpack dialect schema --format-version 3.0.0
MCP dialect_init 接受 formatVersion、id 和 artifactVersion;get_dialect_schema 接受 formatVersion。切勿将命名选择器与旧版 version 参数(CLI 中的 --dialect-version)组合使用。这不会授权作业、执行发布或启用新的源类型。
Human init 和 canonicalize 会打印精确的规范文档字节,末尾不带换行符。Human digest 会打印 sha256:…,后跟换行符。JSON 输出会在其 document 字符串中包含精确的规范字节及其 digest,还会包含范围、诊断信息和固定引用。--pretty 只会改变外层 JSON 报告。规范化会保留成员和数组顺序;根据文档的规范规则,负零会变为零。分数、指数表示法、不安全整数、格式错误的 Unicode 和重复键都会被拒绝。准备阶段规范化和决策处置 JCS 是不同的形式,这些命令不会提供它们。
对应的 MCP 工具是 get_dialect_contract、dialect_init、
dialect_canonicalize、dialect_digest、dialect_validate、get_dialect_schema、
get_dialect_reference 和 dialect_check。它们接收文本,而非文件路径,
不会进行网络调用、读取项目、保存或评估。不支持的编码版本或已定义但不支持的源类型会返回 CLI 退出码 2;格式错误或超出限制的文档会返回 1;
错误的调用和读取失败使用现有的退出码 3 和 4。被拒绝的 MCP
操作会携带相同的结构化报告,并设置 isError: true。
方言编写资源和包覆盖情况
jpack dialect reference 会离线打印精确的固定配套文档。文本
包含提议中的形式;请查看 dialect contract 了解已实现的功能。
jpack dialect schema 会打印由 Runtime 派生的版本 2 或版本 3 JSON Schema 编辑辅助工具
(--dialect-version 3),而非规范性 Spec 工件。它无法强制执行严格的 JSON 拼写或
交叉引用;在将文档视为已检查之前,请运行 dialect validate。
JSON/MCP 资源报告会将文本的精确字节和 SHA-256 与方言标识分别列出。运行时不会获取任何资源。
jpack dialect schema > dialect-v2.schema.json
jpack dialect reference
jpack dialect check draft.dialect.json --pack decision.json --format json
check 会验证两个提供的文档,并将目标与 Runtime
现有的包清单进行比较。对于每个已查询的指针或证据要求,它会报告
mapped、partial、acknowledged 或 missing。祖先目标声明一个子树;子目标只能部分覆盖聚合读取。
显式的 unmapped 声明会保留在报告中。未声明的证据目标或遗漏会导致检查失败;未使用的事实目标和过时的遗漏会生成提示。
清单会过度近似读取范围,也可能包含形如条件的数据。
总体状态为 complete 或 review-required 时退出码为 0;在将映射视为完整之前,请检查状态和提示。incomplete 或 not-applicable 时退出码为 1;
不支持的功能会返回退出码 2。拒绝操作时不会输出部分覆盖结果。包的 SHA-256 会将报告绑定到提供的确切字节。valueTypesChecked 和
executionChecked 仍为 false:这并不能证明运行时事实存在、类型兼容、决策正确或源可运行。配置文件和准备验证仍由 Runner 负责。CLI 仅允许一个操作数使用 -;MCP 接收确切的 document 和 pack 字符串。两者都不会使用当前项目环境或更改文件。功能声明会列出支持的版本和输入/工作限制。有关范围和状态的详细信息,请参阅 ADR-0054。
Artifact 版本选项
jpack artifact version --base 0.1.0 --format json 会返回补丁、次版本
和主版本选项 0.1.1、0.2.0 和 1.0.0。可选参数 --candidate 会报告数值排序关系(lower、equal 或 greater)。等效的只读 MCP
工具是 get_artifact_version_options,参数为 base 和可选的 candidate。
两种传输方式都使用 pack 精确的三段式语法:不允许前导零、预发布后缀
或构建元数据。各段使用精确整数运算。
这是版本运算,而非兼容性分析或发布准入检查。它不会读取项目、制品、作业历史或注册表,不会预留版本,也不会保存任何内容。应用策略负责选择合适的版本升级幅度、验证用法并强制执行不可变发布。特别是,在作业中使用某个版本,不会隐式成为要求 Runtime 重写文档的指令。
该工具接受的每个版本最多为 256 字节,并会拒绝后续选项超出此限制的基础版本。此资源限制不会缩小 Core 架构的范围。输入无效时不会返回部分选项。范围和未检查兼容性的信息会在带内报告。请参阅 ADR-0055。
实验性离线 Policy 原型
jpack experimental policy 实现了 非规范性 RFC 0023 原型,确切版本为 0.0.2,用于处理 policy 和 governing-adoption 文档
(ADR-0059)。这个保留的
原型是实验性的编写辅助工具;其结果不代表任何批准、治理采纳权限或标准符合性。使用 experimental policy contract --format json 查看确切范围、
限制和固定的源修订版本。默认不选择稳定的 Policy 格式。
jpack experimental policy contract --format json
jpack experimental policy init --kind policy --format-version 0.0.2 --id urn:example:policy --version 1.0.0 > policy.json
jpack experimental policy schema --kind governing-adoption --format-version 0.0.2
jpack experimental policy validate policy.json --format json
jpack experimental policy canonicalize policy.json
jpack experimental policy digest policy.json
jpack experimental policy check policy.json --materials retained-materials.json --format json
init 会输出一个包含缺失保留材料的起始模板,并在其 JSON 报告中将这些材料标识为
starter-template;它不会生成经过检查的发布内容。面向用户的输出会在标准输出中以 JSON 形式保留模板,并在标准错误中打印缺失材料的说明。材料由客户端提供并保存。
架构资源是一个自包含的 Runtime 编辑副本,源自固定的原型架构;严格验证仍是独立操作。init 和 schema 都必须指定两个选择器;init 还必须提供工件 --id 和 --version,这两项与原型格式版本相互独立。
validate 会检查严格的文档形式、架构和本地引用。
check 还会验证所提供的保留材料引用闭包是否完全匹配、原始字节摘要和长度、Policy 章节锚点、结构化 Core 包,以及原型定义的特定消费者引用。它不会执行完整的 Core 语义验证,也不会评估规则。编码工具会检查规范数字域,并分别返回规范身份和原始字节身份。只有当引用明确要求规范身份时,所提供的 Core 包才必须采用规范编码。
必需的 --materials 输入是所提供字节的 私有 Runtime 传输格式,不是可移植的发布封装:
{"materials":[{"content":{"bytesDigest":"sha256:<64 lowercase hex>","byteLength":12,"mediaType":"text/plain"},"dataBase64":"<base64 of exact retained bytes>"}]}
示例展示了传输格式;请将其中的占位值替换为确切的内容引用和字节。它不接受其中包含路径或 URL。
CLI 只读取指定的有界常规文件,或表示标准输入的 -;标准输入操作数最多只能有一个。它不会隐式读取或写入项目文件。
文档大小上限为 256 KiB,保留源文件原件上限为 4 MiB,叙述材料和评审依据材料各自上限为 1 MiB,不同的保留字节总量上限为 16 MiB,材料 JSON 文本上限为 24 MiB。报告和错误信息不会回显保留字节。
MCP 对应工具及其较小的有效标准输入/输出封装限制,详见
MCP 客户端。
RFC、原型架构和合成测试夹具均从规范修订版本
8a56a95d555c17640d2db4984363b779536b3c2a 打包而来,并附有各文件摘要和许可来源信息。它们在运行时绝不会被获取。
官方 Policy 草案选择
同一组实验性命令明确支持独立发布的 Policy 草案 formatVersion: "1.0.0"
(ADR-0061)。资源
固定为 policy-v1.0.0-draft.1,对应的 Spec 提交为
0799b37b74e35c4a86bfbf70f7bee80bdb7bbe94,详见
官方来源清单。
完整的已发布存档按原始源路径保留,并包含各文件哈希、公有 HTTPS 架构、说明文本、完整的 124 行语料库、示例、参考读取器及其冻结依赖项。Runtime 会在架构编译前以及发布门禁中验证该清单,不会获取任何内容。
这是通过现有实验性接口提供的草案支持。Runtime 的符合性声明仍仅见于 CONFORMANCE.md。
默认 contract 输出和所有原型报告都保留现有字节和结构,以兼容严格客户端。显式发现会返回单独的 registryVersion: "1" 报告;选择单个契约时,则会返回该格式的来源信息和功能:
jpack experimental policy contract --all-formats --format json
jpack experimental policy contract --format-version 1.0.0 --format json
jpack experimental policy init --kind policy --format-version 1.0.0 --id urn:example:policy --version 7.3.42
jpack experimental policy schema --kind governing-adoption --format-version 1.0.0
jpack experimental policy check adoption.json --materials retained-materials.json --format json
--all-formats 与契约 --format-version 互斥。包含 formatVersion 的文档会显式选择草案语法;受支持的原型输入仍使用其精确包装格式。在 canonicalize/digest/validate/check 中可选的 --format-version 1.0.0 也会为格式错误或缺少选择器的输入启用草案拒绝处理。文档仍必须包含其精确选择器。任何工具都不会插入该选择器、迁移字节,也不会更改 Job 或审批。草案 Policy 使用 workspace-managed 或 externally-managed;desk-managed 会被拒绝。Artifact version 与格式选择器相互独立。草案采纳要求保留 1.0.0 Policy 字节;原型 Policy 无法满足这些引用。
显式 1.0.0 报告会标明 profile: "jps-policy-companion"、profileVersion 和 formatVersion: "1.0.0"、maturity: "draft"、不可变源代码提交及其 spec/policy.md URL。现有的 candidateCapabilities 成员现在包含精确的官方草案能力工件。只有完整的 check 会包含 candidateResult,其完整取值为以下之一:
{"status":"valid","formatVersion":"1.0.0","maturity":"draft"}
{"status":"refused","code":"invalid-selector"}
有限的拒绝代码和阶段顺序由固定的草案契约定义。Runtime 在成功时仍返回退出码 0,在内容无效时返回 1,在输入不受支持时返回 2;嵌套结果提供可移植分类。环境故障不会提供可移植结果。Canonicalize/digest 仅确立编码和身份;validate 检查文档形式和本地引用,不检查保留材料。这些范围更窄的报告会省略 candidateResult。validate 的范围为 closed-draft-document-and-local-references,check 的范围为 draft-supplied-exact-bytes-anchors-and-scoped-core-references。experimental 仍为 true,fullDocumentConformance、审批、执行、实时权限和网络获取能力仍为 false。完整的 Core 语义和评估不在这些检查范围内。
**从 Runtime v0.36.0 迁移:**显式 1.0.0 报告元数据从 proposed-draft 更改为 draft,并新增源代码固定项、URL、能力排除项和范围字符串。严格的报告使用方必须主动更新其 Runtime 和 Spec 固定项以及预期元数据。报告成员名称、输出/契约版本、拒绝代码以及精确的 Policy/采纳语法均保持不变。旧 Runtime 保留的候选报告会保留其原始来源和成熟度;它们是历史证据,绝不会被重新标记。旧的候选供应商目录树和原型字节保持冻结。晋级不会更改任何 Policy/采纳、Pack、源文件、叙述或审查依据字节。原型迁移需要单独的显式迁移、新的不可变身份和依赖方审查;不会隐式迁移任何内容。
草案架构报告会返回自包含的 Runtime 编辑副本,并带有新的、特定于发布版本的 URN $id;resource.sourceId 指向原始的不可变 https://judgmentpack.org/schema/policy/1.0.0/{kind}.schema.json 资源。编辑副本不会以上游 ID 提供。原始上游资源字节及其哈希仍保留在官方供应商目录树中。
Go 测试框架会比较全部 124 个官方可移植结果对象,按需获取向量源,并保留原始 Pack 数值和保留字节身份。未更改的参考读取器会针对同一保留存档运行。可移植测试使用共享的原始注册/检查引擎:不同字节的捆绑包可能超过私有的 24 MiB JSON/base64 载体或 MCP 的 16 MiB 请求限制,尤其是在多种媒体类型下重复使用字节时。这些上限保持不变。结果一致仅是同一供应商实现的证据,不确立稳定的成熟度、由不同主体独立编写的互操作性、审批、当前权限或许可。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。