跳转到内容

AMIR:Aira Modeling Intermediate Representation 规范:事务、诊断、证据与确定性

主文档与完整目录。本分篇与主文档共同构成同一规范,版本、状态与权威以主文档为准;仅拆分阅读结构,条款编号和正文语义不变。

10. Transaction Patch 与执行生命周期

Section titled “10. Transaction Patch 与执行生命周期”

AI、GUI 和插件不得直接修改 committed Revision。它们必须提交 domain Patch:

{
"projectId": "project:aira-example",
"branchId": "branch:main",
"transactionId": "tx:01K3EXAMPLE0000000000000000",
"patchId": "patch:01K3EXAMPLE00000000000000",
"idempotencyKey": "idem:01K3EXAMPLE000000000000000",
"documentId": "doc:plate-example",
"baseRevision": "rev:sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"policyId": "policy:authoritative-default/0.1.0",
"intent": "把板厚从 4 mm 改为 5 mm",
"operations": [
{
"op": "parameter.setValue",
"parameterId": "p.thickness",
"value": { "const": { "type": "Length", "value": "5", "unit": "mm" } }
}
],
"preconditions": [
{
"op": "revision.equals",
"value": "rev:sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
},
{
"op": "parameter.valueEquals",
"parameterId": "p.thickness",
"value": { "const": { "type": "Length", "value": "4", "unit": "mm" } }
}
]
}

统一 envelope 中:

  • projectId/documentId/branchId 确定写入作用域;commit 比较的是该 branch 的 head。
  • transactionId 标识一次状态机生命周期;重试同一请求必须复用它。
  • patchId 标识规范化语义修改;显式 rebase 必须形成带新 base/preconditions 的新 PatchId。
  • candidateId 由服务端在 Patch 应用和 canonicalize 后产生,必须为 candidate:sha256(SHA-256(JCS({documentId, branchId, baseRevision, patchHash, modelHash, authoringLockHash})));它不依赖未来的 RevisionId。
  • previewToken 与 validationToken 是有期限、不可跨 candidate/environment 使用的能力凭据,不是 RevisionId。
  • policyId 必须版本化,规定资源预算、必需 Assertions、最低 determinism、execution class 和 assurance profiles。

本版 Patch Operation 至少包括:

  • parameter.put、parameter.setValue、parameter.remove;
  • expression.put、expression.remove;
  • constraint.put、constraint.remove;
  • semanticRef.put、semanticRef.remove;
  • node.put、node.setInput、node.setLabel、node.remove;
  • body.put、body.setAuthority、body.setLabel、body.remove;
  • assertion.put、assertion.remove;
  • root.put、root.remove;
  • metadata.set。

Patch Operation 必须以稳定 ID 定位对象,禁止通过 JSON array index 定位。remove 默认不 cascade;若仍有依赖,必须失败为 DEPENDENTS_EXIST 并返回依赖列表。

规范生命周期为:

Patch
-> propose/static-check
-> Candidate Revision
-> preview
-> validate(authoritative)
-> commit(compare-and-swap)

preview 可以使用显式 interactive quality profile 生成较粗派生 Artifact,但不得把 coarse 证书当作 authoritative validation。Preview response 必须返回:

  • candidateId 与 patchHash;
  • 静态和执行 Diagnostics;
  • 参数/Feature DAG/Artifact diff;
  • 使用的 execution profile、ExecutionManifest hash、EvaluationId 与 candidate EvaluationBinding;
  • 可选视图、测量和 provisional certificates;
  • 绑定上述信息的 previewToken。

TransactionState 的唯一枚举为 proposed、planned、previewed、validating、validated、committing、committed、rejected、cancelled、expired。committed、rejected、cancelled 和 expired 是终态。proposed、planned、previewed、validating 和 validated 收到取消后必须进入 cancelled。committing 中的取消与 commit linearization point 竞争:若取消标记先持久化,则进入 cancelled;若 branch-head CAS 已先成功,则实际终态为 committed,取消请求返回 CANCEL_TOO_LATE。preview/validation token 到期且不再允许继续时进入 expired;validation 失败进入 rejected。实现不得用未定义的字符串扩展核心状态,扩展状态只能作为独立 progress detail。

validate 必须对同一 candidate、patch hash、settings、seed、Operation Catalog 和完整 ExecutionManifest 使用 authoritative profile,运行必需 Assertion,并返回 validationToken。ExecutionManifest 或任一绑定输入发生变化时 token 失效。

commit 必须:

  1. 重新验证 baseRevision 仍为目标 branch head;
  2. 重验所有 Patch precondition;
  3. 验证 validationToken 与 candidate 完全绑定且未过期;
  4. 确认不存在 error/fatal Diagnostic 和失败的 required Assertion;
  5. 原子写入新 committed Revision、Patch、provenance 和 authoritative certificates;
  6. 以 compare-and-swap 更新 branch head。

commit 的 linearization point 是同一存储事务内 branch-head CAS 成功的瞬间。在它之前不得对外观察到新 Revision;在它之后 commit 不可取消,只能通过新的 revert transaction 恢复。取消与 commit 竞争时,服务必须返回已经持久化的真实终态,不能声称取消成功后又发布 Revision。

Authoritative validation 先产生 candidate EvaluationBinding 与 provisional Certificate。Commit 确定新 RevisionId 后,必须在同一原子提交中写入指向相同 EvaluationId 的 Revision binding,并生成以 {revisionId} 为 source 的新 committed Certificate;原 candidate Certificate 保持不可变。若 EvaluationId 的任一输入已变化,则不得“换 source”冒充复用,必须重新 validate。

任一步失败都不得产生半提交 Revision。相同 idempotencyKey 在同一 Document + Branch 上只能对应相同的规范化请求体并产生同一个提交结果;同 key 不同请求体必须返回 IDEMPOTENCY_CONFLICT,重试不得重复应用。

若 head 已变化,必须返回 REVISION_CONFLICT,并提供 base/head RevisionId 和可重放 Patch;禁止自动把几何冲突静默合并。

程序节点的源码对 AMIR 不透明,因此对它的修改不能靠静态分析约束,而靠声明加实测:

  • 每个 replace-program 步骤必须携带 affects:本次修改允许改变、删除或新建的稳定名称集合;[] 声明不改变任何命名实体。
  • 宿主在 preview 时对每个命名实体实测 bounds、面积与体积,并统计 solid 数;任何未声明的改变、缺失或新增都使候选被拒绝, 诊断逐条列出 before/after 度量;同一几何换名的情形被识别为改名并要求声明双方。
  • set-parameters 步骤的 affects 可选:缺省时差异只报告不拒绝。
  • 守恒结果以 ExactCadConservationReport 返回给编辑方,随候选一起进入证据。

契约见 exact-cad-plan.ts, 实现见 apps/web/src/authoring/exact-cad-conservation.ts。这是 AMIR 在程序主路径上最重要的机制: 它把“重写源码”变成一次有边界、可拒绝、可审计的编辑。

Diagnostic 的机器语义由稳定 code 和结构化 payload 决定,本地化 message 只用于显示。

{
"id": "diag:01K3EXAMPLE00000000000000",
"code": "FILLET_RADIUS_TOO_LARGE",
"severity": "error",
"phase": "kernel",
"at": {
"nodeId": "n.outerFillet",
"port": "radius",
"jsonPointer": "/nodes/n.outerFillet/inputs/radius"
},
"context": {
"documentId": "doc:plate-example",
"transactionId": "tx:01K3EXAMPLE0000000000000000",
"candidateId": "candidate:sha256:...",
"evaluationId": "eval:sha256:..."
},
"messageKey": "geometry.fillet.radiusTooLarge",
"details": {
"requested": { "value": "12", "unit": "mm" },
"safeUpperBoundEstimate": { "value": "4.82", "unit": "mm" }
},
"relatedArtifacts": ["artifact:edge.outer.0"],
"retryability": "afterPatch",
"fixes": [
{
"kind": "patchTemplate",
"action": "reduceRadius",
"suggested": { "const": { "type": "Length", "value": "4.5", "unit": "mm" } }
}
]
}

规则:

  • severity 为 info、warning、error 或 fatal。
  • phase 为 schema、static、resolve、kernel、conversion、assertion、transaction 或 migration。
  • at 至少提供 NodeId、ParameterId、SemanticRefId、AssertionId 或 JSON Pointer 之一。
  • context 可包含 projectId、documentId、branchId、transactionId、candidateId、revisionId 与 evaluationId;存在时必须与承载该 Diagnostic 的请求/工件一致。
  • retryability 为 never、sameRequest、afterPatch 或 afterEnvironmentChange;它只描述安全重试条件,不授权自动修改模型。
  • fixes 只能是显式 Patch template 或人工操作建议,不得自动执行。
  • 同一输入和环境下 Diagnostics 必须按 severity, code, at, id 稳定排序。
  • 原始内核异常、地址和未结构化字符串不得成为唯一错误信息;adapter 必须映射为稳定 code,并可把已清理的原文放入 details.kernelMessage。

Diagnostic code 的唯一 registry 必须与 runtime/diagnostic.schema.json 同版本发布,并生成 Rust/TypeScript 常量与 conformance fixtures。代码一经发布不得复用于其他含义;RFC、adapter 和 UI 不得维护平行别名表。

ArtifactGraph 是一次特定 Evaluation 及其 Candidate/Revision source binding 产生的可持久化派生图,不属于 canonical authoring Document。【已实现】 ArtifactGraph;【未实现】 Source Map(本节后半部分为规范目标)。

每个 Artifact 至少记录:

{
"artifactId": "artifact:sha256:...",
"kind": "KernelShape",
"representation": "ExactSolid",
"source": { "revisionId": "rev:sha256:..." },
"evaluationId": "eval:sha256:...",
"executionManifestHash": "sha256:...",
"producedBy": { "node": "n.extrude", "port": "solid" },
"contentHash": "sha256:...",
"kernel": { "id": "occt-wasm", "version": "pinned", "buildHash": "sha256:..." },
"lifetime": "cache",
"extensions": {}
}

Artifact 的 source 使用与 Certificate 相同的互斥 union:{revisionId} 或 {candidateId, baseRevision, patchHash}。同一 content-addressed artifact 可以被多个 EvaluationBinding 引用,但每条 ArtifactGraph 记录必须明确自己的 evaluation/source 上下文。

ArtifactGraph edge kind 至少包括:

  • generatedFrom;
  • modifiedFrom;
  • splitFrom;
  • mergedFrom;
  • deletedFrom;
  • derivedFrom;
  • convertedFrom;
  • tessellatedFrom;
  • bakedFrom;
  • voxelizedFrom;
  • renderedFrom;
  • validatedFrom。

上述边统一从“结果、后代或 tombstone artifact”指向“来源或前代 artifact”。删除必须创建 tombstone artifact,再以 deletedFrom 指向被删除实体;禁止只从图中抹去旧实体。Operation/Node 的生产关系单独使用 producedBy。

ArtifactGraph 必须维护以下映射:

OriginAnchor
<-> AMIR node + port
<-> kernel artifact + sub-entity
<-> display primitive + triangle range

OriginAnchor 是 SourceSpan | JsonPointer | PatchOpId | ImportElementId 的 tagged union。只有存在对应 .aira 文本投影时才可以使用 SourceSpan;GUI/JSON Patch 和导入模型分别使用 JsonPointer/PatchOpId/ImportElementId。实现不得伪造不存在的源码范围。

Sub-entity ID 在同一 ArtifactGraph 内必须稳定;跨 Revision 的对应关系只能由 lineage edge 表达。禁止序列化裸指针、内存地址或仅在一个内核 session 中有效的 handle 作为长期 ID。

Artifact 可以被删除和重建。Artifact cache key 至少必须包含 model subgraph hash、Operation Catalog、kernel build、显式 tolerances、seed、execution profile 和平台相关 determinism inputs。

Geometry Certificate 是对某个 Artifact 在特定执行条件下已检查事实的不可变记录,不是数学证明。【部分实现】 exact→mesh 转换证书与 exact 会话的几何证据已产出;证书中的 determinism class 字段【未实现】(见 §14.2)。

{
"certificateVersion": "0.1.0",
"certificateId": "cert:sha256:...",
"subject": {
"artifactId": "artifact:sha256:...",
"artifactContentHash": "sha256:...",
"producedBy": { "node": "n.extrude", "port": "solid" }
},
"source": { "revisionId": "rev:sha256:..." },
"evaluationId": "eval:sha256:...",
"executionManifestHash": "sha256:...",
"executionClass": "authoritative",
"assuranceProfiles": ["geometric", "requirements"],
"representation": "ExactSolid",
"approximationClass": "exact-representation",
"inputArtifactsByLogicalKey": {
"profile": "artifact:sha256:..."
},
"kernel": {
"id": "occt-wasm",
"version": "pinned",
"buildHash": "sha256:...",
"features": []
},
"numericPolicy": {
"toleranceProfile": {
"profileId": "tol:standard-mm",
"profileVersion": "1.0.0",
"semanticProfileHash": "sha256:..."
},
"effectiveValues": {
"modelingLinear": { "value": "0.001", "unit": "mm" },
"modelingAngular": { "value": "0.01", "unit": "deg" },
"intersectionLinear": { "value": "0.001", "unit": "mm" },
"fuzzyBooleanLinear": { "value": "0.002", "unit": "mm" },
"sewingLinear": { "value": "0.002", "unit": "mm" },
"constraintLinearResidual": { "value": "0.0001", "unit": "mm" },
"constraintAngularResidual": { "value": "0.001", "unit": "deg" },
"validationDistance": { "value": "0.005", "unit": "mm" },
"quantityRelative": { "value": "0.000001", "unit": "1" }
},
"operationOverrides": []
},
"checks": {
"kernelValidity": "pass",
"watertight": "pass",
"manifold": "notApplicable",
"selfIntersection": "unknown"
},
"metrics": {
"bodyCount": 1,
"volume": { "value": "12800", "unit": "mm^3" }
},
"conversionHistory": [],
"provenanceCoverage": {
"mode": "kernelHistoryPlusRoles",
"coveredFraction": "1"
},
"determinism": "geometricWithinTolerance",
"diagnosticIds": []
}

executionClass 为 authoritative 或 preview。assuranceProfiles 是已通过的检查范围集合,本版标准值为 geometric、requirements、manufacturing、exchange;exchange 必须绑定导出 blob 与格式 profile。每项 check 的值为 pass、fail、unknown 或 notApplicable。未运行的检查必须是 unknown,禁止默认写成 pass。

source 是互斥 union:committed certificate 使用 {revisionId};提交前的 provisional certificate 使用 {candidateId, baseRevision, patchHash}。certificateId 必须覆盖完整 source binding,因此 candidate certificate 与 committed certificate 不是同一证书,即使它们引用同一 EvaluationId。

Certificate 至少必须包含:

  • subject artifact/content hash、source binding、EvaluationId、ExecutionManifest hash、inputArtifactsByLogicalKey、representation/approximation class、execution class 与 assurance profiles;
  • kernel 完整身份和 execution profile;
  • 单位、容差、Field/meshing 分辨率;
  • 适用于该表示的 validity、watertight、manifold、自交、空壳、负体积或退化检查;
  • body/component/face/edge/triangle 等适用计数;
  • conversion history 及误差预算的 requested/achieved/bound class;
  • provenance coverage;
  • determinism class 和 Diagnostic 引用。

Field Certificate 还必须记录 field kind、mathematicalDomain、surfaceBounds、本次 evaluationClip/meshingBounds、value type、inside sign、Lipschitz bound 和 gradient mode。Assembly Certificate 必须记录未解析 mate、instance cycle 检查和干涉检查策略。

ExactSolid Certificate 只能证明“内核在给定 tolerance 下报告有效”等已检查事实;不得把类型名解释成精确实数证明。MeshSolid 的 manifold pass 也不自动意味着无自交,二者必须是独立 check。

AMIR 的 hash 流水线固定为:

  1. 结构和语义验证;canonical AMIR 中所有语义字符串必须已经是 Unicode NFC,非 NFC 输入在进入 canonical form 前规范化并产生可见 diff。
  2. 按字段定义构造 semantic projection,而不是对原始 Document 做通用“删除几个 key”的递归猜测。
  3. 使用第 4.3 节的 decimal grammar;跨语言实现不得先转为宿主浮点再参与 hash。
  4. 对 semantic projection 应用 RFC 8785 JSON Canonicalization Scheme(JCS)。
  5. 对 JCS UTF-8 bytes 计算 SHA-256。

实现必须计算两个 hash:

  • modelHash:语义 payload 包含 amirVersion、settings.coordinateSystem、settings.tolerances、settings.fieldConvention、parameters、nodes、bodies、assertions、roots,以及标记为 semantic 的 extensions;排除 $schema、revision、metadata、所有 label、provenance、kernelHints、settings.units 显示默认值和非语义 extensions。kernelRequirements、operation/version、role、authority 与所有几何/误差 input 必须包含。文档级三个恒空占位已从当前契约和投影一起删除;其旧模型 hash 及派生身份不再被接受。
  • revisionHash:对精确包含 documentId、modelHash、parents、patchHash、authoringLockHash、actor 和 createdAt 的 Revision hash manifest 做 JCS + SHA-256;计算时排除 revision.id、state 与 operationCatalog。RevisionId 为 rev:sha256:<revisionHash>。【实现】 当前 Rust Core 由上述七项生成并在恢复时复核身份;已删除旧迁移槽位,其旧修订身份不再被接受。本次三个实际事务修订通过 Rust/TypeScript 规范哈希交叉核验,完整发布语料的范围见下文。

改变 label、说明或显示默认单位可以产生新 Revision,但不应改变 modelHash。改变几何常量的单位字面量即使物理值等价,也会改变 modelHash;formatter 如需单位归一化,必须产生显式 Patch。

AMIR 的 schema release 必须附带跨 Rust、TypeScript 与至少一个独立实现的 hash fixtures,覆盖字段重排、Unicode、decimal、label/kernelHints 排除、semantic extension 和等价非规范输入;fixtures 未通过时实现不得产生 committed RevisionId。【未实现】 原 fixtures/model-hash/ 与 fixtures/revision-hash/ 语料全部是 AMIR 0.1 的 mesh 文档,已随 0.1–0.3 兼容线于 2026-09-08 删除; 0.4 的跨语言 hash 语料尚未建立,连同第三个独立实现一起,仍是 release 前的未关闭前置条件。

每次 authoritative evaluation 必须固定:

  • AMIR、Operation Catalog 和 schema 版本;
  • kernel ID、版本、build hash 和编译特性;
  • settings、所有显式 tolerance 和转换参数;
  • seed;
  • 外部输入内容 hash;
  • execution profile 和影响数值的硬件/后端能力。

禁止读取当前时间、locale、随机设备、网络响应或未锁定文件。并行实现必须使用稳定归约和稳定输出排序。

【未实现】 以下确定性等级尚无实现,任何 Certificate 目前都不携带该字段;在内容寻址缓存跨会话命中之前必须补齐。Certificate 的 determinism class 为:

  • bitwise:相同环境输出 bytes 相同;
  • topologyStable:拓扑和语义角色稳定,数值在 tolerance 内;
  • geometricWithinTolerance:几何距离在声明 tolerance 内,不承诺相同 tessellation/topology 编号;
  • none:不满足以上任何级别,只允许 preview;authoritative commit 必须拒绝。

用于 determinismAtLeast 比较的顺序为 none < geometricWithinTolerance < topologyStable < bitwise。Authoritative commit 至少要求 geometricWithinTolerance。该顺序只描述可重复性强度,不代替几何有效性检查。

实现不得把常见浮点几何内核错误地宣称为跨平台 bitwise deterministic。

Revision 必须保留创建它的 PatchId、actor、intent 摘要或其 hash、父版本和 authoringLockHash;它不得把具体 kernel/platform build 混入模型身份。EvaluationBinding、ExecutionManifest 与 Geometry Certificate 另行保存执行环境和验证证据。Node 的 provenance.createdBy 应指向 PatchId;导入 Node 必须记录源内容 SHA-256、媒体类型、解析器版本及可选来源 URI。

AI prompt 可以因隐私策略只保存 hash 和结构化 intent;若保存原文必须由上层产品明确授权。Provenance 数据是审计数据,不得被内核解释为建模指令。