# domainCheck Ops Stack Diagnosis Contract ## 1. 目标 这份文档用于冻结海外单脑控制面的“总检入口” contract。 它的职责不是替代: - `overview` - `link-snapshot` - `inspection-overview` - `release launchpad` - `activity-stream` 而是把这些正式 contract 再收口成一份: > 第一现场诊断结果 让下面这些消费者都先看同一份判断: - 海外 Ops Center 页面 - 海外 Codex 驾驶员 - CLI 总检脚本 - 后台按钮自动诊断 正式原则: - 总检不能只回一段说明文字 - 总检必须给出结构化问题清单 - 总检必须给出默认下一步动作 - 总检必须给出可以直接执行的推荐命令 --- ## 2. 入口接口 主入口: - `GET /api/v1/ops/go-live-summary` - `GET /api/v1/ops/stack-diagnosis` 配套来源: - `GET /api/v1/ops/contracts` - `GET /api/v1/ops/link-snapshot` - `GET /api/v1/ops/overview` - `GET /api/v1/ops/nodes` - `GET /api/v1/ops/releases/launchpad` - `GET /api/v1/ops/playbook-runs` - `GET /api/v1/ops/activity-stream` 推荐 query: - `base_url` 用途: - `go-live-summary` - 给 Ops Center 顶部收口卡、CLI 总检、Codex 驾驶员直接消费 - 返回更偏“上线判断”的稳定摘要 - 用于生成 `next_step.command` - 用于生成 `quick_commands` - 让 CLI / Codex / 页面复制出来的命令口径一致 --- ## 3. 顶层结构 建议最小结构: ```json { "generated_at": "2026-04-18 09:00:00", "diagnosis": {}, "api": {}, "surface_matrix": {}, "contracts": {}, "link_snapshot": {}, "overview": {}, "managed_nodes": {}, "release_hub": {}, "playbook_runs": {}, "activity_stream": {} } ``` 正式要求: - 顶层每一段都必须是稳定 key - 页面、CLI、Codex 不允许自己再拼第 2 套总检结构 - `go-live-summary` - 是 `stack-diagnosis` 的稳定摘要层 - 必须至少给出: - `go_live_status` - `blocking_reasons` - `warnings` - `launchpad_recommended_target_node_code` - `launchpad_recommended_recovery_label` - `launchpad_recommended_recovery_summary` - `launchpad_onboarding_bootstrap_pending_nodes` - `launchpad_onboarding_acceptance_ready_nodes` - `next_step_action_code` - `operator_title` - `recommended_commands` - `playbook_runs.problem_runs[*]` - 需要保留 `focus_ref` - 这样 CLI / Codex / 页面才能直接定位到问题编排的正式焦点 - `activity_stream.top_items[*]` - 需要保留: - `occurred_at` - `focus_ref` - `source_focus_ref` - `ui_intent_kind` - 这样总检不会把“观察摘要”再次压扁成一段不可定位的纯文本 - `go-live-summary` + `stack-diagnosis` + `driver-feed.automation_coverage` - 必须能共同驱动 Ops Center 首屏 - 不允许页面自己从局部接口重新推导一份“收口状态” --- ## 4. Diagnosis Contract 来源: - `stack_diagnosis.diagnosis` 最小字段: ```json { "contract_key": "ops_stack_diagnosis_contract", "contract_version": "v1", "registry_version": "2026-04-18", "base_url": "http://127.0.0.1:8100", "surface_status": "partial", "automation_status": "blocked", "stack_status": "blocked", "issue_total": 4, "blocking_issue_total": 1, "warning_issue_total": 3, "missing_surfaces": [ "contracts" ], "launchpad_recommended_target_node_code": "mainland-worker-01", "launchpad_recommended_recovery_label": "待执行接入", "launchpad_recommended_recovery_summary": "mainland-worker-01 还缺接入收口,先执行 bootstrap。", "launchpad_onboarding_bootstrap_pending_nodes": 1, "launchpad_onboarding_acceptance_ready_nodes": 0, "next_step": { "action_code": "bootstrap_run", "source": "issue:managed_nodes_agent_pending", "reason": "mainland-worker-01 还缺接入收口,先执行 bootstrap。", "command": "bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 bootstrap_run", "focus_ref": { "kind": "managed_node", "node_code": "mainland-worker-01" } }, "recommended_actions": [], "issues": [], "operator_hints": [], "quick_commands": [] } ``` 状态语义必须固定: - `surface_status` - `healthy` - `partial` - `broken` - `automation_status` - `ready` - `attention` - `blocked` - `stack_status` - 总结论,面向人和程序 - 推荐值为 `ready / attention / blocked` 正式要求: - `next_step` 是默认下一步,而不是“可能动作之一” - 当首个缺口节点已经明确收敛为 `bootstrap_run / run_acceptance` 时,`next_step.action_code` 不应再退回成泛化的 `fix_managed_nodes` - 当存在 `runtime_build_schema_stale` 时,`next_step.action_code` 必须优先收敛为 `api-restart` - `issues` 必须按可处理性组织,而不是只堆原始异常文本 - `quick_commands` 必须是可以直接复制执行的命令 - `next_step.focus_ref` - 是首屏“定位下一步”的正式落点 - 页面、CLI、Codex 不允许再根据 `action_code` 反推要跳去哪个区域 - `diagnosis.launchpad_recommended_target_node_code` - 代表 stack-diagnosis 已经把 Release Hub 收敛出的首个接管缺口直接下沉到总检摘要 - 页面、CLI、doctor-export、Codex 不应再分别回源二次推导 - `diagnosis.launchpad_onboarding_bootstrap_pending_nodes / launchpad_onboarding_acceptance_ready_nodes` - 代表当前接管缺口的阶段性计数 - 用来帮助总检直接区分“待 bootstrap”与“待 acceptance” - `go-live-summary.launchpad_recommended_target_node_code` - 是 launchpad 已经收敛出的首个接管缺口节点 - 页面、CLI、Codex 应优先直接显示它,而不是重新扫描 gap rows - `go-live-summary.launchpad_onboarding_bootstrap_pending_nodes / launchpad_onboarding_acceptance_ready_nodes` - 用于区分当前是“待接入”还是“待验收” - 这两个计数应作为上线收口阶段的正式 warning 来源,而不是页面本地再统计 --- ## 5. Issue Contract `diagnosis.issues[]` 最小字段: ```json { "code": "managed_nodes_agent_pending", "severity": "blocked", "layer": "managed_nodes", "summary": "托管节点虽然已经纳入 Ops Center,但 0 台 remote-agent 就绪,当前第一动作已收敛为首台节点接入收口。", "detail": "managed_enabled=3,remote_access_ready=0;首个缺口节点 mainland-worker-01:待执行接入。", "action_code": "bootstrap_run", "focus_ref": { "kind": "managed_node", "node_code": "mainland-worker-01" }, "commands": [ "bash domain-api/deploy/multi-region/drive_ops_center.sh driver-resolve http://127.0.0.1:8100 bootstrap_run", "bash domain-api/deploy/multi-region/drive_ops_center.sh node-bootstrap-plan http://127.0.0.1:8100 mainland-worker-01" ] } ``` 严重级别建议固定为: - `blocked` - `warning` - `info` 正式要求: - `summary` 用于列表展示 - `detail` 用于展开解释 - `commands` 用于终端直接执行 - 不允许只有中文文案,没有结构化定位信息 对于运行时版本漂移,还应允许出现这类 issue: ```json { "code": "runtime_build_schema_stale", "severity": "warning", "layer": "runtime_build_info.schema", "summary": "仓库已经具备新的节点接管能力,但运行中的 build-info 仍未声明对应路由键,当前更像 API 还没重启到最新代码。", "detail": "supports_install_command_block=true;route_surface_declares_bootstrap_plan=false", "action_code": "api-restart", "focus_ref": { "kind": "runtime_build_info", "section": "schema", "expected_route_key": "ops_node_handover_bootstrap_plan" }, "commands": [ "bash domain-api/deploy/multi-region/drive_ops_center.sh runtime-refresh-recover http://127.0.0.1:8100", "bash domain-api/deploy/multi-region/drive_ops_center.sh stack-diagnosis http://127.0.0.1:8100 summary", "bash domain-api/deploy/multi-region/drive_ops_center.sh node-bootstrap-plan http://127.0.0.1:8100 mainland-worker-01" ] } ``` --- ## 6. Surface Matrix Contract 来源: - `stack_diagnosis.surface_matrix` 最小字段: ```json { "status_counts": { "total": 8, "available": 7, "missing": 1 }, "items": [ { "name": "contracts", "available": false } ] } ``` --- ## 7. Runtime Build Info Extension `stack_diagnosis.runtime_build_info` 以及 `/api/v1/runtime/build-info` 建议至少包含: ```json { "repository_capabilities": { "supports_install_command_block": true, "supports_multi_layout_bootstrap": true }, "route_surface_declares_bootstrap_plan": false, "runtime_schema_stale": true } ``` 语义要求: - `repository_capabilities` - 表示当前仓库代码本身具备的能力 - `route_surface_declares_bootstrap_plan` - 表示运行中的 API build-info 是否已经声明节点级 bootstrap-plan 路由键 - `runtime_schema_stale` - 表示“仓库能力已到位,但运行中的 API 结构还停留在旧版” - 这是典型的“服务没重启到最新代码”信号,不应误判成“功能没开发完” 作用: - 让页面和 CLI 直观看出“缺的是哪一层” - 避免只看到最终 blocked,却不知道缺的是 contract、launchpad 还是 activity-stream --- ## 7. 与其他 Contract 的关系 `ops_stack_diagnosis_contract` 的定位是: - 不替代 `ops_driver_contract` - 不替代 `ops_observability_contract` - 不替代 `release_hub_contract` 它负责: - 把它们统一收口成第一现场诊断 对于 Ops Center 页面还必须补充一条: - 首屏负责“结论 + 默认下一步 + 复制命令 + 动作回执” - 下方详情区负责“issue / surface / launchpad / activity / runbook”的展开与下钻 - 不允许详情区覆盖首屏的默认下一步结论 所以正确消费顺序应该是: 1. 先看 `stack-diagnosis` 2. 再根据 `issues / next_step / focus_ref` 下钻到: - `overview` - `link-snapshot` - `inspection-overview` - `release launchpad` - `activity-stream` --- ## 8. CLI / Codex / 页面统一约束 CLI: - `check_ops_center_stack.sh` 应优先调用 `GET /api/v1/ops/stack-diagnosis` Codex: - 默认先读取 `stack-diagnosis` - 再决定是继续 `driver-resolve`、`doctor` 还是细分检查 页面: - 顶部总检卡片必须优先消费 `diagnosis` - 不能重新从多个 endpoint 拼一份影子状态 只有这样,海外单脑控制面才能真正进入: > 单入口观察,分层下钻,统一执行