Validation — 结构校验契约
Status: Target design
⚠️ Protected Contract Layer — 本文档定义 Gaia IR 的结构校验边界。它回答“什么样的 IR 是合法的”,而不是“某个 backend 如何运行它”。
目的
Gaia IR 的 validation 用来阻止 contract-invalid 的图进入后续阶段。
它主要覆盖三类问题:
- schema 是否完整
- 引用与层级是否自洽
- 图是否满足 Gaia IR 的结构不变量
validation 的职责是验证结构合法性。
它不负责:
- 参数值如何选择
- BP 是否收敛
- 某个 backend 的运行时诊断
- 跨 package 的同题判断、重复计数审查或 registry 侧对齐结论
这些属于相邻层。
1. 校验分层
建议把校验分成 3 层:
- 对象级校验
单个
Knowledge/Operator/Strategy/FormalExpr是否自洽 - 图级校验
一个
LocalCanonicalGraph内部引用是否闭合、scope 是否一致 - 相邻层完整性校验 例如 parameterization completeness、lowering preconditions
本文件主要定义前 2 层。第 3 层只做边界说明。
2. Knowledge 校验
对每个 Knowledge,至少应检查:
id必须为有效 QID 格式{namespace}:{package_name}::{label},label 字符集允许[A-Za-z_][A-Za-z0-9_]*(详见 03-identity-and-hashing.md §2.1)type属于gaia.engine.ir.KnowledgeType允许集合:claim(唯一携带 prior + belief 的类型)note(v0.5 推荐替代setting的非概率背景说明)composition(结构组合;必须带template_name/template_version/sub_knowledge/conclusion)setting(legacy 非概率背景)question(待研究方向)context(legacy 非概率范围限定)content_hash由 Knowledge model 构造时保证(Pydantic model_validator);graph-level validator 不重复检查;hash 公式见 03-identity-and-hashing.md §3- 若某处把它当作可取真值命题引用(如 Operator
variables/conclusion或 Strategypremises/conclusion),则其type必须是claim - 含
parameters的 claim 仍然是 claim,不是独立类型 - helper claim 仍然是
claim,不能引入新的 Knowledge primitive - 结构型 helper claim 不应携带独立 prior;当前 validator 硬拒绝 structural-expression helper 上的
metadata["prior"],更宽的 PriorRecord 入口由 package compile/check 与 review 规则约束(见 04-helper-claims.md) composition的sub_knowledge/conclusiongraph-closure 约束是设计不变量;当前 graph-level validator 只校验字段形态,尚未解析这些引用或强制conclusion指向claimlabel在同一LocalCanonicalGraph内必须唯一LocalCanonicalGraph.namespace/package_name约束自动生成的本地 QID;显式写入的 foreign QID 允许作为 external reference 出现在 graph 中- graph-level closure 的对象是"显式出现在 graph 中的节点集合",因此 imported external occurrence 若被引用,也必须作为
Knowledge显式存在于该 graph 中
3. Operator 校验
对每个 Operator,至少应检查:
- 顶层 Operator 必须设置
operator_id(lco_前缀)和scope,且scope必须与所属LocalCanonicalGraph.scope一致;嵌入在FormalStrategy.formal_expr.operators[]内的 Operator 是表达式片段,可省略operator_id与scope,由宿主 FormalStrategy 拥有(实现见gaia.engine.ir.validator._validate_operators) variables中所有 ID 都必须引用同 graph 中存在的 Knowledgevariables中的 Knowledge 必须全部是claimconclusion必须引用同 graph 中存在的claimconclusion不得出现在variables中——variables只放输入,conclusion独立承载输出- Operator 分为三类(见 02-gaia-ir.md §2.4):
- Directed(
implication):conclusion是结构型 implication helper claim(如implies(A,B)型) - Expression(
negation、conjunction、disjunction):conclusion是结构型计算结果 helper claim(如合取输出M = A ∧ B) - Relation(
equivalence、contradiction、complement):conclusion是结构型 warrant helper claim - 关系型 Operator 的
conclusion不允许被作者借来手写任意主观结论 - 若
metadata.canonical_name缺失或未采用推荐 functor 形式,当前更适合作为 warning / lint,而不是 hard error
这里的 “同 graph 中存在” 指的是 引用闭合,不是 ownership 相同。
也就是说,Operator 可以连接 imported claim,只要这些 imported claim 已被显式放入 graph。
helper claim 的命名纪律见 04-helper-claims.md。
4. Strategy 校验
对每个 Strategy,至少应检查:
strategy_id必须使用lcs_前缀premises中的 Knowledge 必须全部是claimconclusion若非空,必须引用claimbackground可引用任意允许类型type必须属于允许集合(与gaia/engine/ir/strategy.py::StrategyType同步,共 14 个):infer|associate|noisy_and(deprecated → 编译时自动转support,发DeprecationWarning,仍接受) |deduction|reductio(deferred) |elimination|mathematical_induction|case_analysis|abduction|analogy|extrapolation|support|compare|induction- 三种形态互斥:
- 基本 Strategy:无
sub_strategies,无formal_expr CompositeStrategy:必须有非空sub_strategiesFormalStrategy:必须有formal_exprsub_strategies与formal_expr不得同时出现sub_strategies中的每个值都必须引用同 graph 中存在的strategy_idsub_strategies引用关系必须构成 DAG(无环)noisy_and不应用来压平命名策略的整体语义
与 Operator 一样,Strategy 的 premises / conclusion / background 只检查图内闭合和类型约束,不检查这些 Knowledge 是否都属于当前 graph owner。
5. Compose 验证
对每个 Compose(实现见 gaia.engine.ir.validator._validate_one_compose / _validate_compose_dag),至少应检查:
compose_id必须以lcm_前缀开头inputs / background / warrants中的所有 ID 必须引用同 graph 中存在的Knowledgeconclusion必须引用同 graph 中存在的Knowledge,且其type必须是claimactions中的每个 ID 必须引用同 graph 中存在的Knowledge、Operator(lco_)、Strategy(lcs_)或其他Compose(lcm_);其中 Operator 与 Strategy 仅当其 ID 已显式赋值时才能被 Compose 引用actions中不得包含compose.compose_id自身(不允许自引用)- 多个 Compose 之间通过
actions形成的引用关系必须构成 DAG——gaia.engine.ir.validator._validate_compose_dag会沿这些边做循环检测,发现环时给出 cycle 路径
6. FormalExpr 校验
对每个 FormalExpr,至少应检查:
- 只包含
Operator - 所有内部 Operator 满足各自的 Operator 校验规则
- 内部 Operator 引用关系必须构成 DAG(无环)
- 其引用到的中间 claim 必须在同 graph 中显式存在
- 私有中间节点(不出现在任何 Strategy 的
premises/conclusion中)禁止被外部 Strategy 引用——违反时报 error(见 04-helper-claims.md) - 引用闭合性:FormalExpr 内每个 Operator 的
variables和conclusion所引用的 claim,必须属于以下三类之一——否则报 error: - 该 FormalStrategy 的
premises(接口输入) - 该 FormalStrategy 的
conclusion(接口输出) - 同一 FormalExpr 内另一个 Operator 的
conclusion(内部中间节点)
7. Graph 校验
对每个 graph,至少应检查:
scope与所有对象 ID 格式一致- 图内所有引用都闭合
- 不允许引用未在当前 graph 中显式物化的对象;external reference 若参与引用,也必须先作为
Knowledge出现在当前 graph 中 ir_hash若定义,则必须与 canonical serialization 一致- 同一 graph 内不应出现重复 ID
namespace是自由字符串;validator 不限制为固定集合,只校验对象 ID / QID 形状和 graph-local 引用闭包
identity 与 hashing 的细节见 03-identity-and-hashing.md。
8. LocalCanonicalGraph 校验
至少应检查:
steps允许存在- 内容字段允许完整保留
- Knowledge 使用 QID 格式;Strategy 使用
lcs_;顶层 Operator 使用lco_;Compose 使用lcm_ gaia._meta.IR_SCHEMA在与 LKM 等下游交换 IR 时通过check_ir_compat校验前缀(详见 06-parameterization.md "与 IR schema 版本的关系" 段);schema 形状漂移时 pre-push 钩子scripts/check_ir_schema_bump.py强制要求 bump
9. 与相邻层的边界
以下内容不是 Gaia IR core validation,但通常会在相邻层一起检查:
- parameterization completeness
- lowering preconditions
- backend runtime diagnostics
- BP convergence
这些分别见:
10. 推荐输出形式
一个 validator 至少应能输出:
valid: boolerrors: list[...]warnings: list[...]
其中:
- error 表示 contract-invalid,必须阻止后续流程
- warning 表示 contract-valid 但存在风险、兼容性问题或未来可能收紧的行为
11. 当前仍待细化的点
- canonical serialization 的标准化顺序与
ir_hash精确定义 - helper claim 的标准命名是否需要更强约束
strategy_id/operator_id的规范生成算法是否写成强约束