# Brain → Sense 运行与健康状态契约 v1 本目录是 Brain 运行状态到 Sense 运维投影的版本化事实源。Brain 只发布脱敏状态事实;Sense 不读取 Brain 的缓存、数据库或内部运行对象,也不能借此契约执行远程命令。 ## 消息与时间语义 - `schema_version` 固定为 `yovision.runtime-status/v1`。生产者必须先通过 `runtime-status.schema.json` 再发布。 - `status_id` 是消息幂等键;`sequence` 在单个 `brain_instance_ref` 内单调递增。重复消息可忽略;小于当前已保存 sequence 的消息不得覆盖投影。 - `observed_at` 是 Brain 完成该次观测的 UTC RFC 3339 时间,不是 Sense 的接收时间。允许最大 30 秒未来时钟偏差;超过时拒绝该消息,并保留最后已知投影。 - Brain 的推荐发布周期是 30 秒。Sense 以 `evaluation_time - observed_at > 90 秒` 推导 `stale`;恰好 90 秒仍为 fresh。`stale` 和 `offline` 都是 Sense 的传输/时间投影,不是 Brain 写入的运行状态。 - 未收到任何有效状态时显示 `not_received`;传输断开但最后状态未过期时显示 `offline_fresh`;传输断开或无新消息且超过 90 秒时显示 `offline_stale` / `stale`,同时保留最后已知状态及其观测时间。 ## 状态机 Brain 报告的 `runtime.state` 和每个输入的 `state` 使用同一枚举: | 状态 | 含义 | 允许的下一状态 | |---|---|---| | `unconfigured` | 尚无可运行配置 | `starting`, `stopped` | | `starting` | 已接受启动,资源准备中 | `running`, `degraded`, `failed`, `stopped` | | `running` | 正常提供推理 | `degraded`, `failed`, `stopped` | | `degraded` | 仍提供有限服务 | `running`, `failed`, `stopped` | | `failed` | 无法继续提供服务 | `starting`, `stopped` | | `stopped` | 已有序停止 | `starting`, `unconfigured` | 首次有效消息可为任一状态;Sense 只校验同实例连续消息的迁移。`stale`、`offline_*` 不参与 Brain 状态迁移。恢复连接后,只有 schema、时间、sequence 和状态迁移均有效的新消息才能更新投影。 ## 配置流与 revision `configurations` 按 #148 的配置流报告,可以为空,也可以包含多个配置。每项 `config_id` 必须唯一,并与 `yovision.source-config/v1` 的 `config_id` 一致;重复 ID 使整条状态无效,不能覆盖最后已知投影。`applied_revision` 是 Brain 对该配置流已实际应用的 integer revision。Sense 必须逐个 `config_id` 与自己已投递的期望 revision 比较:相等为 synchronized,不相等为 mismatch;Sense 的期望 revision 不进入本消息,避免产生第二事实源。 - `not_configured`:尚未应用该配置,revision 必须为 null。 - `applying`:正在应用;revision 为 null 或仍在运行的上一个 revision。 - `applied`:应用成功,revision 必须是大于等于 1 的整数。 - `rejected`:本次应用被拒绝;revision 为 null 或最后成功 revision,且必须带稳定错误码。 ## 兼容与回退 - v1 字段语义冻结,未知字段被拒绝。新增可选字段或错误码前必须更新本契约及双方测试;改变字段语义或删除字段发布新主版本。 - 消费者必须按 `schema_version` 先分派到对应版本验证器。未知主版本停止摄取并记录 `UNSUPPORTED_SCHEMA_VERSION`,不得清空或覆盖最后已知投影。 - 回退时 Sense 停止摄取新版本,继续使用上一冻结版本的 adapter 和最后已知投影。回退不触发 Brain 重启或运行态修改。 ## 安全边界 只允许 Schema 列出的字段。逻辑引用不允许 `/` 或 `\\`,因此不能携带绝对路径。消息不得包含凭据/token、堆栈、内部路径、用户会话、客户视频/图像、人脸信息或业务 Alert。结构化错误只传稳定错误码,不传自由文本错误详情。 错误码、映射责任和可复制验证分别见 `error-codes.md`、`mapping.md` 与 `../../tests/runtime-status-v1/README.md`。