Preflight 是 execute 之前的机械就绪门。它回答:本次 Run 引用的对象能否解析、每个 stage 与 lifecycle handler 是否已有实现 binding、实现声明的 Requirement 在当前 workspace 和环境中是否可用。
Preflight 不是顶层 kind。检查结果写入 Run.status.conditions、Run.status.preflight,详细证据保存为 type: huoban.dev/preflight-report 的 Artifact。
完整执行前链路
dryRun 不等于 Preflight,Preflight 也不等于授权。三者回答不同问题:计划是什么、环境是否就绪、行为是否允许。
Run scope 与 stage scope
Run scope 检查完整 Run;stage scope 只用于定位某个阶段的阻塞原因。Run.spec 对应的 Run scope 证据。
Resolution 与 Readiness
每个 check 分成两个正交状态:| 状态 | 问题 | 例子 |
|---|---|---|
| Resolution | 目标是否声明完整、引用能否定位? | binding 指向的 Skill 是否存在且提供所需 capability。 |
| Readiness | 当前环境是否满足目标? | executable 是否可执行、MCP tool 是否能被发现。 |
True、False、Unknown:
False:检查得到明确的不满足结果。Unknown:当前检查模式无法得出权威结论。例如 offline 模式不会联网发现 MCP tool。True:检查在当前范围与时刻观察到满足。
False 时,聚合 condition 为 False;出现 Unknown 且没有 False 时,聚合 condition 保持 Unknown。二者都会阻断 execute gate。可选依赖仍记录证据,但不单独阻断。
Offline 与 live
默认 offline 是安全边界,不只是性能选项。| 模式 | 行为 |
|---|---|
默认 / --offline | 检查 schema、workspace refs、路径、executable、credential 名称和 runner capability;动态网络目标通常保留 Unknown。 |
--live | 对远程 context source 执行只读 HEAD;对声明的 MCP endpoint 执行有限、只读、超时受控的 initialize 与 discovery;不调用业务 tool。 |
tools/call。远程 context source 只允许 HEAD。MCP 请求每次最多等待 5 秒、列表发现最多读取 20 页、单次响应体上限为 1 MiB。报告会去除 URL user info、query、fragment、常见 credential 形式和远端 MCP error text。网络可达也不代表来源可信或行为已获授权。
Freshness 与失效
动态事实会变化。Requirement 的freshness.maxAgeSeconds 用来计算报告的 validUntil。执行器不得复用已过期报告,也不得把不同 Run.spec 的报告套用到当前 Run。
snapshotHash 哈希的是当前 Run.spec,用于关联报告与 Run 声明。权威 Preflight 还会逐项重算 flowSpecHash、profileRefHash、policyRefHash 和 bindingHash。这些 hash 不归档被绑定 Skill 或 Adapter 的完整内容,报告本身也未签名;执行实现仍需使用可信时钟、比较 hash 并拒绝过期或被修改的证据。
证据落点
Preflight 的最小证据链包括:Run.status.conditions中的Resolved与PreflightReady摘要。Run.status.preflight中的 scope、snapshotHash、checkedAt、可选 validUntil 与 reportRef。- Preflight Report Artifact 中的逐项 checks。
失败语义
执行前缺失依赖属于Blocked,不是 stage 业务失败。此时 stage 尚未开始,不能伪造 stage.failed,也不能创建 Checkpoint 让人“批准忽略”必需依赖。
fallback 只有在 Run 中显式锁定、能力匹配且同样通过 Preflight 时才可用。临时热切换实现会使现有报告与 Run snapshot 失真。