阶段二十:Agent 运行态势与四层闭环
阶段状态:进行中
计划状态:实施中
当前工作包:P20-5-11 生产页面与 API 最终回读(已完成)
用户已确认按本计划开始执行。P20-0 至 P20-4 已完成本地门禁、精确 SHA 构建、RR 生产部署、生产 API 回读,以及使用临时管理员 API Key 的公网桌面与移动端浏览器验收。
📌 结论摘要
P20 第一版在 Console 中建立“Agent 运行态势”只读总图:把原本分散在节点、网络、CPA、Memory、Web Fetch、Web Search、规则、技能和工具配置中的状态,组织成一张人能看懂的跨域关系图。页面回答三个问题:整个 Agent 系统现在处于什么状态、哪个节点或服务影响了结果、一次对话的四层路由闭环断在什么位置。
后端已实现管理员只读聚合、逐源状态、新鲜度判断和脱敏投影;前端已实现四域关系图、六阶段闭环、节点矩阵、异常列表、30 秒刷新和移动端布局。真实 101 数据投影已验证:101 基线与 Memory 回写可见;明确主机离线的节点显示“离线”并从异常列表排除,在线节点的工具断点仍显示“需关注”;Web Fetch 与 Web Search 只有健康响应、没有最近真实调用证据时显示“未验证”。审计发现的具体故障仍只展示,不在本阶段修复。
状态语义规则:主机离线是可达性状态,不是当前可执行的处理项,因此单独显示“离线”;只有主机在线后,客户端心跳、中央路由、工具目录、规则技能和四层闭环证据才参与“需关注、阻塞、未验证或已过期”的处理判断。节点恢复在线后自动重新计算,不保留离线期间的旧问题作为当前待处理项。
用户在生产截图评审后要求关系图缩小并补充颜色说明。当前桌面端关系图最大宽度已限制为 960px 并居中,图下新增五项图例:正常、需关注、阻塞、未验证、已过期;图例同时写明每类含义,不再只依赖颜色。
用户进一步确认了 P20-5 的中央管理目标:规则和技能在 Memory 中统一管理,通过不可变 Release 分发到各节点的 Codex 运行时镜像,再由 Hook 在 turn 内验证实际加载。P20-4 的现有页面保留,P20-5 完成后再把中央期望、节点安装和 turn 运行统一展示。
🗂️ 目录
- 计划状态与工作边界
- 问题背景与目标
- 总体架构图
- 四个状态域
- 四层功能路由闭环
- 节点、配置与中心服务关系
- 只读页面规划
- 数据、状态与更新策略
- 工作包与依赖
- P20-5 规则与技能中央管理计划
- 实施前评审门
- 验收、回退与风险
- 未决项 / 需要用户决策
🧾 计划状态与工作边界
| 项目 | 当前值 | 依据 | 影响 / 下一步 |
|---|---|---|---|
| 当前阶段 | P20:Agent 运行态势与四层闭环 | docs/plans/state.json |
P20-4 已发布,P20-5 进入实施 |
| 阶段状态 | 进行中 | P20-4 已完成,P20-5 分发器与中枢面板已落地 | 冲突资产对账完成后评估阶段出口 |
| 计划状态 | 实施中 | 用户确认按 P20-5 计划开始实施 | P20-4 保持已发布,P20-5 按工作包推进 |
| 当前工作包 | P20-5-11 生产页面、API、节点心跳和网页能力表格最终回读 |
P20-5 工作包 | 已完成管理员 API 与真实浏览器双重验收;RR 两容器目标 SHA 5e1dd061 且健康;8 个客户端均返回 web_capabilities;OfficeSummer 离线单独保留 |
| 本轮修订 | P20-5-12 运行态势对象三分与证据口径收敛 |
2026-11-04 用户评审确认三分类方案 | 代码与本地测试完成;生产部署、节点心跳刷新和 Memory 项目侧契约仍未收口,详见文末同名章节 |
| P19 | 临时收口、可重启,不宣称完整验收 | completed-phase-19-temporary-closure.md |
未来重启 P19 时从原计划继续,不与 P20 混写 |
| 当前实现 | 本地门禁、同 SHA 镜像构建、RR 主生产部署和最终页面/API 验收通过 | 管理员会话 role=admin;runtime-status HTTP 200;真实浏览器确认网页能力表格 |
P20-5-11 完成;OfficeSummer 仍按离线状态观察 |
P20-4 第一版不包含:修复审计异常、更新节点规则、发布技能、扩散 MCP、重启中心服务、修改 Memory 数据、建立第二套告警系统、恢复旧治理 API/observer、提供页面写操作。P20-5 只新增受控的资产 Release 与节点分发,不恢复旧治理系统;运行态势页面继续只读。
🎯 目标、成果与验收契约
背景
“从节点到 Agent”的讨论先出现了中央服务部署、Agent 客户端安装和 Agent 对齐配置。现在状态域进一步收敛为:中央模型路由、中央服务、Agent 客户端、中央配置与节点镜像。Memory 是规则和技能的中央管理权威,Codex 节点保存经过验证的本地运行时镜像;101 是第一个完整基准和分发 canary,但不再是分散手工配置的终点。Memory 历史记录 6ed6e777d30cb98c1acbc585e489cfe05adc2485e0fcb0ed88c1721f127fadd6 与 6377731c06a6a199c0f8d56d24ab7ebe3b5a9952dacd98b2114a0a0ddd5b88eb 是本计划的讨论依据,但历史快照不能直接代替当前实时状态。
另一条讨论线是配置更新与扩散:Memory 作为中央编辑和版本管理面,发布不可变 Release;101 先作为 canary 接收并验证,通过后再向其他 Codex 节点分发。P20-5 不仅要展示中央资产,还要展示 Release、节点安装、本地镜像和 turn 实际加载的完整状态链。
目标与非目标
| 类型 | 本阶段定义 | 下一步 |
|---|---|---|
| 目标 1 | 形成四个状态域的跨域总图 | 中央配置域显示期望、安装、运行三层证据 |
| 目标 2 | 显示四层功能路由闭环的断点 | 区分规则、Memory Bootstrap、技能、工具、执行/验证、Memory 回写 |
| 目标 3 | 把 Memory 中央资产、Release、节点分发、Codex 镜像和 Agent 客户端连成关系网 | 主机在线、Agent 在线和规则/技能已加载分开 |
| 目标 4 | 动态只读刷新,未知不得显示为正常 | 后续处置回到已有管理页面 |
| 非目标 | 立即修复审计发现的问题 | 等用户评审后另立实施工作包 |
🧱 技术栈与架构选型
P20 采用“Memory 中央管理 → 不可变 Release → 节点分发与本地镜像 → turn 运行证据 → 只读状态投影”的结构。浏览器不直连 Tailnet 服务,不持有内部凭据;API Gateway 只负责查询和归一化,不成为第二控制面。Memory 管理资产,节点分发器负责安装,Codex Hook 负责运行时校验,P20 页面只展示三种状态之间的关系。
flowchart TB
Author["Memory 中央管理\n规则集 / 技能资产 / 平台 / 范围"] --> Release["不可变 Release\n版本 / SHA256 / 目标 / dry-run"]
Release --> Distributor["节点资产分发器\n拉取 / 校验 / 原子安装 / 回执"]
Distributor --> Mirror["Codex 运行时镜像\nAGENTS.md / 受管 SKILL.md"]
Mirror --> Hook["Codex Hook\n规则匹配 / 技能正文校验 / RouteContext"]
Hook --> Runtime["Turn 实际运行\n选择 / 工具 allowlist / 执行验收"]
Release --> Gateway["API Gateway:只读聚合"]
Distributor --> Gateway
Hook --> Gateway
Runtime --> Gateway
Gateway --> Console["P20 状态投影\n中央期望 / 节点安装 / Turn 运行 / 漂移"]
架构取舍
| 方案 | 可维护性 | 部署复杂度 | 性能与扩展性 | 结论 |
|---|---|---|---|---|
| Console 直接访问每个内部服务 | 低,前端重复理解协议 | 高,需暴露多个边界 | 难统一缓存与状态语义 | 不采用 |
| 新建独立治理/observer 系统 | 低,会形成第二事实源 | 高,增加服务、数据和回退面 | 初期灵活,长期漂移 | 不采用 |
| API Gateway 只读聚合 + Console 投影 | 高,沿用现有边界 | 中,只增加一个查询面 | 可按 TTL、并发和新数据源扩展 | 计划采用 |
🧩 分布式底座接入声明
本阶段接入现有 Console、API Gateway、CPA、Memory、Web Fetch、Web Search、节点登记与 Agent 心跳。不新增 Nomad Job、Worker 或数据库;API Gateway 在进程内并发执行有界只读查询并做归一化,Console 只消费一个管理员接口。
| 使用层 | 计划判断 | 依据与边界 |
|---|---|---|
| Network | 沿用现有内网与受控服务访问 | 浏览器不直连 Tailnet 服务;不新增公网入口 |
| Nomad | 本阶段不接入 | 不创建 Job,Nomad 仍是唯一任务调度器 |
| Compute | 复用 API Gateway 进程内有界查询 | 不新增 Worker、定时任务或独立 observer |
| Storage | 本阶段不新增 | 不建立新数据库或复制现有业务状态 |
| Observability | 只读复用已有健康、心跳和真实调用证据 | 只展示,不执行修复或形成第二事实源 |
| Adapter | 当前不新增 | 查询与归一化保持在 API Gateway 内,不改变 Runtime Adapter 边界 |
| 凭据 | 保留在现有服务端 | 浏览器、模型、普通 Agent 和 MCP 不获得基础设施凭据 |
| 生命周期 | 查询、缓存、刷新和过期状态均有界 | 故障仅标记未知/过期,不触发配置变更 |
🧩 四个状态域
四个状态域是“观察对象的分类”,不是四层闭环的替代物。每个状态域均应显示一个人类可读结论、影响范围、最近真实验证和下一处理入口;缺少证据时显示“未验证”或“过期”,不能显示为绿色正常。
| 状态域 | 要回答的问题 | 计划显示 | 状态边界 |
|---|---|---|---|
| 中央模型路由 | CPA 是否可用,Agent 是否有可用模型入口,以及每个客户端是否正确指向它 | CPA 健康、CPA 版本、中央模型目录、逐节点 config.toml 路由、模型目录指纹、真实 /models 探测 |
CPA 健康不等于每个 Agent 客户端配置正确;客户端目录与 CPA 实际目录不一致时显示“需关注” |
| 中央服务 | Memory、Web Fetch、Web Search 等服务是否存在且可验证 | 服务健康、服务版本、工具面、最近真实调用、客户端连接 | configured 不等于 verified;服务健康不等于客户端在线 |
| Agent 客户端 | 哪些节点的 Agent 真正在线 | 主机在线、Agent 心跳、版本、节点角色、闭环摘要 | 主机在线与 Agent 在线分列显示 |
| 中央配置与节点镜像 | Memory 发布内容是否安装到节点,并被当前 turn 实际加载 | Release/版本/哈希、Codex 版本、Memory 版本、CPA 版本、节点安装回执、Codex 镜像、规则/技能选择与加载 | 中央资产存在、节点已安装、当前 turn 已加载是三件事;版本一致不能替代功能验证 |
状态词
| 页面用语 | 含义 | 颜色语义 |
|---|---|---|
| 正常 | 当前证据完整,最近验证通过 | 绿色 |
| 需关注 | 有降级、部分缺失或客户端不一致 | 黄色 |
| 阻塞 | 必需链路断开,当前 Agent 无法完成闭环 | 红色 |
| 未验证 | 配置存在或接口可读,但没有足够真实调用证据 | 灰色 |
| 过期 | 曾经有证据,但超过新鲜度窗口 | 紫灰色,不能当正常 |
🔁 四层功能路由闭环
四层功能路由闭环描述一次对话如何从用户意图走到可验证结果。严格说,运行路径包含意图解析、执行和验证等状态,因此页面将四个核心配置/能力层显示为四层节点,并把意图、执行/验证作为连接节点。契约依据是 /root/.codex/docs/rule-layer-contract.md:规则、技能、工具和 Memory 必须分别有权威源、运行时对象和真实生效证据。
flowchart LR
Intent["用户意图"] --> Rules["① 规则层\n规则授权 / 范围 / 禁止项"]
Rules --> Bootstrap["Memory Bootstrap\n历史事实 / 候选 / 新鲜度"]
Bootstrap --> Skills["② 技能层\n选择 / 加载 / 版本 / SHA256"]
Skills --> Tools["③ 工具层\ntools/list / schema / allowlist"]
Tools --> Execute["执行与验证\n真实调用 + 独立回读"]
Execute --> Memory["④ Memory 层\n观察 / 摘要 / outbox 回写"]
Memory -. "下一 turn 的可验证上下文" .-> Bootstrap
Rules -. "缺证据" .-> Blocked["BLOCKED:停止新外部调用"]
Skills -. "未加载或冲突" .-> Blocked
Tools -. "未枚举 / 不在 allowlist" .-> Blocked
Execute -. "结果未验收" .-> Blocked
四层与四域的关系
| 视角 | 关注对象 | 典型问题 | 页面关系 |
|---|---|---|---|
| 四个状态域 | 系统资产和部署关系 | 中央服务是否健康?哪个 Agent 客户端离线?中央 Release 与节点镜像是否一致? | 上方总览、域卡片、节点矩阵 |
| 四层路由闭环 | 当前 turn 的功能链路 | 规则是否注入?技能是否加载?工具是否进 allowlist?Memory 是否回写? | 中部横向链路、断点标记 |
| 节点到 Agent | 分发后的落地对象 | Release 是否安装到该节点?本地镜像是否匹配?turn 是否真实加载? | 节点 × 域矩阵、规则技能中枢 |
核心关系是:状态域告诉人“系统哪里有问题”,四层闭环告诉人“对话为什么因此运行不了”,节点映射告诉人“问题影响哪个 Agent”。缺少任一视角,页面都只能显示孤立的健康灯,不能形成可处置的问题定位。
🧩 节点、配置与中心服务关系
配置更新与扩散主线
flowchart LR
Memory["Memory 中央资产\nRule Sets / Skill Assets"] --> Release["不可变 Release\n版本 / 平台 / SHA256"]
Release --> Canary["101 canary\n安装 / 回退 / 真实 turn"]
Canary --> Fleet["其他 Codex 节点\n按平台安装"]
Fleet --> Mirror["本地运行时镜像\nAGENTS.md / 受管 SKILL.md"]
Mirror --> Runtime["Hook RouteContext\n实际加载 / allowlist"]
Runtime --> Projection["一致 / 预期差异 / 等待安装 / 漂移 / 阻塞"]
Projection --> Console["P20 只读展示"]
P20 需要同时记录三件事:资产是否存在、运行时是否加载、任务是否真实使用。只能证明第一件事时,状态为“未验证”;节点与 101 不同但属于登记的 Windows 或平台差异时,状态为“预期差异”;没有登记的版本或哈希不一致时,状态为“漂移”;完全没有证据时,状态为“未知”。历史记录中出现的节点名称、版本和配置不能直接当作今日状态。
中心服务关系
flowchart TB
Agent["Agent turn"] --> CPA["CPA:模型路由"]
Agent --> Memory["Memory:bootstrap / recall / writeback"]
Agent --> Fetch["Web Fetch:页面抓取"]
Agent --> Search["Web Search:搜索发现"]
Agent --> Other["其他已登记 MCP / CPA 服务"]
CPA --> Providers["模型与 Provider"]
Memory --> Relation["历史事实、规则候选、技能候选、工具观察"]
Fetch --> Context["抓取正文"]
Search --> Context
Context --> Verify["结果验证"]
Verify --> Memory
中心服务必须分别显示“已配置、已发现、已验证、实际调用、最近失败”这些不同证据层级;不能因为服务端口存在就判为 Agent 工具可用,也不能因为一次 Web Fetch 成功就假设 Web Search 已验证。
中央模型路由的节点客户端子层
中央模型路由域不是只显示 CPA 服务本身。它同时显示“CPA 中央模块”和每一个 Codex 客户端的路由配置,形成“中央服务 → 客户端配置 → 本地目录 → 真实模型目录探测”的完整关系。
| 检查对象 | 页面显示 | 真实证据 | 状态规则 |
|---|---|---|---|
| 中央 CPA | CPA 中央路由(101)、模型数量、健康状态 |
101 healthz 与 /v1/models |
中央服务不可用时为阻塞/需关注 |
| 客户端路由配置 | provider、目标中央路由、模型名、Responses 协议 | 各节点 config.toml 的脱敏快照 |
未上报为未验证,目标不是当前 CPA 为阻塞 |
| 本地模型目录 | 目录存在、目录数量、目标模型是否存在 | model_catalog_json 文件与 SHA256 短指纹 |
DeepSeek 目录缺失、无法解析或目标模型缺失为需关注 |
| 目录与中央一致性 | 本地目录数量与 CPA 实际 /models 数量 |
节点心跳同时上报本地目录和 /models 探测 |
数量不一致为需关注,防止客户端拿到过期或额外目录 |
| 节点运行新鲜度 | 最近一次路由探测时间 | Memory metrics 心跳 |
超过新鲜度窗口为已过期,不画成正常 |
| 运行版本对齐 | Codex、CPA、Memory 的版本是否清楚且符合基线 | Codex 客户端 --version、CPA healthz/version 字段、Memory system status |
版本缺失为未验证;在线节点版本不一致为需关注;版本一致仍必须保留真实调用证据 |
本次真实盘点发现:101 与 CPA 都返回 5 项模型;102、RR、Home、Summer 原先本地目录为 10 项,虽然都能访问 CPA,但目录与中央实际目录不一致。按 101 canary 规则,已将 101 的正式目录分发到四台在线节点,保留原文件备份;随后五台在线客户端均回报“CPA 路由正常、目录 5 项、目标模型存在、真实 /models 探测通过”。OfficeSummer 当前离线,页面保持未验证,不计入已同步。
🖥️ 只读页面规划
导航归组
页面不再作为一个孤立入口随意插入导航,而是把现有散落入口整合成一个“Agent 运行态势”组,形成同一组资料和同一观察语境。建议组内顺序如下:
Agent 运行态势
├── 总图:Agent 运行态势与四层闭环
├── 节点与 Agent 客户端
├── 中央服务与工具
├── CPA 模型路由
├── Memory 服务
├── 网络与连接态势
└── 告警与异常
现有页面不立即删除、不复制成第二套管理页;只调整导航归组和入口名称,具体页面仍承担原职责。新增总图只读,不提供重启、更新、发布、写 Memory、改规则、确认告警或同步节点按钮。
页面从上到下的结构
flowchart TB
Header["页面标题 + 总体状态 + 最近刷新"] --> Summary["总体摘要:影响节点 / 状态新鲜度"]
Summary --> Relation["四域关系图:中央路由 ↔ 中心服务 ↔ Agent ↔ 101 基线"]
Relation --> DomainCards["四个状态域卡片"]
DomainCards --> Loop["四层路由闭环:断点高亮"]
Loop --> Matrix["节点 × 状态域 × 闭环矩阵"]
Matrix --> Issues["需要关注:原因 / 影响 / 已有处理入口"]
用户看到的是“正常、需关注、阻塞、未验证、过期、离线”和人类可读原因;原始哈希、端点、调用 ID 和技术日志只作为可折叠证据,不作为首屏主语言。主机离线时只显示“离线”,不把该节点列入在线待处理问题;节点重新上线后再恢复客户端、路由、工具和规则状态判断。节点矩阵使用独立列显示客户端、主机、Agent、版本、中央路由、模型、API、规则、技能、工具、Memory 和结论,避免把同一信息重复写进摘要。中央模型路由域使用同样的表格结构,版本、模型和 API 不再从长文本中解析。所有状态卡必须在桌面和移动端保持稳定尺寸,移动端可纵向排列,不产生页面级横向滚动。
📊 数据、状态与更新策略
只读聚合契约
查询面固定为 GET /api/agent/runtime-status,需要管理员只读会话。返回结构已冻结为以下对象:
| 对象 | 内容 | 必须保留的证据 |
|---|---|---|
overall |
总体状态、影响节点数、刷新时间、最旧数据年龄 | 状态计算规则和数据新鲜度 |
domains |
四个状态域的摘要与状态 | 每个域的来源和最近验证 |
clients |
节点、主机状态、Agent 状态、版本、闭环摘要 | 主机与客户端分开的证据 |
clients[].model_route |
每个 Codex 客户端的中央路由配置与探测结果 | 目标路由、模型、协议、目录数量、目标模型存在性、短指纹、最近探测 |
loop |
规则、Bootstrap、技能、工具、执行/验证、回写状态 | 当前 turn 或最近验证的上下文 |
rule_skill_authority |
Memory 中央期望、节点安装、turn 运行和统一裁决 | Release 版本/hash、节点回执、规则/技能加载摘要 |
issues |
人类可读问题、影响范围、处理入口 | 首次/最近观测和状态来源 |
sources |
数据源名称、状态、时间、新鲜度 | 不暴露密钥、内部凭据和不必要地址 |
动态刷新与过期
页面每 30 秒刷新只读聚合结果,离开页面时停表,回到页面立即刷新。API 默认使用 15 秒缓存、5 秒单源超时和 1800 秒证据新鲜度;各数据源独立失败、独立标注,不用一个失败覆盖所有域。刷新失败时页面明确显示“状态暂不可读”,不把旧结果继续画成正常。
现有审计事实如何进入计划
CPA 的实际健康路径已验证为 /healthz,不能猜用 /health;Memory 总体健康与客户端心跳必须分开;Web Fetch 要同时看服务状态和真实调用;Web Search 区分 configured、verified、blocked;101 的规则、四层契约和 Memory Hook 哈希可作为基线卡片。它们都是页面设计的输入和验收样本,不是 P20 当前要处理的故障清单。
🛠️ 工作包与依赖
| 工作包 | 目标 | 前置依赖 | 预期成果 | 当前边界 |
|---|---|---|---|---|
| P20-0 计划评审与架构冻结 | 冻结范围、图、状态词、只读边界和导航归组 | 用户确认“按照这个计划开始执行” | 详细计划、Mermaid 图和未决项记录 | ✅ 完成 |
| P20-1 数据源盘点与只读契约 | 将现有来源映射到四域和闭环 | P20-0 确认 | GET /api/agent/runtime-status、逐源状态和脱敏测试 |
✅ 完成 |
| P20-2 Console 信息架构与跨域总图 | 形成可扫读的总览、卡片、矩阵和异常列表 | P20-1 契约冻结 | #agentRuntime、动态关系图、六阶段闭环和移动端契约 |
✅ 完成 |
| P20-3 101 基线与节点扩散可视化 | 显示 101 基线和在线 Agent 的规则上下文覆盖 | P20-1、真实证据可用 | 101 基线卡、扩散覆盖、证据过期和未知语义 | ✅ 完成 |
| P20-4 实施、测试与只读发布 | 完成完整门禁、精确 SHA 发布和公网回读 | P20-0 至 P20-3 完成 | 代码、测试、生产只读页面、回退材料 | ✅ 已完成 |
| P20-5 规则与技能中央管理 | Memory 管理资产,节点接收运行时镜像,P20 展示三层状态 | P20-4 完成;用户确认 P20-5 契约 | Release、分发器、Hook 证据、API v2、Console 中枢 | 实施中:101 对账与回执完成,跨节点安装待正文模型 |
依赖顺序固定为 P20-0 → P20-1 → P20-2/P20-3 → P20-4 → P20-5。P20-5 内部按 Release → 101 canary → Hook 证据 → API/Console → Fleet rollout 串行推进。
🧭 P20-5 规则与技能中央管理计划
目标修正
P20-5 的目标是让 Memory 成为规则和技能的中央管理权威,让各节点的 Codex 获得经过验证的本地运行时镜像。它不把 Memory 变成 turn 内实时内容注入器,也不允许页面直接修改 Codex 规则或技能。
推荐链路如下:
flowchart LR
Author["Memory 中央管理\n规则集 / 技能资产"] --> Release["不可变发布清单\n版本 / 平台 / 范围 / SHA256"]
Release --> Distributor["受控节点分发器\n下载 / 校验 / 原子安装 / 回执"]
Distributor --> Mirror["Codex 本地运行时镜像\nAGENTS.md / 受管 SKILL.md"]
Mirror --> Hook["Codex Memory Hook\n本地读取 / RouteContext 发布"]
Hook --> Evidence["Memory 客户端证据\n本轮规则/技能加载摘要"]
Release --> Gateway["API Gateway"]
Distributor --> Gateway
Evidence --> Gateway
Gateway --> Console["P20 规则与技能中枢"]
选择本地镜像而不是每个 turn 直接从 Memory 拉取技能和规则,原因是 Codex 的规则、技能和工具目录在 turn 开始前已经进入运行时;本地镜像可离线、可复现、可按 SHA 回退,也不会让 Memory 网络故障直接变成每个 turn 的前置失败。
当前真实状态
| 对象 | 实测事实 | 当前结论 |
|---|---|---|
| Codex 本地规则 | 全局和 AgentMeshOS 项目 AGENTS.md 存在,override 不存在 |
101 本地规则源可用 |
| Codex 本地技能 | 三个技能根目录共 35 个 SKILL.md,去重 32 个技能名 |
本地已有完整技能集合 |
| Memory 规则资产 | 5 个 Rule Set、40 条规则;1 个规则集来源不可用 | 中央资产已存在,但资产质量需单独核对 |
| Memory 技能资产 | 33 个技能,32 个启用、1 个停用 | 中央资产已存在 |
| Memory 技能目录 | /api/skills/catalog 当前返回 20 项 |
目录暴露数和资产库存数不是同一口径 |
| 101 最近 turn | rule_count=6、本轮技能候选 0、rule_source_mismatch=true |
规则源与 Memory 期望不一致,中枢判定阻塞 |
| RouteContext | ready、TOOLS_READY、published=true、stale=false |
当前 turn 路由已发布 |
| 技能加载 | skills_loaded=0、tool_allowlist_count=2、route_context_published=true |
本轮没有选择技能,工具白名单已生成 |
| Memory 全局规则副本 | codex-global-resident 指向 101 的 AGENTS.md,当前副本哈希与本地文件不一致 |
中央资产与本地运行时镜像存在漂移 |
| 中央分发链路 | 没有活跃的 skill_sync、asset_sync 或 global_rules 客户端;import_codex_assets.py 的方向是“本地导入 Memory”,旧 asset sync 只剩 .bak |
“在 Memory 新增后自动到所有 Codex”目前尚未实现 |
依据是 /api/rules、/api/skills、/api/skills/catalog、/api/system/capabilities、/api/system/clients、本地技能目录和最近 Hook 调试记录。旧治理 API、observer 和旧资产同步 timer 已退役,不得作为本计划的实现基础复活。
权威与状态模型
| 层级 | 权威 | 记录内容 | 不能证明 |
|---|---|---|---|
| 中央期望状态 | Memory Release | 规则/技能 ID、版本、平台、目标范围、SHA256、启用状态 | 不能证明节点已经安装 |
| 节点安装状态 | 节点分发器 | 已安装版本、目标路径、原子替换结果、回执时间、last-known-good | 不能证明当前 turn 已加载 |
| turn 运行状态 | Codex Hook | 本地规则源、技能候选、技能正文校验、RouteContext、allowlist | 不能证明中央资产仍是最新版 |
| 治理结论 | API Gateway 归一化 | aligned、expected_difference、pending、drift、blocked、unknown、stale | 只展示,不代替实际修复 |
规则和技能的中央管理对象分开建模:
| 对象 | 建议目标 | 所有权标记 | 回退方式 |
|---|---|---|---|
| 全局规则 Release | 平台对应的 AGENTS.md 完整镜像 |
rule set ID、version、platform、SHA256 | 原子替换回上一 Release |
| 技能 Release | 节点共享技能目录中的受管技能目录 | .agentmeshos-managed.json 清单和技能 version/hash |
按上一清单恢复或删除受管项 |
| 项目规则 | 项目仓库 AGENTS.md |
项目 ID、范围、版本 | 不自动覆盖用户项目规则 |
| 系统/插件技能 | 不纳入中央改写 | 只读 | 保留原厂或插件自身升级路径 |
数据契约
API Gateway 为每个 Agent 返回 rule_skill_authority_v1,原始正文、完整路径和原始哈希不进入浏览器:
{
"status": "healthy",
"classification": "aligned",
"desired": {
"rules_version": 45,
"skills_release": "release-2026-10-28.1",
"rule_sets": 5,
"skill_assets": 33,
"source_fresh": true
},
"applied": {
"rules_version": 45,
"skills_release": "release-2026-10-28.1",
"last_applied_at": 1793144000,
"last_result": "ok"
},
"runtime": {
"rule_candidates": 6,
"rule_sources_loaded": true,
"rule_source_mismatch": false,
"skill_candidates": 5,
"skills_selected": 5,
"skills_loaded": 5,
"required_skills_missing": 0,
"skill_warnings": 0,
"selection_status": "selected",
"tool_allowlist_count": 5,
"route_context_status": "ready",
"route_context_published": true,
"snapshot_stale": false
},
"issues": []
}
classification 与 status 分离:平台差异或未选择可选技能可以标为 expected_difference,仍显示正常;已发布但节点尚未拉取标为 pending;同一版本出现不同内容才是 drift。
发布与分发
- Memory 规则/技能编辑后先生成 dry-run manifest,列出受影响平台、节点、目标文件和变更类型。
- 正式发布生成不可变 Release,原资产可保留历史版本,节点只能消费完整 Release。
- 节点分发器使用受控只读凭据或 Tailnet 身份拉取,校验 Release、平台、目标和 SHA256。
- 先写临时目录,校验后原子替换;规则文件与受管技能清单分别保存 last-known-good。
- 安装后回读版本、hash 和文件可见性,再向 Memory 的节点资产状态上报
applied。 - Codex 下一 turn 由 Hook 读取本地文件并发布 RouteContext;中央页面用它区分“安装成功”和“真实加载成功”。
首版不直接删除无法映射的本地技能,也不接管 .system 或插件技能。受管技能若被删除,只清理 .agentmeshos-managed.json 中登记的所有项。
工作包
| 工作包 | 目标 | 主要改动 | 退出条件 |
|---|---|---|---|
| P20-5-0 语义与发布契约 | 冻结中央期望、节点安装、turn 运行三态 | Memory asset ID/version/hash、平台差异、expected_difference 定义 | 用户确认路径、所有权和回退规则 |
| P20-5-1 Central Release | 把规则/技能资产组织为不可变 Release | Memory release manifest、dry-run、历史版本 | 能列出 101/Windows 的目标与差异 |
| P20-5-2 Node Asset Sync | 建立单节点受控分发器和原子安装 | 拉取、校验、安装、回执、last-known-good | 101 canary 安装与回退通过 |
| P20-5-3 Hook 证据 | 发布真实规则/技能加载摘要 | mismatch、skill candidate/selected/loaded、required、warnings、allowlist | 每个 turn 都有完整脱敏摘要 |
| P20-5-4 API v2 | 聚合 desired/applied/runtime 三层 | agent_runtime.py schema v2、兼容 v1 缺失字段 |
单测覆盖全部 classification/status |
| P20-5-5 Console | 增加“规则与技能中枢”只读面板 | 来源、安装、运行、问题、下一步 | 桌面/390px 可读,不出现正文和路径 |
| P20-5-6 Fleet Rollout | 101 完成后扩展其他 Agent 节点 | 平台映射、逐节点 canary、失败关闭 | 至少一个非 101 Agent 安装和真实 turn 通过 |
| P20-5-7 Model Route Clients | 把中央 CPA 与各 Codex 客户端配置、目录和真实探测纳入中央模型路由域 | 心跳路由快照、客户端目录一致性、节点矩阵和异常项 | 在线节点回报目标路由、模型、协议、目录和 /models 探测;离线节点保持未验证 |
| P20-5-8 Runtime Version Alignment | 把 Codex、CPA、Memory 版本纳入四域对齐对象 | 版本来源、基线版本、节点版本差异、未上报状态和页面摘要 | 版本可见、缺失不伪装正常、版本一致不替代功能验收 |
| P20-5-9 Web Capability Routing | 在 Agent 客户端域展示中央 Fetch、本地 Fetch 兜底、中央 Search 和浏览器升级能力 | 心跳本地依赖盘点、API web_capabilities、Console 网页能力表格 |
本地门禁、浏览器契约和 API 单测通过;代码进入可发布镜像 |
| P20-5-10 RR Primary Release | 将 Console/API 镜像部署到 RR 主生产 | console-site、api-gateway 同 SHA 发布、RR 健康和回滚材料 |
✅ 完成:RR 运行镜像 SHA 等于目标提交;两个服务健康 |
| P20-5-11 Production Readback | 验证主生产页面和真实状态接口 | 管理员会话、runtime-status、网页能力表格、客户端心跳和移动端页面 |
✅ 完成:管理员 API 200;8 个客户端带 web_capabilities;真实浏览器显示网页能力路由表格;OfficeSummer 单独离线 |
页面规划
不新增第五个顶层状态域;“101 对齐配置”内部增加子项,并在四个状态域之后增加独立只读面板:
| 区域 | 内容 |
|---|---|
| 中央期望 | 规则 Release、技能 Release、平台、目标节点、发布时间和新鲜度 |
| 节点安装 | 已安装版本、最近安装时间、last-known-good、失败节点 |
| Turn 运行 | 规则源匹配、技能候选/选中/加载、必需技能缺失、RouteContext、allowlist |
| 统一裁决 | 一致、预期差异、等待安装、漂移、阻塞、未验证、过期 |
| 需要关注 | 按影响列出节点、问题、影响范围和下一步入口 |
规则与技能分别显示,不合并成一个数字。页面首屏不显示完整 SHA、文件路径、规则正文或技能正文。
状态与告警
| 场景 | 分类 | 健康状态 | 是否告警 |
|---|---|---|---|
| 中央 Release 与节点安装一致,turn 已加载 | aligned | 正常 | 否 |
| Windows 使用登记的平台差异 | expected_difference | 正常 | 否 |
| 中央发布成功,节点尚未拉取 | pending | 需关注 | 超过窗口后告警 |
| 本地受管文件被手工修改 | drift | 阻塞 | 立即告警 |
| 规则源缺失、必需技能缺失或 hash 不一致 | blocked | 阻塞 | 立即告警 |
| 只有 Memory 资产,没有节点安装证据 | unknown | 未验证 | 首个观察窗口后提醒 |
| 安装或 turn 证据超时 | stale | 已过期 | 立即告警 |
可选技能未被选择、Memory catalog 与总资产数量不同,不单独告警;但节点本地模型目录与 CPA 实际 /models 目录不一致属于客户端路由漂移,必须显示“需关注”。
验收
| 验收项 | 方法 |
|---|---|
| 新增技能可下发 | 在隔离 Memory 测试空间生成技能 Release,101 canary 安装并由下一 turn 真实加载 |
| 修改全局规则可下发 | 修改测试规则 Release,101 原子更新 AGENTS.md,回读版本/hash 和实际 prompt |
| 平台差异 | Windows 安装同一 Release 的 T2 变体,状态显示预期差异 |
| 负向漂移 | 手工篡改受管技能,记录 drift 并拒绝宣称 loaded |
| 负向缺失 | 删除必需技能候选对应文件,RouteContext 进入 BLOCKED |
| 回退 | 恢复上一 Release,规则、技能和 turn 状态均回到 aligned |
| 节点离线 | 中央显示 pending,不把离线节点标成中央发布失败 |
| 页面只读 | 无发布、安装、删除、编辑按钮,原管理入口保留 |
回退
中央 Release 只追加不覆盖;节点保留上一 Release 和 .agentmeshos-managed.json。回退时分发器先安装上一版本、校验 hash、重启/新建 Codex turn,再确认 RouteContext ready。API 与 Console 可独立回滚,不影响已安装本地文件;Memory Release 不删除时可直接重新发布。
仍未决
| 编号 | 决策 | 结论 |
|---|---|---|
| D7 | 中央技能统一安装到哪个目录 | 已定:Codex 技能根 + 受管标记;未受管同名项不覆盖 |
| D8 | 全局规则采用整文件发布还是受管块 | 已定:整文件 Release + last-known-good,默认不写 |
| D9 | P20-5 首批范围 | 已定:101 canary,冲突对账通过后再扩 |
| D10 | 发布是否需要人工审批 | 已定:不引入审批;用只读计划、失败关闭和显式写入开关兜底 |
| D11 | 跨节点安装所需的完整 SKILL.md 原文 |
待实现:Memory 当前只存正文和原始文件哈希;建议新增 raw_text 字段并在导出返回,分发器按原文安装 |
🧪 P20-5 本轮实施记录
已完成
| 交付物 | 证据 | 影响 / 下一步 |
|---|---|---|
| 节点资产分发器 | scripts/maintenance/agentmeshos-agent-assets-sync.py:plan / apply / rollback / status,原子写入、受管标记、last-known-good、目标越界阻断 |
默认只读;规则写入需显式 --apply-rules |
| 分发器回归 | scripts/maintenance/tests/agent-assets-sync-test.py:过滤、幂等、冲突保护、外部技能根、漂移修复、回退、越界、受管删除 |
已接入 scripts/ci/run-local-tests.sh |
| Hook 运行证据 | 备份 codex-memory-hook.py.bak-20261028-p20-assets(SHA256 215c83eb…),现行 Hook 为 cc5a7f65…;新增规则源、技能选择/加载、必需缺失、告警数、allowlist、RouteContext、资产 Release 摘要 |
规则匹配支持跨平台路径;插件快照差异不再阻断 turn |
| 中枢 API | rule_skill_authority 返回 desired / applied / runtime、aligned/pending/blocked/unknown/stale 分类与问题项 |
浏览器只看到计数、短指纹和人类可读结论 |
| Console 面板 | #agent-runtime-authority 四张只读卡片,覆盖中央期望、节点安装、最近一次 Turn、统一裁决 |
桌面四列,640px 以下单列;不出现正文、绝对路径或完整哈希 |
| 工具与 MCP 目录 | #agent-runtime-tools 逐节点显示核心能力的配置、依赖安装和运行证据 |
Playwright、Kimi WebBridge、CUA、Memory、Web Search、Web Fetch、Context7 不再隐藏在四层摘要里;可选 MCP 自 2026-11-04 起单独进入“可选扩展”表 |
| 工具目录实测 | 101 的 Playwright/WebBridge/CUA 均可用;102/RR/Summer 的 Playwright 已安装并配置为本地 cli.js;Summer CUA 已安装但 Session 0,WebBridge 未安装 |
配置、安装和运行状态已分开显示;OfficeSummer/Home 待在线复验 |
| 部署工作流 | reusable-rr-deploy.yml 的资源下载增加 6 次有界重试,生产部署门禁校验该契约 |
消除 release 资产可见性滞后导致的假失败邮件 |
| 全局规则 | /root/.codex/AGENTS.md 新增“GitHub 远程同步与 Action 闭环(强制)”,备份为 .bak-20261028-github-action-gate |
规则从 v45 升到 v46,并已回灌 Memory |
| 中央模型路由客户端态势 | agentmeshos-agent-assets-sync.py 心跳新增无凭据 model_route 快照;API 将其挂入中央模型路由域和客户端矩阵 |
101、102、RR、Home、Summer 均指向 CPA /v1,Responses 协议,模型目录 5 项,真实 /models 探测通过;OfficeSummer 离线 |
| 运行版本对齐 | API 新增 versions 和“运行版本对齐”子项;Codex 版本来自客户端 --version,Memory 版本来自实时 system status,CPA 版本只接受 health/version 字段 |
当前 Codex 为 0.163.0,Memory 为 12.1.1;CPA healthz 只返回 status=ok,因此 CPA 版本显示未上报,不把它当作故障 |
| 路由目录漂移修复 | 101 正式目录与 CPA 实际目录均为 5 项;102、RR、Home、Summer 原为 10 项 | 已按 101 基准分发 5 项目录,逐节点备份与 SHA256 校验后,五台在线节点回报一致 |
| Home 心跳根因修复 | Home 计划任务原先未显式传 --codex-home,导致任务环境读取错误目录 |
已补充显式 Codex Home 与 Agent 类型参数;任务结果回读为 0,路由状态恢复正常 |
| 网页能力路由子层 | 原页面只展示中央 Web Fetch/Web Search,未把节点本地 Fetch 兜底与 Playwright/WebBridge/CUA 分层呈现 | API 新增逐节点网页能力契约;页面独立显示中央 Fetch、本地 Fetch 兜底、中央 Search 和三种升级工具,中央正常不再代表节点本地兜底已验证 |
| 状态投影去重与统一 | Memory MCP 别名、工具目录与网页能力表、模型路由域与节点矩阵存在重复展示 | 后端统一 MCP 别名;工具目录与网页能力表共用中文状态单元格;节点矩阵移除重复的路由/模型/API列,模型路由域保留唯一明细 |
双源裁决流程
flowchart LR
Central["Memory 中央资产\nRule Sets / Skill Assets"] --> Release["不可变 Release\ncontent_digest / 版本 / SHA256"]
Release --> Plan["节点只读计划\n安装 / 更新 / 一致 / 冲突 / 外部提供"]
Plan -->|无冲突| Apply["原子安装 + 受管标记\nlast-known-good"]
Plan -->|冲突| Reconcile["人工对账\n确认以哪一侧为准"]
Apply --> Hook["Hook 校验本地正文\n规则源 / 技能 SHA / RouteContext"]
Hook --> Verdict["统一裁决\naligned / pending / drift / blocked / unknown / stale"]
Reconcile --> Central
Verdict --> Console["P20 规则与技能中枢"]
状态判定
| 分类 | 触发条件 | 页面状态 | 是否告警 |
|---|---|---|---|
aligned |
中央内容指纹与节点安装回执一致,本轮规则源与必需技能校验通过 | 正常 | 否 |
pending |
节点有安装回执,但内容指纹落后于中央 | 需关注 | 是 |
blocked |
规则源哈希不一致、必需技能缺失或 RouteContext 未发布 | 阻塞 | 是 |
unknown |
只有中央资产,没有节点安装证据 | 未验证 | 否,首个窗口后提醒 |
stale |
安装回执超过新鲜度窗口 | 已过期 | 是 |
101 只读计划实测
命令:python3 scripts/maintenance/agentmeshos-agent-assets-sync.py plan --codex-home /root/.codex(--memory-base 取自 Hook 现用地址,不写入文档)。
| 阶段 | 结果 | 说明 |
|---|---|---|
| 对账前 | 8 个同名技能内容不一致、9 个由其他技能根提供、1 条规则不一致 | 哈希按“正文”比较时误报;实际是 Memory 只保存正文、原始文件哈希在 metadata |
| 对账动作 | 回灌 16 个本地技能,重建 codex-global-resident;新增全局 Action 闭环规则后为 v46(SHA256 5e21513a…) |
Memory 中央副本与 101 运行时一致 |
| 对账后 | 8 个本地受管技能一致、9 个由 ~/.agents/skills 提供且一致、1 条规则一致、0 冲突 |
只读计划 blocked=false |
| 回执 | release=c3700497faab、content=7849ee740747,16 技能 + 1 规则 |
没有写入任何技能文件或 AGENTS.md |
结论:101 的运行时镜像已经与中央期望对齐,且回执内容指纹与 API desired 完全一致。
四节点分发结果
按 101 基准把 AGENTS.md、Hook、16 个技能和资产回执同步到 102、RR、Home、Summer,每台均保留本机备份并逐文件校验 SHA256。
| 节点 | 规则哈希 | Hook | 技能 | 资产回执 | 客户端状态 |
|---|---|---|---|---|---|
| 101 | 7ee4d51b… |
cc5a7f65… |
16 | c3700497faab / 7849ee740747 |
在线 |
| 102 | 7ee4d51b… |
cc5a7f65… |
16 | 同上 | 在线;旧 AGENTS.override.md 已备份停用 |
| RR | 7ee4d51b… |
cc5a7f65… |
16 | 同上 | 在线 |
| Home | 7ee4d51b… |
cc5a7f65… |
16 | 同上 | 在线 |
| Summer | 7ee4d51b… |
cc5a7f65… |
16 | 同上 | 在线;旧 override 已备份停用,主机登记待验证 |
| OfficeSummer | 7ee4d51b… |
b1e7a6f5… |
16 | c3700497faab / 7849ee740747 |
在线 |
102 与 Summer 原先存在 AGENTS.override.md,会完全覆盖全局规则;两份都已改名备份,当前不再阻断规则源匹配。102 上 6 个重复的 Paseo 技能已移入 .agentmeshos-quarantine-20261031-083945,由共享技能根提供一致版本。
客户端心跳
Memory 的在线判定是 5 分钟 TTL、15 分钟转离线。为区分“空闲”和“掉线”,已给五个 Codex 客户端加 4 分钟心跳:
| 平台 | 节点 | 机制 | 结果 |
|---|---|---|---|
| Linux | 101、102、RR | agentmeshos-client-heartbeat.timer |
active,服务 Result=success |
| Windows | Home、Summer | 计划任务 AgentMeshOS-Client-Heartbeat |
Ready,LastTaskResult=0,允许电池启动和错过补跑 |
| Linux | 101 | agentmeshos-paseo-heartbeat.timer、agentmeshos-opencode-heartbeat.timer |
active,Paseo/OpenCode 客户端在线 |
心跳只上报客户端在线与版本,不产生模型调用、turn 或 Memory 写入。
资产回执是持久事实,API 按 7 天判断是否过期;实时性由客户端心跳负责,避免安装完成 30 分钟后被误判为“已过期”。
Hook 的 PostToolUse 现在上报 tool_call 通道;101 的规则、Bootstrap、技能、工具、执行和 Memory 回写六层已全部取得健康证据。Summer 的主机别名已从错误的 summer 修正为 windows-summer,与节点登记表一致。
Web Search 现在由网关执行一次真实 SearXNG 搜索并记录 last_success_at,且要求结果数大于 0;Web Fetch 已在服务端增加真实调用计数,/healthz 返回 last_success_at 与 call_count。
SearXNG 容器本身正常,但 Brave 超时/429、DuckDuckGo CAPTCHA、Google CSE 超限、Wikidata 超时,导致直连查询返回 0 条。搜索 MCP 已增加 SearXNG → Serper → Tavily 兜底,实测 SearXNG 0 条时 Serper 返回 5 条;页面会如实显示“上游搜索源返回 0 条结果”,不再把 0 条画成健康。
兜底 MCP(f04609c6…)与 search.env 凭据已同步到 102、RR、Summer、OfficeSummer;凭据只走 SSH 传输,Linux 权限 0600,Windows 使用受限 ACL。102 实测 SearXNG 0 条时 Serper 返回 3 条。Home 当前离线,恢复后补发。
控制台的中央服务现在同时显示主机与实际工具:Memory(102)、Web Fetch(101 · agentmeshos-web-fetch)、Web Search(101 · SearXNG)。Web Search 的说明还会写出“兜底:Serper → Tavily”,不再把一个大面写成单一服务名。
Console 的“中央 Web 搜索”入口已改为 #webSearch 内嵌视图,地址固定为同源路径 /__agentmeshos/searxng/。RR 私有回源网关先执行 A-Auth admin 检查,再按 Tailnet DNS 解析 101 并转发到其 8090;SearXNG 的公开基址同步为 Console 子路径,因此页面、静态资源、表单、重定向和偏好设置都不会把 101 节点地址带回浏览器。该入口不再使用 window.location.assign 离开 Console,也不在菜单文案中显示节点 IP。
SearXNG 虽然部署在 101,但它只是元搜索聚合器,真正检索仍要访问 Brave、DuckDuckGo、Google CSE、Wikidata 等外部引擎。限流来自这些外部引擎对 101 公网出口 IP 的 429、CAPTCHA 和超时,不是容器本地故障;兜底 Serper/Tavily 通过 API Key 走授权通道,因此不受同一套网页反爬限制。
OfficeSummer 原先只有 WindowsApps 的 Python 占位符。已安装 Python 3.13.9(安装包经官方源与镜像 SHA256 对验),并把旧 Hook 引用的 .codex\python313 做成指向标准安装目录的目录联接;资产回执与心跳均已通过。
工具目录的边界
Playwright 是可由节点包管理器自动安装的本地 MCP,102、RR、Summer 已安装 @playwright/mcp 0.0.83,并改为固定本地 cli.js,避免每次启动依赖 npx 下载。Kimi WebBridge 不是普通 MCP 包:它要求 daemon、真实 Chrome 扩展和扩展连接地址三件套,官方操作边界要求由用户从 Kimi 官方入口安装,分发器只展示状态,不静默安装。CUA Driver 依赖真实桌面会话;RR 不适用,Summer 的 driver 已安装但当前 SSH 在 Session 0,不能把服务会话当成 GUI 可用。
因此,这些工具现在属于“Agent 客户端”状态域下的“工具与 MCP 目录”子层,而不是遗漏在状态域之外。页面在核心表逐项显示配置、安装和运行证据,避免把 config.toml 里出现一段配置误判成工具已可用;不属于核心必检的可选 MCP 单独进入“可选扩展”表,平台角色不适用的工具直接不进入该节点核心表,不再用“不适用”填充单元格。
工具目录分发结果
下表是 2026-10-31 的历史盘点快照,其中“不适用”是按当时的展示口径记录的;2026-11-04 起的运行态势页面已改为“核心表只列核心能力、可选扩展单独成表、非 Codex Agent 使用自有检查”的口径。
| 工具 | 101 | 102 | RR | Summer | OfficeSummer | Home |
|---|---|---|---|---|---|---|
| Playwright MCP | 本地包、Node、Chrome 可用 | 已安装本地 @playwright/mcp 0.0.83,配置已改为固定 cli.js |
同上 | 已安装并配置为固定 cli.js |
节点暂时连接超时,待复验 | 离线 |
| Kimi WebBridge | daemon + Chrome 扩展已连接 | 不适用 | 不适用 | 未安装 | 未安装 | 未知 |
| CUA Driver | socket 可用 | 已安装;socket/daemon 状态需单独启动验收 | 不适用 | 已安装;桌面运行证据待验证 | 已安装;桌面运行证据待验证 | 未知 |
| Web Search MCP | SearXNG + Serper/Tavily | MCP/凭据已同步,实测 Serper 兜底 | 同上 | MCP/凭据已同步 | MCP/凭据已同步 | 离线 |
| Web Fetch MCP | 中央 101 | 中央 101 | 中央 101 | 中央 101 | 中央 101 | 中央 101 |
| Context7 | 已配置 | 未配置 | 未配置 | 配置存在但本地包缺失 | 待复验 | 未知 |
结论:工具缺口之前确实没有被状态域完整覆盖。现在工具目录是“Agent 客户端”状态域的显式子层;配置存在、依赖安装、实际运行和平台不适用分开显示。WebBridge 的 daemon 与浏览器扩展安装遵循官方边界,不由分发器静默安装;Playwright 则可由节点包管理器安装。
运行态势聚合在冷启动时可能耗时约 46 秒。网关已改为“缓存完成后计时 + 后台刷新 + 启动预热”,页面等待 60 秒;后续请求直接返回缓存快照,不再出现首次加载误报“状态暂不可读”。
验证
| 项目 | 命令 | 结果 |
|---|---|---|
| 分发器回归 | python3 scripts/maintenance/tests/agent-assets-sync-test.py |
agent-assets-sync=passed |
| Hook 证据(桩) | 本地 stub 调用 _bootstrap_recall,覆盖匹配与哈希不一致 |
hook-evidence=passed,py_compile 通过 |
| Hook 证据(真实回执) | Memory codex-pcdell-101 的 recall 通道已出现 rule_source_mismatch、skill_candidates、skills_loaded、tool_allowlist_count、route_context_published、asset_* 字段 |
规则源当前确实不一致,页面判定为阻塞 |
| 中枢 API | .venv/bin/python tests/test_agent_runtime.py |
agent_runtime=passed |
| 真实投影 | 用真实 Memory 导出调用 build_agent_runtime_status |
desired 为 1 个规则集 / 17 项受管技能;分类为 blocked,脱敏扫描通过 |
| Console 契约 | bash tools/console-site/tests/browser-contract.sh |
四组浏览器契约全部 PASS |
| 生产 API 回读 | 管理员 API Key 登录后读取 https://api.yohan.fun/api/agent/runtime-status |
返回 rule_skill_authority;分类 blocked,desired 1 个规则集 / 17 项技能,runtime 报告规则源不一致 |
| 生产 API(对账后) | 同一管理员会话重新读取 | desired 与 applied 均为 7849ee740747,分类 aligned;规则源匹配 |
| 公网浏览器验收 | Playwright 1440×1000 与 390×844 打开 #agentRuntime |
图例位于关系图右侧(248px 栏),图标 14px;中枢在四域之前;scrollWidth == clientWidth |
| 镜像构建 | 实现提交 0a24e90 的 API Gateway(Run 40609509862)与 Console(Run 40609509776)均成功;37b5b10 只改维护脚本 |
生产运行的是包含中枢代码的 0a24e90 镜像 |
回退
分发器回退依赖 <CODEX_HOME>/state/agentmesh-assets/last-known-good/,逐文件校验 SHA256 后恢复,并交换 current / previous Release。Hook 回退使用同目录备份文件;Memory 与 Console 可独立回滚,不影响已安装镜像。
🚦 实施评审结果
P20-4 已通过
用户已经在 2026-10-28 明确回复“好,按照这个计划开始执行”,P20-0 评审门已通过。确认内容如下:
- 用户确认四个状态域的名称、范围和页面归组。
- 用户确认四层闭环图的表达:规则、Memory Bootstrap、技能、工具、执行/验证、Memory 回写,以及
BLOCKED的失败关闭含义。 - 用户确认页面只读,问题只展示、不在 P20 第一版修复。
- 用户确认 101 是第一个分发 canary,Memory 是中央管理权威。
- 用户确认导航整合方式,不再把 CPA、Memory、节点、网络等入口继续分散在不同组。
- 计划正文、
state.json、当前摘要、计划看板、路线图、文档索引和 MkDocs 导航已经同步,并通过计划状态与 Markdown 门禁。
P20-5 的发布、节点安装和回退仍需用户确认 D7 至 D10 后才能实施。P20 状态页继续保持只读;发布和节点安装属于分发器职责,不在页面提供按钮。
P20-5 实施边界
用户已确认按计划开始实施,以下边界已冻结;它们是实现依据,不再是待确认项:
- 受管技能安装在 Codex 技能根,带
.agentmeshos-managed.json标记;系统、插件和其他 Agent 技能不接管。 - 已有未受管同名技能一律不覆盖;
~/.agents/skills已提供的同名技能不重复安装。 - 全局规则采用整文件 Release 与 last-known-good;默认只做差异检查,写入必须显式
--apply-rules。 - 101 是第一个 canary,冲突对账完成后才向其他节点扩展。
- 安装前先跑只读计划,冲突或阻断必须失败关闭,不静默覆盖。
- 运行态势页面只读;发布、安装、删除和回退动作保留在分发器与管理入口。
🧪 验收、回退与风险
当前实施验收
| 验收项 | 通过条件 | 证据 |
|---|---|---|
| 计划完整性 | 有目标、非目标、图、数据关系、工作包、验收、回退、未决项 | 本页正文 |
| 状态口径 | 计划状态与阶段状态分离,P20-4 已完成、P20-5 修订中 | state.json 与计划状态检查 |
| 图示可读性 | 有总体架构、配置扩散、四层闭环、中心服务和页面流程图 | 本页 Mermaid 图示 |
| 文档库一致性 | 看板、摘要、路线图、索引和导航都指向 P20 | 文档链接检查与 MkDocs 配置 |
| 实施隔离 | 代码测试不等于生产发布;审计问题只展示、不修复 | 工作包状态与本页边界声明 |
| API 契约 | 六阶段闭环、四域状态、未知/过期语义和脱敏字段通过单测 | tools/api-gateway/tests/test_agent_runtime.py |
| 浏览器行为 | 四域卡片、六阶段闭环、960px 紧凑关系图、五项颜色图例、单刷新按钮和 390px 无页面级溢出 |
tools/console-site/tests/browser-contract.cjs |
| 真实数据投影 | 101 基线、工具通道断点、Web 服务未验证状态按实际证据出现 | 本机只读 Memory/CPA/Web 数据投影 |
| 完整本地门禁 | Runtime 211 passed、Auth 22 passed、API/Console 契约、脱敏扫描、计划与文档门禁、MkDocs strict 全部通过 |
bash scripts/ci/run-local-tests.sh |
| 同 SHA 发布 | 历史版本曾完成 RR 部署;本次 466e7ca2 目前只有 API/Console 构建和 102 standby 部署证据,RR 主生产尚未验收 |
466e7ca2 Build Runs 41394576970、41394576999;Standby Run 41394981670 |
| 生产 API 回读 | 管理员会话返回 role=admin;runtime-status 返回 200、schema agentmeshos.agent-runtime/v1、8 个客户端均有 web_capabilities |
P20-5-11 API 回读与真实浏览器页面验收 |
| 中央模型路由客户端回读 | 中央 CPA 与每个在线 Codex 客户端配置、模型、协议、目录和真实目录探测均可见;目录漂移必须被标记 | Memory metrics 心跳 + build_agent_runtime_status 单测 + 101/102/RR/Home/Summer 真实回读 |
| 公网登录验收 | 临时管理员 API Key 换取管理员只读会话;页面账号为“API Key 管理员身份”,角色为管理员 | #account-button 与 /__agentmeshos/session 双回读 |
| 公网桌面布局 | 四域、六阶段、五项图例、单刷新按钮均可见;关系图宽度 960px,页面级横向溢出为 0 |
1440px Playwright 实拍 |
| 公网移动布局 | 图例两列排列,页面级横向溢出为 0 | 390px Playwright 实拍 |
后续实施验收原则
实施阶段必须验证四域均有状态、主机和 Agent 分列、未知/过期不显示绿色、六阶段断点可定位、页面无写操作、动态刷新可见、数据源失败可分别解释、桌面和移动端无页面级横向溢出。每项必须有真实 API 回读或浏览器验收证据;“配置存在”不能替代“实际加载/调用”。
回退方案
P20 采用增量、可撤回设计:回退时撤下新增总图入口和只读聚合路由,恢复原导航分组;不回滚 CPA、Memory、Web 服务、节点配置、规则、技能、MCP 或生产数据库。API Gateway 和 Console 部署脚本各自保留上一可用镜像,计划文档和真实审计事实保留,便于重新评审。
风险
| 风险 | 影响 | 计划处理 |
|---|---|---|
| 把历史快照当实时状态 | 页面误报健康或漂移 | 所有结论带来源和新鲜度,缺证据显示未验证 |
| 主机在线被误当 Agent 在线 | 无法定位真实客户端断点 | 永久分列展示并分别取证 |
| 状态图变成第二套治理系统 | 页面越权执行修复 | API 只读,处理入口回到原页面 |
| 配置扩散只看文件哈希 | 误判规则、技能或工具已生效 | 增加实际注入、tools/list 和真实调用证据 |
| 数据源慢导致总图假正常 | 隐藏局部故障 | 每源独立超时,结果标过期/未知 |
| 中央 Release 与节点镜像漂移 | Memory 显示最新,但 Codex 实际加载旧规则/技能 | 三层状态分开;哈希不一致和安装超时明确告警 |
| 分发器误删非受管技能 | 破坏系统或插件技能 | 只处理 .agentmeshos-managed.json 登记项,原子替换并可回退 |
⚠️ 未决项 / 需要用户决策
| 编号 | 需要确认的事项 | 当前建议 | 未确认时的处理 |
|---|---|---|---|
| D1 | 页面总入口名称 | 已确认使用 Agent 运行态势 |
已冻结 |
| D2 | 导航归组 | 已确认增加独立“Agent 状态”组,先放置总图;后续可讨论把其他入口整体迁入同组 | 第一版不删除原管理入口 |
| D3 | 四个状态域命名 | 采用中央模型路由、中央服务、Agent 客户端、中央配置与节点镜像 | P20-5 页面迁移时替换旧“101 对齐配置”标签 |
| D4 | 闭环表达 | 已采用规则、Memory Bootstrap、技能、工具、执行与验证、Memory 回写 | 已冻结 |
| D5 | 只读边界 | 第一版严格只读,只保留刷新按钮 | 已冻结 |
| D6 | 中央配置权威 | Memory 中央管理,101 作为第一个分发 canary | 其他节点按 P20-5 计划逐步接入 |
📌 本轮收口
P20-5-9 已完成分发器、Hook 证据、中枢 API、网页能力路由子层、只读面板、中央模型路由客户端子层和版本对齐代码及本地验收。P20-5-10 已完成:目标 SHA 5e1dd061 的 Console/API 已部署到 RR 主生产并健康运行。P20-5-11 现已完成:凭据文件已修正为标准 export CONSOLE_API_KEY=... 格式并轮换旧 Key;管理员 API 会话、runtime-status 和真实浏览器页面均验收通过,页面可见“网页能力路由”表格。OfficeSummer 离线保持单独状态,不影响 P20-5-11 收口。
🔁 主生产回读与状态口径统一(2026-11-02 23:40)
结论:7e24b791 的中文额外 MCP 显示名与 312e4288 的别名去重已经进入 RR 主生产 API 和页面,不需要重新发布后端;剩余的唯一不一致是工具目录徽标取前端本地映射、网页能力表取后端 status_label,本轮已统一到后端口径。
生产 API 回读
以管理员 API Key 换取真实会话(POST https://auth.yohan.fun/api-key-login 返回 200、role=admin),再读取 https://api.yohan.fun/api/agent/runtime-status:
| 检查项 | 实测结果 |
|---|---|
| 接口状态 | HTTP 200,schema_version=agentmeshos.agent-runtime/v1 |
| 客户端数量 | 8 个(101/102/RR/Home/Summer/OfficeSummer 的 Codex,外加 101 的 Paseo、OpenCode) |
| 工具 ID 重复 | 每个客户端 0 个重复 ID |
| Memory 列 | 每个客户端恰好 1 个 agentmeshos_memory |
| 额外 MCP 中文化 | fetch→网页读取、node_repl→Node.js 运行环境、sequential-thinking→结构化推理、time→时间工具 |
| 网页能力 | 8 个客户端均返回 web_capabilities,标签为中文(正常/未验证/需关注) |
生产页面回读
| 检查项 | 实测结果 |
|---|---|
| Console 首页 | https://console.yohan.fun/ HTTP 200,81202 字节 |
| 静态脚本 | /app.js?v=29f37596…c96eb,386333 字节,与源码一致包含“工具与 MCP 目录”“网页能力路由”“Agent 运行态势” |
| 节点矩阵表头 | 客户端、主机、Agent、版本、规则、技能、工具、Memory、结论;没有模型、API、中央路由重复列 |
| 工具目录单元格 | 只渲染状态徽标与“配置/安装/运行”证据,不重复工具名 |
本轮统一改动
工具目录单元格原来调用 agentRuntimeToolStatusLabel(status) 自行翻译,网页能力单元格使用后端 status_label,同一个 healthy 在前者显示“可用”、在后者显示“正常”。现在工具目录改为 status_label || agentRuntimeToolStatusLabel(status),两张表同源同词,旧载荷仍可回退到本地映射。对应静态契约新增断言 item?.status_label || agentRuntimeToolStatusLabel(status),防止再次漂移。
测试
| 检查 | 结果 |
|---|---|
node --check tools/console-site/src/app.js |
通过 |
bash tools/console-site/tests/workspace-contract.sh |
PASS |
node tools/console-site/tests/browser-contract.cjs |
PASS |
tools/api-gateway/tests/test_agent_runtime.py |
agent_runtime=passed |
发布与备用控制面
| 事项 | 证据 |
|---|---|
| 主生产 Console 已更新 | 统一后的生产脚本为 /app.js?v=48b70f84…eacf8(386355 字节),包含 status_label || agentRuntimeToolStatusLabel |
| 备用控制面 102 已追平 | Run 41479214334(b2d1315d):dedupe、verify、build、deploy 全部 success;Sync RR snapshot and deploy standby control plane 与 Verify standby read-only contract 均 success |
| GHCR 拉取瞬时故障已加固 | 首次 docker pull 出现 TLS handshake timeout;Verify standby images 现改为 3 次有界重试(间隔 15/30 秒),后续运行构建步骤成功 |
残余风险
- OfficeSummer 仍按离线状态保留,不参与在线验收结论。
- 真实 Chrome 会话未在本轮复用(改用真实管理员 API 会话加生产静态资源回读),如需像素级页面证据,应补一次真实浏览器截图。
- 备用控制面只在镜像类工作流触发时自动追平;纯文档或纯工作流提交期间它会短暂落后,直到下一次带镜像变更的提交。
本轮“未验证 / 需关注”收敛(2026-11-03)
| 问题 | 根因 | 处理 |
|---|---|---|
| 101 本地 Fetch 兜底显示“节点尚未上报工具目录” | 101 安装的资产分发脚本是 11 月 1 日旧版,缺“本地兜底盘点” | 安装仓库版脚本并回读,工具目录出现独立的本地兜底行 |
| Hook 与心跳各维护一份工具清单 | codex_memory_hook._tool_inventory_snapshot 硬编码 7 项,不含本地兜底 |
Hook 改为复用资产分发脚本的盘点结果,工具目录只保留一个采集器 |
| 远程 MCP 入口长期停在“未验证” | 聚合要求安装状态为 installed,远程入口记录的是 remote |
聚合接受 installed 与 remote,并补回归断言 |
工具目录缺少 mcp_servers 时整页聚合抛异常 |
reported_servers 可能为 None |
补空值兜底,缺字段时按空列表处理 |
| 本地兜底只有安装检查,无法证明可用 | 从未执行过不依赖中央网关的真实抓取 | 新增 scripts/maintenance/web-fetch-local-acceptance.mjs,真实抓取后写入 acceptance.json;状态读取该证据,7 天后自动过期 |
| 备用控制面校验步骤没有网络重试 | verify-image-pair.sh 的 GHCR 清单读取是单次调用 |
改为 4 次有界重试,内部镜像清单读取改为 3 次有界重试 |
| 中央 Web Search 长期显示“最近真实调用未验证” | 状态页探测沿用 5 秒通用超时,聚合搜索经常超时;且每 15 秒探测一次会加重上游负担 | 探测改为 20 秒独立超时、失败重试一次、结果缓存 10 分钟 |
| 心跳与 Hook 各自上报工具目录,旧快照会覆盖新结果 | 聚合按固定通道顺序覆盖,不看时间 | 改为取 reported_at 最新的一份清单 |
| 本地兜底状态无法引用真实调用 | 盘点只看文件是否存在 | 盘点读取 Hook 的 web_route_events 与本地 acceptance.json,成功与失败都有时间证据 |
真实证据:101 本地兜底直接用本机 Router 抓取 https://example.com,返回 HTTP 200、后端 mcp-server-fetch、正文 190 字符,写入 acceptance.json 后运行态势显示“本地兜底已真实验收”。
🩺 运行态势对象三分与证据口径收敛(2026-11-04,P20-5-12)
结论:运行态势不再要求每个客户端都套用 Codex 六层闭环,而是按“Codex 核心能力、可选扩展、非 Codex Agent 自有运行态势”三类对象分别取证。在线对象的正常状态必须来自真实证据;缺证据就显示“未验证”并进入异常清单,不能靠隐藏单元格变绿。
问题与判定
| 现象 | 根因 | 判定 |
|---|---|---|
| 在线 Codex 出现“不适用”单元格 | 工具清单按平台角色把不适用的工具写成 not_applicable 行 |
这不是状态,而是采集器替页面做了结论;改为不进入核心表 |
| Paseo/OpenCode 在 Codex 六层里全部“不适用” | 六层是 Codex Hook 契约,非 Codex Agent 没有 Bootstrap、技能选择和写回链路 | 复用会把不存在的能力当成故障;改为该 Agent 自有心跳与服务检查 |
| Memory 专项缺失时停在“未验证” | Memory 诊断行不一定覆盖每个客户端 | 不能用规则、技能、工具层“推导”出绿色;只允许使用该客户端在 Memory 侧的通道证据 |
| 工具目录与网页能力表部分重复 | 两张表来自同一份工具清单的不同投影 | 允许重叠,但核心表不再混入可选扩展 |
三类对象
| 对象 | 成员 | 证据 | 页面位置 | 禁止 |
|---|---|---|---|---|
| Codex 核心能力 | agentmeshos_memory、local_search_registry、web_fetch、web_fetch_local、playwright、kimi_webbridge、cua-driver、context7 |
配置、安装、运行、真实调用与最近成功时间 | 工具与 MCP 目录、网页能力路由 | 缺证据时隐藏,或标成“不适用” |
| 可选扩展 | node_repl、sequential-thinking、time、旧 fetch |
配置、安装、最近使用 | 新增“可选扩展”表 | 计入核心必检,或删除节点配置 |
| 非 Codex Agent | 101 的 Paseo、OpenCode | 客户端心跳加本地服务检查 | 新增“非 Codex Agent 运行态势”表 | 套用 Codex 六层或 Codex 工具目录 |
非 Codex Agent 的本地服务检查固定为:Paseo 检查 paseo.service;OpenCode 检查 opencode-headless.service 与 opencode-mem-web.service。任一服务未运行即“需关注”,并写入异常清单,不等到用户翻表才发现。
Memory 专项证据
| 规则 | 说明 |
|---|---|
| 优先 Memory 诊断行 | 存在 codex-observability 行时直接使用该行结论 |
| 缺行时只投影 Memory 侧通道 | 必检 bootstrap、event_ingest、tool_call,参考 recall、write |
| 不用外层六层洗绿 | 规则、技能、工具层成功不能替代 Memory 内部证据 |
| 没有通道证据仍是“未验证” | 保留未验证并进入异常清单,不生成绿色兜底 |
新鲜度口径
| 项 | 原值 | 现值 | 依据 |
|---|---|---|---|
| 实时通道与工具证据 | 30 分钟 | 6 小时 | 30 分钟会把空闲节点的真实正常状态误判为过期 |
| 资产安装回执 | 7 天 | 7 天 | 属于持久事实,实时性由客户端心跳负责 |
实施映射
| 文件 | 变更 |
|---|---|
tools/api-gateway/src/agent_runtime.py |
核心工具不再产出 not_applicable 行;可选工具标记 optional;非 Codex Agent 生成 agent_status 并参与状态与异常;Memory 专项按通道证据投影 |
scripts/maintenance/agentmeshos-agent-assets-sync.py |
心跳新增 local_services 检查;CUA 增加 status 探测 |
tools/console-site/src/app.js、tools/console-site/src/index.html |
核心表排除可选工具;新增“可选扩展”与“非 Codex Agent 运行态势”两张表;Codex 六层矩阵只展示 Codex |
| 测试 | test_agent_runtime.py、agent-assets-sync-test.py、browser-contract.cjs 同步断言 |
验证与剩余动作
| 检查 | 结果 |
|---|---|
tools/api-gateway/tests/test_agent_runtime.py |
agent_runtime=passed |
scripts/maintenance/tests/agent-assets-sync-test.py |
通过 |
bash tools/console-site/tests/browser-contract.sh |
通过 |
python3 -m py_compile 两个 Python 文件 |
通过 |
git diff --check |
通过 |
本节的代码与测试已完成,生产侧还没有收口:
| 事项 | 当前状态 | 影响 |
|---|---|---|
| Memory 项目侧的在线判定 TTL 与缺行诊断契约 | 待实施(mcp-memory-server 仓库) |
在线客户端缺行应成为真实问题,而不是靠 AgentMeshOS 投影 |
| RR 主生产 API 与 Console 部署 | 待执行 | 用户当前访问的页面仍是旧版 |
| 各节点资产同步器刷新与心跳重启 | 待执行 | 非 Codex Agent 的本地服务检查需要在节点上真正运行 |