Doctor CLI 的 Kernel 定义跨 Command 稳定的生命周期、数据流、扩展边界和信任边界。Provision、Collect、 Eval、Perf 与 Chat 共用启动上下文和基础设施,但各自拥有不同的领域结果:
| 主路径 | 主要结果 | 与 Collect 的关系 |
|---|---|---|
| Provision | 外部能力或环境准备完成 | 不隐藏在 Collect 中;由用户显式触发 |
| Collect | 可复查的 Evidence、Finding、Coverage 与诊断产物 | 确定性诊断主路径 |
| Eval | Case 执行记录及关联证据 | 复用已有 Collect 入口采集证据 |
| Perf | 受控负载结果及同窗口证据 | 复用已有 Collect 入口采集证据 |
| Chat | Agent 会话与 AgentUE 输出 | 面向无法预先固化路径的开放式问题 |
Collect Command 的最小模型是:Core 统一驱动 Prepare、Execute、Finalize;Execute 固定沿 Inspect → Probe → Detector 推进;Core 与 Plugin Service 在同一流程中贡献能力,不形成两套执行框架。
Prepare
→ 解析 Config / Profile / Target / Service
→ 选择 Core 与 Plugin Service contributions
→ 形成 access plan 与 CommandContext
↓
Execute(Core 驱动)
→ Inspect [Core Inspect + Plugin Service Inspect]
→ 汇总并冻结 Facts
→ Probe(Facts) [Core Probe + Plugin Service Probe]
→ 汇总 Observations,构建 Evidence
→ Detector(Evidence) [Core Detector + Plugin Service Detector]
→ Findings / Coverage / Diagnosis
→ Render(领域输出投影,触发位置沿用现状)
↓
Finalize
→ Artifact / Bundle
→ Delivery / Cleanup / exit status
Inspect 与 Probe 之间存在阶段屏障:选中的 Inspect 全部收敛并冻结 Facts 后,Core 才生成 Probe 计划。 Detector 只能在 Observations 汇总成 Evidence 后运行。Plugin Service 只注册 contribution;阶段推进、 调度、失败隔离和收尾始终由 Core 控制。
| 阶段 | Core | Plugin Service |
|---|---|---|
| Prepare | 解析并校验用户意图;选择 Target、Service 与 contribution;合并 Core/Plugin access needs;创建本轮上下文和清理责任 | 声明 Service、Workload、capability、dependency、access 与 contribution;校验 Plugin-owned config;不自行创建命令生命周期 |
| Inspect | 形成 Query;决定 Inspect 的依赖、顺序、预算、遍历、去重和失败隔离;驱动 Core/Plugin Inspect;规范化并冻结 Facts | 执行一次业务 Inspect,返回 Fact/Relation;拥有私有协议和业务数据语义,不拥有遍历或后续调度 |
| Probe | 根据冻结 Facts 生成计划;向 Probe 注入公共 Fact;控制依赖、策略、授权、风险和资源生命周期;驱动 Core/Plugin Probe | 执行一次业务 Probe,消费 Input/Facts 并返回 Observation;不内建循环、并发或跨 Probe 调度 |
| Detector | 构建 Evidence;统一执行 Core/Plugin Detector;校验证据引用与 provenance;形成 Coverage 和 Diagnosis | 提供纯业务 Detector,消费只读 Evidence,返回带显式证据引用的 Finding;不接收运行上下文或发起 I/O |
| Finalize | 驱动领域 Renderer,组装 Artifact/Bundle,完成 Delivery、Cleanup 与最终退出语义 | 不拥有阶段或资源生命周期;业务语义已通过 Fact、Observation 与 Finding 进入 Diagnosis |
Plugin 不必在每个阶段都有可执行逻辑。Prepare 中它主要提供声明,Execute 中贡献业务采集和判断,
Finalize 则由 Core 收口。Renderer 的领域逻辑与当前触发位置仍归 collect/<domain>/render;Finalize 只消费已准备的产物。
Inspect 回答“本轮诊断中已经知道什么”。Core Command 根据诊断目标形成由 Identity + Constraints
组成的 Query,并选择 Core Inspect 或接受该 Identity 的 Service Inspect contribution:
Query(Identity + Constraints)
→ Inspect
→ InspectQueryResult
→ ValueFact / RecordFact / RelationFact
ValueFact表达一个 kind 至多一个的领域值。RecordFact表达同 kind 可重复、带稳定recordKey的独立记录。RelationFact表达两个 Identity 之间已经由现场数据证明的关系。
Fact 在一次 Command 内足够稳定,可被后续 Probe 和 Detector 复用,但不是跨时间永远成立的真理。
InspectQueryResult 独立表达解析状态、缺失证据与截断,不能把采集状态伪装成领域 Fact。
Core 与适配后的 Plugin Fact 都携带 kind + schemaVersion + producer。runInspects 在阶段边界校验
每个叶子 Fact 的 schema identity,并要求 Core Fact 的 producer.id 等于实际执行的 Inspect.id;违反
契约属于实现错误,不能降级成 Coverage 缺口。Fact 不另设对象 ID,Detector 通过本轮 Evidence 中的
factPath 引用它。
RelationFact 可以形成后续 Query,但只有 Core Command 能决定是否继续,以及查询深度、容量、去重、 失败隔离和停止条件。Plugin 拥有 Identity、Fact、Relation 的业务语义与固定查询,不拥有自递归调度。
Probe 回答“针对已确认目标,本次主动观察到了什么”。Core 根据冻结 Facts 选择并驱动 Core Probe 与
Service Probe。领域先显式选择可公开的 Fact、Service scope、factPath 与 value shape,再由共享
Service Evidence adapter 保留原始 kind + schemaVersion + producer 并形成公共投影;adapter 不递归遍历
Evidence,也不把 Fact payload 的子对象派生成新的伪 Fact。当前选出的公共 Fact 不再按 Service、producer
或 kind 过滤;所有 Probe 共享同一份深冻结快照,只能消费,不能修改或追加 Fact。
Probe 是一次执行原语:可以使用 Core 提供的 Target-scoped infra 和授权入口,但不拥有 Command 的循环、 并发、预算、停止条件或 Evidence。Observation 只陈述某个探测时间点或时间窗口看到的状态,不能默认 代表之后的现场。Probe 之间的真实数据依赖显式声明;会产生负担或改变现场的动作必须经过 Operation 授权。
Plugin Workload Probe 的 Observation 契约由 Plugin 以 produces: ObservationDefinition 拥有;其 TypeBox
object schema 同时驱动 TypeScript payload 推导和 Core 的 Draft 2020-12 运行时验证。Core 不信任
跨动态 ESM 边界的静态类型;未通过严格 JSON/schema 校验的 payload 不进入 Evidence,校验不会强转、
补默认值或删字段。
Evidence 是本次诊断明确选择的 Facts 与 Observations。Detector 回答“已有证据说明什么”:
- Core Detector 提供跨业务通用判断。
- Service Detector 提供业务判断,可以关联跨 producer、跨 Service 的 Evidence。
- Detector 不接收
CommandContext、PluginContext或 infra handle,不执行 I/O。 - Finding 必须显式引用 Evidence 中的
factPath或observationId。 - Core 通过同一个 Detector runner 执行 Core Detector 与适配后的 Service Detector,并校验 Finding 身份、 producer、Evidence 引用和本轮唯一 ID;违反契约属于实现错误,不能降级成 Coverage 缺口。
- Coverage 表达诊断目标的证据充分度,不表达 Target 是否健康。
Fact、Observation 与 Finding 使用 kind + schemaVersion 标识 payload schema。Core kind 使用保留短名;
Plugin 本地 kind 由 Core 规范化为 plugin/<plugin-id>/<service>/<local-kind>。两者都携带结构化 producer,
消费方不能通过解析 kind 字符串猜测来源。Plugin version 标识实现版本,schemaVersion 只标识数据契约。
cli/src/plugin/evidence.ts 是 Core/Plugin Service Evidence 的统一适配边界:Core Fact/Observation 原样继承
已持久化 identity,Plugin 本地 schema 在这里统一补 namespace 与 producer;领域 projector 只拥有披露和
Service 关联决策,不能再次手写或改写 identity。
每个常规命令提供 CommandSpec<Input, Output>,普通命令和组合命令共用
run(context, input): Promise<CommandResult<Output>>。CLI 将 flags 转为领域 Input;父命令直接调用
子命令的同一入口。defineCommand 包装校验、环境准备、取消与资源收尾,因此嵌套调用仍需满足自身
的 capability 和 access 前提。
根入口只解析一次 Profile,选定的 Plugin 及其配置校验在整轮内复用。每次调用按顺序执行:
validate domain input
→ required Plugin capability + validated Plugin config
→ declared Host / Kubernetes environment
→ selected Target + staged access plan + permission check
→ domain work or child CommandSpec.run calls
→ invocation result + resource cleanup
组合命令逐个调用已选择的子命令;一个子命令不可用时,其它独立子命令仍可执行。子命令的必要条件 不能简单合并成父命令的全局门槛,否则缺少一种证据能力就会阻断整个概览或采集。
Input 可以提供 idempotencyKey(): string,显式声明本次逻辑执行的身份。defineCommand 在输入校验后,
按 Command 定义身份和 key 在当前 CommandContext 中合并调用:正在执行时等待同一个 Promise,包括资源
清理;已完成时返回原状态、Output、Artifacts 和 reportName,不产生 skipped 状态。未提供方法时每次独立
执行。完成结果包括 partial 和 failed,本轮不隐式重试;取消始终优先于复用。key 必须包含会改变结果的
领域参数,Profile、Plugin 和宿主配置由当前 Context 隔离,记录不跨 Doctor 运行保留。
Inspect 和 Tenant 的 Input 构造函数按检查范围、租户及采集参数生成 key,Collect 使用这些 Input 调用 子命令。调用方仍显式纳入子产物,Artifacts 按路径去重,因此多个 Collect 可引用同一份环境/租户证据, 最终报告只交付一份。Overview 无需识别第一次或后续 Collect。
CommandContext 属于整轮执行树,保存 Profile、当前 Plugin、按需准备并复用的环境信息、权限检查、
Decision、Discovery、ExecutionRecord 与取消信号。领域 Context 保存单次执行准备的 Target、client、
Bundle 和领域状态;PluginContext 只暴露本次 Service 调用所需的受限依赖与 infra。
同一 CommandContext 可以被并发子命令共享。Artifacts 使用异步调用作用域,每次调用返回自己的产物 引用和报告名称,父命令显式选择并纳入子产物;不能按全局列表位置或命令名猜测产物属于哪次调用。 领域输入与输出通过 Input / Output 传递,不放入共享 Context。
Host 创建的 PluginContext 继承当前调用的取消信号,并登记到本次调用的资源作用域。显式 dispose 和执行层兜底清理共用一次回收;子调用只关闭自己的资源,不关闭父调用的资源。用户取消会传播到整轮 执行树,停止后续工作,并保留已生成证据。
CommandStatus 统一定义 ok / partial / failed / cancelled 四种最终执行状态。它描述命令完成度;
业务错误、Finding severity 和 Evidence Coverage 各自保留领域含义。父命令依据自己的目标汇总子结果:
部分采集失败但仍形成有效结果时为 partial;用户只看 Overview 并拒绝可选采集属于正常完成。
根 CLI 将结果映射为退出码:ok 和 partial 为 0,failed 为非零,cancelled 为 130。子命令不设置 进程退出码,也不调用根入口的最终交付。
Finalize 只执行一次,消费根结果纳入的 Artifacts,统一处理路径、格式、Bundle、Delivery 和临时产物 清理。报告名称由相应调用拥有,最外层决定最终交付名称。交付失败时保留源产物以便恢复。
默认格式、partial 报告、Evidence Bundle、失败兜底和退出码语义由
collect-protocol.md 统一定义。init/profile 等启动命令不要求已有 Profile。
Core 与 Plugin 使用同一套 Inspect、Probe、Detector 词汇。Service 是业务 contribution、Workload 和运行时 依赖的归属单元;Plugin 是多个 Service 与 Skill 的版本化分发单元。具体 Plugin 只依赖公共 Plugin SDK, CLI Core 不依赖任何具体 Plugin 实现。
这里统一的是概念、执行阶段和 Evidence 语义,不要求 Core 与 Plugin 直接复用同一个代码 interface。
Core 实现可以直接消费进程内领域上下文;Plugin contribution 还必须携带 Service、版本、access 与分发
边界所需的信息。CLI composition root 负责把选中的 Plugin contribution 适配进同一 Execute 流程,不能
为了统一函数签名丢掉边界信息,也不让 packages/plugin 反向依赖 CLI Core。
双方边界分为两层:
| 边界 | 方向 | 所有权 |
|---|---|---|
| Inspect / Probe / Detector contribution | Plugin Service → Core | Plugin 提供业务逻辑;Core 选择、驱动并验证结果 |
| access | Plugin capability → Core | Plugin 声明最小需求;Core 合并、检查并授权 |
| dependencies | Service → Core | Service 声明所需其它 Service capability;Core 解析并注入受限 handle |
| data | Core ↔ Plugin capability | 公共包定义类型化输入输出;私有 schema 留在 Plugin 内 |
| infra | Core → PluginContext | Core 提供当前 Target 的受限访问、取消和资源生命周期 |
| config | Profile/Core → PluginContext | Core 不透明保存和透传;schema、校验和解释归 Plugin |
这些边界不能互相替代:取得 infra handle 不代表获得任意权限;config 不承载 kubeconfig 等 Core-owned 连接状态;业务返回值不能泄露整包私有配置;Plugin contribution 不能推进或绕过 Core 生命周期。
Kubernetes 只是 Doctor Host 到 Target 的一种访问通道。Core 解析 kubeconfig/context,托管查询、超时、 输出上限、取消和 port-forward 回收;Plugin 通过 Workload discovery 描述业务部署拓扑,通过 capability 持有专有 API 与业务语义。Plugin 不持有 kubeconfig,也不自行启动 kubectl。
Collect 的命令终止、证据覆盖度、Target 健康和产物交付是不同维度:
- Finding severity 描述 Target 健康,不决定命令是否成功。
- Coverage 描述证据是否充分;partial 可以是正常完成状态。
- 单项 Probe 现场失败只降低对应 Coverage;Doctor 自身不变量错误不能伪装成 partial。
- Delivery 失败会改变最终命令结果,但不能抹掉已经取得的 Evidence。
Collect 以可审计 Evidence 为结果,即使某个 Probe 需要受控副作用,也不能隐藏式发布 image、创建 debug
environment 或安装工具。Operation 明确描述风险、目标、影响和步骤;授权只覆盖当前动作,不是 blanket
approval。完整的调度、Coverage、Worksheet、授权、报告和退出码契约见
collect-protocol.md。
| 主路径 | 与 Collect 的稳定边界 |
|---|---|
| Provision | 以外部状态变化或能力准备为结果,不使用 Collect engine;只共享 CommandContext、终端和 infra |
| Eval | 顺序触发 canonical Case,并调用已有 Trace/Log/Data Collect 入口取得关联证据;不复制采集器,也不评价回答质量 |
| Perf | 负责并发、预算、熔断与性能窗口,并调用已有 Metric/Trace/Log Collect 入口;Plugin Case runner 每次只执行一个请求 |
| Chat | 使用共享 Agent runtime 处理开放式问题;不依赖 Collect 的确定性流程 |
Model discovery、Case、Trace、Store 等能力可以被多个主路径复用,但复用的是稳定 capability 或 Command
入口,不是复制内部编排。具体边界分别见 plugin.md、commands/eval.md、
commands/perf.md 与 ../docs/chat.md。
cli/src/
├── app/ Prepare / Execute / Finalize composition root
├── command/ CommandContext、Target、access 与审批契约
├── collect/
│ ├── protocol.ts Fact、Observation、Finding、Coverage 共享协议
│ ├── evidence-identity.ts Fact/Observation/Finding schema identity 运行时校验
│ ├── engine.ts runCollect:Inspect → Probe → Evidence → Detector / Coverage
│ ├── inspect-engine.ts Inspect 依赖调度与 Facts 冻结
│ ├── probe-engine.ts Probe 依赖、安全顺序与失败隔离
│ ├── detector-engine.ts Core/Plugin Detector 执行与 Finding 契约校验
│ ├── evidence.ts Worksheet 与 Evidence Bundle
│ ├── operation.ts 副作用授权与审计
│ ├── output/ 通用格式与交付原语
│ └── <domain>/ 领域 Config、Inspect、Probe、Detector、Renderer
├── provision/ image、debug environment 与工具准备
├── eval/ Case 顺序执行与关联证据编排
├── perf/ 受控负载与跨数据面证据编排
├── chat/ Session / Controller 与 AgentUE adapter
├── plugin/ Plugin 宿主选择、加载与公共协议适配
├── model/ Model Collect 与 Chat 共用的模型访问
├── terminal/ 选择、确认与输出边界
└── infra/ Host、Target、Kubernetes 与外部资源 adapter
packages/plugin/ Plugin、Service、capability 与 Inspect/Probe/Detector contribution 公共协议
packages/agent/ CLI/server 共用的 Agent runtime
plugins/<plugin>/ 具体 Service 实现、固定查询与 Skills
toolkit/ 独立版本的诊断工具和平台资源
依赖方向保持:
cli/collect → packages/plugin ← plugins/<plugin>
app → command / collect / provision / eval / perf / chat / infra
collect/<domain> → collect shared protocol + infra ports
公共协议和调度只有出现跨领域稳定、同语义的重复时才上提;领域数据语义、固定查询、Renderer 和具体
Failure/Coverage 解释继续留在 collect/<domain>。packages/plugin 不依赖 CLI,具体 Plugin 不反向依赖
CLI 实现。
collect-protocol.md:Collect 调度、partial、Coverage、授权、交付与退出码。plugin.md:Plugin capability、Context、分发和信任边界。commands/collect.md:集合命令如何组合多个 Collect 入口。commands/tenant.md与commands/data-diagnosis.md:Application 数据的 Query 作用域。commands/eval.md与commands/perf.md:Case 执行和主动负载。../../toolkit/README.md:Toolkit 的独立版本与平台资源模型。commands/:各领域 Command 的理念、流程和关键设计。
新增 Collect Command 时,先定义 Facts、Observations、Evidence、Findings/Coverage 和纯 Detector,再实现 Inspect、Probe 与 Renderer;契约测试至少覆盖依赖调度、能力降级、授权拒绝、敏感信息边界和交付结果。