# 22 domainCheck 海外 Codex 驾驶员与 Ops Center 落地路线 如果当前目标已经从“设计 Codex 驾驶员”进入“准备正式上线”,建议先补看: - `docs/25_domainCheck_海外单脑控制面上线收口总表.md` - `docs/schemas/ops_driver_contract.md` - `docs/schemas/ops_stack_diagnosis_contract.md` ## 一、目标收口 这套体系后续不应该再依赖: - 人工登录每台大陆机器 - 手工 `systemctl` - 手工复制 `journalctl` - 人工判断哪台机器在跑、哪台机器没跑 要收口成两种都能工作的模式: ### 模式 A:有 Codex - 海外主机部署 Codex - Codex 作为智能驾驶员 - 自动读取集群状态、同步状态、参与检测节点、日志回传状态 - 自动决定下一步执行哪类运维动作 ### 模式 B:没有 Codex - 海外后台照样能点按钮 - 后台把按钮动作转换成标准化 `ops job` - 控制面自动分发到节点 - 节点回传执行结果、日志、诊断摘要 一句话: > Codex 负责“智能判断”,Ops Center 负责“标准动作执行”。 --- ## 二、推荐最终结构 ### 1. 海外控制面 海外控制面承担: - Web 前端 - API 控制面 - Ops API - 发布包管理 - 节点纳管 - 日志汇聚入口 - 运维任务中心 ### 2. 大陆节点 大陆节点统一视为“被托管节点”: - controller / worker 主服务 - node agent - systemd - 本机诊断采集器 ### 3. 三条运维链路 #### 主链路:Agent 拉任务 - 最终常态方案 - 适合日常安装、更新、巡检、采日志 #### 辅链路:后台按钮 - 前端触发动作 - 后端创建 `ops job` - 节点 agent 执行 #### 兜底链路:SSH - 只保留给首次 bootstrap 和紧急救援 - 不再作为日常主流程 --- ## 三、当前代码基座已经具备的条件 当前仓库已经具备这些基础: - `runtime/status` - `runtime/cluster` - `runtime/readiness` - `runtime/sync-summary` - debug handoff / diagnosis - 远端日志回传开关基础 - 检测参与节点与待命节点视图基础 这意味着我们不是从零开始,而是已经有: > 运行态观测基座 现在需要补的是: > 运维动作编排基座 --- ## 四、建议的落地顺序 ### 第 1 步:先统一成 Ops API 本次先补: - `/api/v1/ops/overview` - `/api/v1/ops/capabilities` - `/api/v1/ops/blueprint` - `/api/v1/ops/runbook` - `/api/v1/ops/nodes` - `/api/v1/ops/jobs` 这一步的意义不是“已经远控完成”,而是先把控制面语言统一起来。 也就是以后无论: - Codex 判断 - 后台按钮 - 节点 agent 执行 都围绕统一的 `ops` 模型展开。 后续发布链路也应保持这个原则: - `release launchpad` - `ops overview.driver_recommendations` - `ops runbook.release_progression` 三者必须共用同一份发布状态机,而不能各自维护一套“推荐下一步”。 同理,标准作业路径也不应只是“展示文案”: - `ops runbook.control_sequences` - `POST /api/v1/ops/runbook/sequences/{sequence_key}/resolve` - `POST /api/v1/ops/runbook/sequences/{sequence_key}/execute` 这三层组合起来,才是海外 Codex 驾驶员和后台按钮都能复用的统一作业入口: - `control_sequences` 负责提供当前应该走哪条标准路径 - `resolve` 负责把这条路径收口成“此刻真正要执行的 driver action / node_codes / payload” - `execute` 负责真正触发后端动作 这样海外 Codex 可以先做: 1. 读取 `runbook` 2. 对目标 sequence 调 `resolve` 3. 判断是自动执行、请求确认,还是只生成建议 4. 最后再调 `execute` 同样地,发布审阅动作也不应只是“跳到某个页面再看”: - `review_smart_rollout_preview` - `review_control_rollout` - `fix_rollout_blockers` 现在这类动作应该直接返回结构化 `release_launchpad_review` 结果,至少包括: - `latest_release` - `launchpad_status` - `preview` - `smart_rollout` - `target_node_codes` - `gap_rows` 这样没有前端时,Codex、CLI、自动化任务也能直接基于 launchpad 预案判断下一步,而不是先依赖 UI 才能继续。 这里还要把自动化等级口径固定下来,避免后面又把“审阅”和“执行”混成一类: - `review_smart_rollout_preview` - `review_control_rollout` - `fix_rollout_blockers` 这三类动作现在应统一视为: - `safe_auto` - 只读审阅 - 可以直接由后端执行并返回结构化 `release_launchpad_review` 而真正会创建发布或放量对象的动作,例如: - `publish_latest_worker` - `create_smart_release_rollout_worker` - `create_smart_release_rollout_control` - `create_release_rollout_worker` - `create_release_rollout_control` 则必须继续归类为: - `guarded_auto` - 先确认,再执行 - 必须走正式的发布 / rollout 审批与审计链 这样海外 Codex、CLI、按钮驾驶舱三边看到的规则才会一致: - “看预案”可以自动跑 - “创建放量”不能静默自动提交 而不是把判断逻辑重新写在 Codex prompt 或后台页面里。 同样,`GET /api/v1/ops/codex-brief` 和 `GET /api/v1/ops/stack-diagnosis` 也不应该只返回“人看得懂的摘要”,还要内嵌: - `contract_navigation.primary_contract_key` - `contract_navigation.contract_keys` - `contract_navigation.detail_endpoint_pattern` 以及每条 entry / issue 对应的 contract hints。 现在这条规则应继续扩展到: - `GET /api/v1/ops/driver-feed` - `GET /api/v1/ops/activity-stream` 也就是说,不只是 Codex 摘要层,连“驾驶主线”和“统一活动流”本身也必须能直接给出 contract navigation,页面、CLI、海外 Codex 才能真正顺着协议跳转,而不是再各自猜一遍。 这样海外 Codex 驾驶员在收到“建议动作”或“总检缺口”后,下一步不是靠 prompt 猜协议,而是可以直接按 contract key 去拉: - `GET /api/v1/ops/contracts/{contract_key}` 这才是真正可持续的“驾驶层”,而不是一次性的提示词工程。 现在这条链路还要再收口一层: - `GET /api/v1/ops/go-live-summary` - 作为页面、CLI、海外 Codex 共用的稳定“上线收口摘要” - `GET /api/v1/ops/codex-brief` - 继续返回 `go_live_summary` - `GET /api/v1/ops/driver-feed` - 继续返回 `go_live_summary` 也就是说,海外 Codex 驾驶员的固定起手式现在应变成: 1. 先读 `go-live-summary` 2. 再读 `codex-brief` 3. 真要解释阻断原因、看主车道、抄命令时,再下钻 `stack-diagnosis` 这样 Codex 不再需要从零拼“当前能不能上线”,而是先接住一份稳定结论,再进入解释层和动作层。 这里还要继续固定一个口径: - `go_live_summary.go_live_status` - 回答当前是否已经进入统一收口 / 联调 / 复核车道 - `go_live_summary.publish_status / publish_ready` - 回答当前是否已经满足正式发布门禁 同时还要把“接入缺口是否已经影响发版门禁”的字段也固定下来,避免海外 Codex 继续自己拼 launchpad gap: - `go_live_summary.launchpad_onboarding_bootstrap_pending_nodes` - `go_live_summary.launchpad_onboarding_acceptance_ready_nodes` - `go_live_summary.launchpad_recommended_target_node_code` - `go_live_summary.launchpad_recommended_recovery_label` - `go_live_summary.launchpad_recommended_recovery_summary` 这样海外 Codex 的默认判断就应该变成: 1. 如果 `publish_status = blocked` - 先看硬阻断 2. 如果 `publish_status = attention` - 再优先看 launchpad 是否只是节点接管缺口 3. 如果 launchpad 已经给出 - `recommended_target_node_code` - `recommended_recovery_summary` 那就直接进入节点级恢复动作 而不是再去从 `release_launchpad.worker_rollout_preview.policy_preview.release_gate.rows` 里二次翻译一次。 也就是说海外 Codex 的第一轮判断必须先分清: - “现在可以继续收口” - 和 “现在可以正式发版” 这两个结论不能再混成一句模糊建议。 这里再补一个已经适合前后端直接消费的收口字段: - `driver-feed.automation_coverage` - `codex-brief.automation_coverage` 它们现在应该统一返回至少这些统计: - `safe_auto_total` - `guarded_auto_total` - `mixed_total` - `ui_only_total` - `blocked_total` - `preview_only_total` - `backend_handled_total` - `execution_ready_total` - `human_dependency_total` - `launch_status` - `launch_ready` 这组字段的定位要固定: - `automation_level_counts / recommendation_counts` 回答“当前动作池的自动化构成” - `preview_only_total` 回答“现在有多少动作虽然可自动跑,但本质仍是只读预览/聚焦/审阅” - `backend_handled_total` 回答“当前驾驶主线里有多少动作已经真正后端化,不再依赖人工进页面” - `execution_ready_total` 回答“此刻可以直接执行或确认后执行的动作总数” - `human_dependency_total` 回答“此刻仍需要人工复核、进入工作区、或先排阻断的动作总数” - `launch_status / launch_ready` 给页面、CLI、Codex 一个统一的自动化侧收口判断,而不是每层再各自猜 这样后续前端顶部摘要、Codex 驾驶提示、CLI 巡检输出,都可以共享同一套“自动化覆盖率”口径。 这里还要固定一个前端交互约束,避免页面重新退回“按钮点了只弹几条 toast”的碎片状态: - Ops Center 首屏的 - 执行默认下一步 - 定位下一步 - 看下一步契约 - 进入主处理面板 - 复制收口命令 - 复制快检命令 - 这些动作都应统一回到 - `驾驶回执条` 也就是说,首屏动作执行后,页面应该统一返回: - 成功 - 关注 - 阻断 三类结构化回执,而不是: - 有的只弹 toast - 有的静默跳转 - 有的打开抽屉但没有说明 这样值班时第一屏不只是“能点动作”,还必须能在第一屏立即知道: - 动作是否已经生效 - 当前是否已经进入下一个处理面板 - 还是仍然缺少上下文 / 需要人工继续处理 同时,`doctor-export / doctor-decision` 现在也不应只返回: - `required_failures` - `optional_unavailable` - `recommended_commands` 还要一起返回: - `scene_log_reports_total` - `scene_log_reports_ok` - `scene_log_status_counts` - `scene_log_reports` 这样海外 Codex 读取一份 `manifest.json` 或 `doctor-decision` 摘要时,不只是知道“总检建议去看某台节点”,还知道: - 关键节点现场日志附件有没有真正打出来 - 打出来的是 `healthy / full_capture` 还是 `waiting_sample / missing_sample` - 下一步应该继续看 `driver-feed` 还是直接下钻具体 `scene-node-log` 同时,在线驾驶层本身现在也应固定暴露: - `driver-feed.scene_log_observation` - `codex-brief.scene_log_observation` 这两个字段不是替代 `doctor-export` 附件,而是给“当前这一刻”的在线控制面提供统一口径: - 现场日志是否关闭 - 是否已经开启但仍在等样本 - 当前最适合继续下钻的节点是谁 - 对应的正式 `focus_ref` 是什么 这样离线交接包看 `scene_log_reports`,在线驾驶层看 `scene_log_observation`,职责就完全分开了。 同时,页面侧为了减少额外请求,现在也应优先复用 `GET /api/v1/ops/runbook` 自带的: - `primary_resolution` - `secondary_resolution` 也就是: - 页面首屏直接使用 runbook 内嵌的解析快照 - CLI / Codex / 自动驾驶器在需要单独复核某条路径时,再额外调用 `resolve` 这样“运行手册快照”和“单条路径即时解析”就有了清晰分工,不会每个入口都反复打一轮解析请求。 当前还额外补了一个最小任务闭环: - 可登记托管节点 - 可创建 `ops job` - 可查看 `ops job` 执行记录 - 当前节点可先本机即时执行部分 `runtime.*` 动作 这让“后台按钮触发 -> 标准任务留痕”已经开始成型,而不是继续堆零散脚本。 当前运维中枢还补了一层很关键的“批量巡检捷径”: - 真正参与检测节点 - 在线未参与节点 - 全部有效执行节点 它们不会直接执行 shell,而是把目标节点批量预填到 `diagnostics.collect` 模板里,再统一创建 `ops job`。 这个设计的意义是: - 页面先把“节点分组口径”统一好 - Codex 和后台按钮复用同一套动作模型 - 后续节点变多时,不需要每次人工挑选机器 当前这层快捷入口只纳入: - 已纳管 - 已启用 - Node Agent 在线 - 当前属于有效执行节点 这样能避免“页面看起来能点,但其实任务根本发不到节点”的假动作。 并且这层已经不只是“打开模板”,还开始支持标准巡检序列: - `health.snapshot` - `logs.collect` - `diagnostics.collect` 也就是一键把“健康快照 -> Worker 日志 -> 诊断包”整套任务批量排进 `ops job` 队列。 这样后续无论: - 海外 Codex 自动判断 - 还是后台按钮人工触发 都复用同一套巡检动作编排,而不是再写新的临时脚本。 现在 OpsCenter 还要继续并入“执行现场”: - 直接看真正参与检测节点 - 直接看在线但未参与的待命节点 - 直接看远端日志回传当前是关闭 / 关键 / 全量 - 并且在同一页上切换日志回传模式 也就是说,海外驾驶舱不应该要求操作者再切去 Runtime 页面拼状态,而要在运维中枢里直接完成“观察现场 -> 切日志回传 -> 下发标准巡检”这一整段动作。 同时运维中枢开始具备第一版“驾驶建议卡”: - 首个缺口节点优先执行接入收口 / 接管验收 - 先补现场日志回传 - 先看真正参与检测的节点 - 再排查在线未参与节点 - 最后进入 Release / Rollout 其中“先补现场日志回传”很关键: - 如果参与节点存在,但远端日志回传还没开 - 驾驶建议应优先让操作者开启关键回传 - 如果日志回传已开但还没有现场样本 - 则优先抓 Worker 日志,确认为什么现场过程没被镜像回来 - 日志回传本身也应该成为正式 contract,而不是只有一个布尔开关: - 当前状态是关闭 / 等待样本 / 部分覆盖 / 关键覆盖 / 全量观察 - 当前参与节点覆盖了几台 - 哪些参与节点仍未回传样本 - 下一步建议动作是什么 这一步的意义是把“海外 Codex 驾驶员”的判断逻辑,先沉淀成页面里可见、可点、可回执的正式入口。 同样,“参与检测节点”也不能只给一个总数,而要继续拆成: - 执行中 / 已领待跑 - 近窗刚有吞吐 - 在线待命 - 负载待确认 这样海外控制面看到“在线 3 台、有效执行 3 台”时,才不会误以为这 3 台都在真正做同一种事情。 同理,Release / Rollout 也不能只停留在“有没有版本”这一层,而要补成正式门禁对象: - `release_hub.default_rollout_gate` - 里面明确给出: - 默认 Release 是谁 - 默认 Rollout 目标节点是谁 - 当前门禁状态是 `missing_release / release_not_ready / artifact_missing / no_targets / blocked / attention / ready` - 当前阻断原因、告警原因、推荐动作 - 当前 remote-agent 就绪数、巡检通过数 这样首页驾驶建议、Release Hub、Codex 自动驾驶、后续后台按钮,才能基于同一份门禁判断,而不是页面自己再拼一套“能不能发版”的逻辑。 现在这层还要继续后移: - `GET /api/v1/ops/overview` 不只返回运行摘要 - 也直接返回 `driver_recommendations` - 每条建议带标准化 `action_code`、节点列表和展示文案 这样页面只是负责把动作映射到现有按钮,而不是自己再次判断一遍优先级。 继续往下一步,就是把能标准化的建议动作直接后端化: - `POST /api/v1/ops/driver-actions/execute` - 先覆盖: - 开/关现场日志回传 - 批量标准巡检 - 批量抓 Worker 日志 - 批量收诊断包 这样页面、脚本、Codex 驾驶员都先走同一个后端执行入口;还不能后端化的动作,再暂时回退到前端交互。 并且动作命名也要继续收敛到通用语义: - `run_standard_inspection` - `open_worker_logs` - `open_diagnostics` 不要长期把动作名绑死在 `participating / standby` 这种页面上下文里,否则后续同一动作很难在不同入口复用。 现在又继续往后收了一层: - `GET /api/v1/ops/playbooks` - `GET /api/v1/ops/playbook-runs` - `GET /api/v1/ops/playbook-runs/{run_code}` - `GET /api/v1/ops/playbook-runs/{run_code}/events` - `GET /api/v1/ops/activity-stream` - `POST /api/v1/ops/playbook-runs/{run_code}/rerun` - `POST /api/v1/ops/playbook-runs/{run_code}/cancel` - `POST /api/v1/ops/playbooks/preview` - `POST /api/v1/ops/playbooks/execute` 这层不是替代 `ops job`,而是把一组固定的高层运维意图继续往下展开。 同时每一次 playbook 执行,不应该只留下零散的子任务,而应该形成一条正式“编排回执”: - 每次执行生成独立 `run_code` - 每个展开后的 `ops job` 都挂上同一份 playbook metadata - 控制面可以按 `run_code` 重新聚合: - 本轮编排是什么 - 目标节点有哪些 - 当前卡在哪一步 - 最近一条可查看事件的任务是哪条 这样页面、Codex 驾驶员和后续自动化,都不再需要自己从多条 `ops job` 记录里反推“这一轮到底发生了什么”。 继续再往前一步,playbook run 不能只“看”,还要能直接作为运维对象被操作: - 直接按 `run_code` 查看详情 - 直接按 `run_code` 重跑同一轮编排 - 直接按 `run_code` 取消当前仍未收口的子任务 这样运维中心面对的就不再只是“原子 job 列表”,而是正式的“编排回执对象”。 再往前收一层,OpsCenter 还要把: - playbook run - standalone ops job - rollout 统一压成一条“活动流”。 这样海外驾驶舱里看到的就不再是三块割裂入口,而是: - 最近发生了什么 - 这是编排、单任务还是 rollout - 当前状态是什么 - 一键应该跳到哪个详情抽屉 这一层已经开始落成: - 后端聚合 `activity-stream` - 前端活动流面板直接复用: - playbook run 详情抽屉 - ops job 事件抽屉 - rollout 任务抽屉 最近又补了一层很关键的驾驶口径: - `runbook_sequence` 也就是说,统一活动流里现在不只收“已经发生的执行回执”,还会收: - 当前固定标准作业路径此刻解析出的下一步动作快照 这样海外控制面看到活动流时,能同时得到两类信息: - 最近现场到底发生了什么 - 当前更推荐先进入哪条固定路径 并且这条 `runbook_sequence` 活动不是新 job,也不是新 rollout,而是: - 对 `ops runbook.control_sequences[*].primary_resolution` 的时间线化投影 它点进去后应直接把页面焦点定位到对应的标准作业路径卡片,而不是再跳去一个无关抽屉。 再往前一步,还需要一份正式给“驾驶员”消费的统一结果: - `GET /api/v1/ops/driver-feed` 这份 feed 不应该只是页面内部拼接,而要由后端直接给出: - 当前最高优先建议 - 其他驾驶建议 - 标准作业路径 并且每条都明确声明: - 这是 `driver_action` 还是 - `runbook_sequence` 这样海外 Codex、后台按钮和 CLI 才能共享一套真正稳定的执行 contract,而不是继续在前端或 prompt 里二次判断。 在这层之上,还要再补一层真正适合“海外 Codex 自动驾驶”的判断结果: - `GET /api/v1/ops/codex-brief` 这层不是重复造一个 feed,而是在 `driver-feed` 之上补齐: - 这条动作是 `safe_auto` - 还是 `guarded_auto` - 还是 `mixed` - 还是 `ui_only` - 或者已经 `blocked` 同时直接给出: - 推荐动作口径: - `auto_execute` - `confirm_then_execute` - `resolve_first` - `open_ui` - `blocked` - 最终应命中的 API: - `/ops/driver-actions/execute` - 或 `/ops/runbook/sequences/{sequence_key}/execute` - 请求预览: - `action_code / node_codes / action_payload` - 或 `sequence_key / secondary / action_payload` 这样海外 Codex 就不需要再把“哪些能自动开、哪些必须人工确认、哪些只能进 UI”重新写死在 prompt 里,而是直接消费控制面给出的统一自动驾驶 contract。 并且活动流不该只是“堆最近 20 条”,还要具备正式运维视角: - 按 `kind` 筛: - playbook run - standalone ops job - rollout - runbook sequence - 按 `status` 筛 - 按关键词搜: - 编号 - 对象 - 摘要 - 发起来源 这样节点数和动作数上来以后,活动流才能继续保持可用,而不会退化成人工翻时间线。 这样后续 Codex 驾驶员与人工操作员共用的就是同一条“最近活动 -> 直接钻取”的驾驶链路。 最近又再收一层“可读性 contract”: - `GET /api/v1/ops/playbook-runs` 已支持按 `status`、`group_key`、`query` 过滤 - 回执聚合结果会直接给出: - `focus_level` - `focus_step_key` - `focus_step_title` - `focus_summary` - `problem_steps` - `active_steps` - 前端不再只展示“这轮 run 有几步”,还会直接提示: - 当前最该看的步骤是哪一步 - 它是在执行中,还是已经异常 - 应该优先去看哪条事件入口 这样海外控制面看到的就不是一张“机械回执表”,而是已经带有现场聚焦能力的编排驾驶面板。 继续再补一层之后,编排详情也不该只停在“看 step 状态”,还要能直接看整轮事件流: - 不再要求操作者点进每一条子任务再翻事件 - 控制面可以直接按 `run_code` 拉整轮编排的聚合事件 - 还能继续按 `step_key`、`node_code` 做二次过滤 这样 playbook run 在海外控制面里的形态才完整: - 能看总状态 - 能看当前焦点 - 能看每一步 - 也能直接回放整轮现场事件 再往前收一层,顶部“运维驾驶建议”也不该只盯节点和日志,而要开始直接消费 playbook run: - 如果最近存在异常编排,驾驶建议优先提示这轮 `run_code` - 建议里直接带上当前焦点步骤 - 点一下就能打开该轮编排详情或最近事件 这样海外控制面看到的就是: - 先告诉你哪轮编排最值得优先处理 - 再把你直接带到对应的编排现场 这才符合“海外 Codex 驾驶员 / 按钮化驾驶舱”的设计目标。 再往前一步,驾驶建议还不该只盯 playbook run,本轮已经开始让它继续消费统一活动流: - 如果最近存在异常 `ops job` - 或存在异常 / 待审批 `rollout` - recommendation 也应直接把这条 activity 顶上来 - 点一下直接落到对应 `job events` 或 `rollout jobs` 也就是说,驾驶建议的优先级已经开始变成: - 先看异常编排 - 再看异常活动 - 再处理接管缺口、日志回传和巡检动作 这样海外控制面才不是“会推荐很多动作”,而是真正会把操作者先送到最值得处理的现场。 再继续收一层,driver action 也不该只返回“handled / unhandled”,而要开始返回正式的 `ui-intent`: - 后端统一决定这次动作是: - 直接执行 - 创建 playbook - 还是打开某个界面入口 - 前端不再自己硬编码“这个 action_code 到底该弹哪个抽屉” 例如现在已经开始固化的 intent 方向: - `playbook_run_detail` - `playbook_run_latest_events` - `job_events` - `rollout_jobs` - `managed_node_handover` - `managed_node_edit` - `open_release_dialog` - `open_rollout_dialog` - `focus_release_hub` 这样控制面、Codex 驾驶员、后续自动化脚本三方看到的动作 contract 会越来越一致。 这里再补一条新的收口约束: - `focus_release_hub` 不应只是“打开版本区”的导航动作 - 它现在还应同时返回结构化 `release_hub_preview` 至少带: - `summary` - `launchpad` 这样页面仍然可以跳到 Release Hub,但 CLI、Codex、自动化任务即使不进页面,也能继续基于 release hub 摘要判断下一步。 同样,`release_package` 在打包自动化真正落地前,也不应继续只是“打开打包面板”: - 页面侧仍可消费 `ui_intent = open_release_dialog` - 但后端应同时返回 `release_package_preview` 例如: - `available` - `package_name` - `release_version_suggestion` - `reason` 这样海外 Codex 和 CLI 至少能先判断: - 现场是否已经存在可用发布包 - 建议的版本号是什么 - 当前卡在“缺包”还是“只是还没进页面确认” 例如: - `inspection.standard` - `health.snapshot` - `logs.collect(worker)` - `diagnostics.collect` - `scene.logs.key` - `logs.collect(worker, 120)` - `scene.diagnostics` - `diagnostics.collect(200)` 这样前端按钮、海外 Codex 驾驶员、后续自动化脚本都不需要自己再手动拼“三连动作”,而是统一复用后端定义的 playbook。 现在 OpsCenter 页面也已经开始直接接这层 playbook: - 页面可读取 `playbooks` - 页面可做 `playbook preview` - 标准巡检主入口优先直接调用 `inspection.standard` - 接管后一键验收优先直接调用 `onboarding.acceptance` 这意味着“标准巡检”第一次不再由前端自己顺序创建三组模板任务,而是正式走后端编排层。 同样的收口方向现在也已经开始覆盖“纳管新节点”与“现场观察”: - `node_onboarding` - 主动作:`bootstrap_run` - 次动作:`run_acceptance` - `scene_observe` - 主动作:`run_scene_logs_key` - 次动作:`run_scene_logs_full` - `standard_inspection` - 主动作:`run_standard_inspection` - 次动作:`open_diagnostics` - `release_progression` - Launchpad 就绪时优先:`publish_latest_worker` - 只有 Release、但还没形成明确 Launchpad 推荐时:`create_release_rollout_worker` 其中发布链要继续严格区分两种动作层级: - `review_smart_rollout_preview / review_control_rollout / fix_rollout_blockers` - 属于 `safe_auto` - 目标是读 launchpad 预案、看门禁缺口、返回结构化审阅结果 - `publish_latest_worker / create_*_release_rollout_*` - 属于 `guarded_auto` - 目标是正式创建发布 / rollout 对象 - 必须继续要求确认和审计留痕 也就是说,Runbook 里的主次步骤已经开始直接落到正式驾驶动作,而不是统一先打开弹窗再让操作者自己决定。 也就是说: - 有 Codex 时,它读这些状态后自动帮你挑动作 - 没 Codex 时,你在后台也能沿着同样的优先级直接点下去 再往下一层,运维中枢还需要具备“巡检结果收口面板”: - 不是只会发 `health.snapshot / logs.collect / diagnostics.collect` - 而是要按节点把这三类任务最近结果重新聚合 - 直接看出这台节点是: - 已健康收口 - 仍在执行 - 存在异常 - 还没形成巡检记录 这样海外控制面才真正像驾驶舱,而不是“按钮发射器”。 现在这层已经开始正式后移到后端语义: - `GET /api/v1/ops/overview` 里直接带 `inspection` - 也单独提供 `GET /api/v1/ops/inspection-overview` - 前端优先消费后端聚合结果,本地计算只作为 fallback 这样后续无论是: - 海外 Codex 驾驶员 - 页面按钮 - 自动化巡检脚本 都读同一份“节点巡检收口状态”,不会再出现页面一套、脚本一套、人工 SQL 又一套的口径分裂。 这一层再往前,还应该有“异常节点优先队列”: - 先把巡检失败 / 阻断 / 取消的节点顶上来 - 再显示仍在执行中的节点 - 最后才是未形成巡检记录的节点 并且日志聚合口径要严格: - 标准巡检只认 Worker 日志 - 不能把 Node Agent 的临时排障日志混进 Worker 巡检收口 ### 第 2 步:补 ops jobs 这一步后续建议直接以 [ops_job_contract.md](/www/wwwroot/getDomain/docs/schemas/ops_job_contract.md:1) 为正式母本,不再让页面、CLI、Codex、Node Agent 各自定义任务结构。 后续新增: - `ops_jobs` - `ops_job_steps` - `managed_nodes` - `node_log_streams` 每个动作必须有: - 谁发起 - 发给哪台机器 - 目标服务 - 执行结果 - stdout/stderr - 结构化摘要 ### 第 3 步:补 node agent Node Agent 第一版建议只做四类动作: - `service.restart` - `service.status` - `health.check` - `logs.collect` 先把最常用的远程运维闭环跑通,再逐步扩成: - `deploy.release` - `config.render` - `diagnostics.collect` - `bootstrap.finish` ### 第 4 步:补发布与回滚 正式收口成: - 海外控制面构建 release 包 - 节点下载 release - 校验 checksum - 切换软链 - 重启服务 - 失败自动回滚 --- ## 五、Codex 在这里真正扮演什么角色 Codex 不应该只是“聊天助手”,而应该是: ### 1. 运维驾驶员 Codex 读取: - readiness - cluster - sync-summary - debug diagnosis - ops overview 然后给出: - 当前是网络问题、配置问题、节点未参与、还是同步问题 - 下一步先拉日志、先重启、先巡检、还是先暂停同步 ### 2. 动作编排器 当 Codex 确认动作后: - 创建 ops job - 标准化执行 - 等待回执 - 汇总结果 ### 3. 联调加速器 以后你不需要再复制大量日志给我看,而是让 Codex 直接在海外控制面读: - 节点状态 - 任务结果 - 聚合日志 - 诊断包摘要 --- ## 六、你以后理想的操作方式 你只需要在海外控制面做三件事: ### 1. 配置节点 - 节点名称 - SSH / bootstrap 信息 - 区域 - 角色 - 发布通道 ### 2. 看状态 - 哪些节点在线 - 哪些节点是有效执行节点 - 哪些节点正在领任务 - 哪些节点只是在线待命 - 哪些节点同步失败 ### 3. 点动作 - 安装节点 - 更新节点 - 重启节点 - 拉日志 - 巡检 - 收诊断包 - 治理 Node Agent 回执积压 / 死信 如果装了 Codex,就再多一步: - 让 Codex 自动判断“该点哪个动作” ## 六点五、回执队列已经进入统一驾驶入口 当前 Node Agent 回执队列不再只是“后端看得见”,而是已经进入统一驾驶面: - OpsCenter 托管节点表可以直接打开“回执队列治理”抽屉 - `driver_recommendations` 遇到 `dead_letter / retrying` 时,会优先下发标准队列治理动作 - 海外单入口 CLI 也可以直接查看、冲刷、重放和丢弃 这意味着: - 没有 Codex 时,人工也能在海外控制面闭环处理 - 有 Codex 时,Codex 不需要自己发明死信处理逻辑 - 页面、CLI、Codex 都围绕同一组 `ops job` 入口治理回执队列 当前统一 CLI 入口已经支持: ```bash cd /opt/domaincheck/domain-api # 查看某台节点当前回执队列状态 bash domain-api/deploy/multi-region/drive_ops_center.sh queue-status mainland-worker-01 # 只看可见死信头部记录 bash domain-api/deploy/multi-region/drive_ops_center.sh queue-records mainland-worker-01 dead_letter # 立即冲刷积压回执 bash domain-api/deploy/multi-region/drive_ops_center.sh queue-flush mainland-worker-01 20 # 重放当前可见死信 bash domain-api/deploy/multi-region/drive_ops_center.sh queue-replay mainland-worker-01 20 # 对头部死信执行单条动作 bash domain-api/deploy/multi-region/drive_ops_center.sh queue-replay-record mainland-worker-01 event-ops-123-2 bash domain-api/deploy/multi-region/drive_ops_center.sh queue-discard-record mainland-worker-01 event-ops-123-2 "确认已人工归档" ``` 当前阶段仍然要严格坚持: - 所有动作都创建正式 `ops job` - 当前只操作 `record_visibility=head_only` 的可见头部记录 - 不直接 SSH 到节点手改队列文件 这样以后即使从 `head_only` 扩到“远端全量记录正式投影”,也只是扩展可见范围,不需要推翻当前治理模型。 ## 六点六、现场观察 runbook 也不再依赖弹窗 `scene_observe` 这条标准作业路径现在也开始从“打开 playbook 弹窗”收口到“直接执行正式动作”: - 主动作:`run_scene_logs_key` - 次动作:`run_scene_logs_full` - 两者都直接落到标准 `ops playbook` 执行链,而不是先让操作者进入模板弹窗二次确认 这样海外单脑在排查“谁在跑、为什么卡住、日志有没有回来”时,已经可以直接从 runbook 进入执行态,Codex 和后台按钮也能复用同一条现场观察链路。 --- ## 七、当前最优结论 当前最优路线不是继续堆更多手工排查命令,而是: 1. 以海外主机为唯一运维入口 2. 用 `ops api + ops jobs + node agent` 接管所有大陆节点 3. SSH 只做 bootstrap,不做日常主链路 4. Codex 作为智能驾驶员可选增强,但不是唯一依赖 5. 没有 Codex 时,后台按钮也能完整跑通 这条路线的优点是: - 节点越多越省心 - 跨地域调试成本显著下降 - 可以沉淀成正式运维平台,而不是临时联调脚本集合