1
0
Files
DiAL/openspec/specs/cmd-checker/spec.md
lanyuanxiaoyao 7a635a0a9f refactor: 统一 expect 断言体系,引入共享 ValueMatcher/ContentRules/KeyValueExpect 模型
- 引入共享 ValueMatcher(equals/contains/regex/exists/empty/gt/gte/lt/lte)
- 引入共享 ContentRules 数组(direct/json/css/xpath 提取器)
- 引入共享 KeyValueExpect(动态键值断言,字面量等价 equals)
- maxDurationMs → durationMs: ValueMatcher(所有 checker)
- match → regex(固定无 flags)
- Ping max* → packetLossPercent/avgLatencyMs/maxLatencyMs(ValueMatcher)
- LLM finishReason/rawFinishReason → ValueMatcher
- DB 新增 result: ContentRules
- TCP banner → ContentRules 数组
- 删除旧模块:operator.ts、validate-operator.ts、duration.ts、body.ts、text.ts、output.ts
- 更新全部 checker schema/validate/expect/execute
- 更新 probe-config.schema.json、probes.example.yaml
- 更新 README.md、DEVELOPMENT.md(含 expect 字段选择规范)
- 同步 10 个 delta specs 到主 specs,归档 change
2026-05-19 14:24:27 +08:00

7.8 KiB
Raw Blame History

Purpose

定义 Cmd 类型拨测目标:通过 type: cmd 配置执行本地命令(如进程检查、脚本健康检测),捕获 exit code、stdout、stderr按 expect 规则校验并生成 matched 判定。

Requirements

Requirement: cmd target 配置

系统 SHALL 支持 type: cmd 的 target 配置,通过 cmd.execcmd.args 描述本地命令,并使用 cmd 专用字段配置工作目录、环境变量和输出限制。

Scenario: 解析 cmd target

  • WHEN YAML 中 target 配置 type: cmdcmd.exec: "pgrep"cmd.args: ["nginx"]
  • THEN 系统 SHALL 将其解析为 cmd checker并保留 exec、args、cwd、env、maxOutputBytes、interval、timeout 和 expect 配置

Scenario: cmd target 缺少 exec

  • WHEN YAML 中 target 配置 type: cmd 但缺少 cmd.exec
  • THEN 系统 SHALL 以配置错误退出,并提示该 target 缺少 cmd.exec 字段

Scenario: cwd 相对配置文件目录解析

  • WHEN cmd target 配置 cmd.cwd: "scripts" 且配置文件位于 /opt/checker/probes.yaml
  • THEN 系统 SHALL 将 cwd 解析为 /opt/checker/scripts

Scenario: cmd 不使用 shell

  • WHEN cmd target 配置 execargs
  • THEN 系统 MUST 直接执行该程序和参数,不通过 shell 解释整段命令字符串

Scenario: env 默认继承并允许覆盖

  • WHEN cmd target 配置 cmd.env: {LANG: "C"} 且当前进程环境包含 PATH
  • THEN 系统 SHALL 继承当前进程的全部环境变量,并将 LANG 覆盖为 "C"

Scenario: 不支持 stdin

  • WHEN cmd target 配置并执行命令
  • THEN 系统 MUST NOT 向子进程 stdin 写入数据,避免命令因等待输入而阻塞

Requirement: cmd checker 执行

系统 SHALL 按 cmd target 配置执行本地命令记录执行耗时、退出码、stdout 和 stderr并在执行失败时产生结构化错误信息。

Scenario: 命令正常退出

  • WHEN cmd target 执行的进程正常退出且 exit code 为 0
  • THEN 系统 SHALL 记录 durationMsstatusDetail="exitCode=0",并进入 expect 校验

Scenario: 命令非零退出

  • WHEN cmd target 执行的进程正常退出但 exit code 为 1
  • THEN 系统 SHALL 记录 statusDetail="exitCode=1",并由 expect.exitCode 决定 matched 结果

Scenario: 命令启动失败

  • WHEN cmd target 的 exec 不存在或无法启动
  • THEN 系统 SHALL 记录 matched=false,并在 failure 中写入 kind=error 和可读错误信息

Scenario: 命令超时

  • WHEN cmd target 在 timeout 时间内未结束
  • THEN 系统 MUST 终止该子进程,记录 matched=false,并在 failure 中写入命令超时信息

Scenario: 命令输出超限

  • WHEN cmd target 的 stdout 和 stderr 合计输出超过 maxOutputBytes
  • THEN 系统 MUST 停止收集输出并终止该检查,记录 matched=false,并在 failure 中写入输出超限信息

Requirement: cmd expect 校验

系统 SHALL 支持 cmd 专用 expect包括 exitCodedurationMsstdoutstderr,并按 exitCode、durationMs、stdout、stderr 的阶段顺序快速失败。exitCode SHALL 保持有限整数数组语义,未配置时默认 [0]durationMs SHALL 使用共享 ValueMatcher 校验完整命令执行耗时。stdoutstderr MUST 使用共享 ContentRules 数组,直接 matcher 作用于对应输出文本,json extractor SHALL 支持对 JSON CLI 输出执行 JSONPath 断言。

Scenario: 默认 exitCode 成功语义

  • WHEN cmd target 未显式配置 expect.exitCode
  • THEN 系统 SHALL 使用默认 expect.exitCode: [0] 进行校验

Scenario: 显式 exitCode 校验

  • WHEN cmd target 配置 expect.exitCode: [0, 2] 且实际 exit code 为 2
  • THEN 系统 SHALL 判定 exitCode 阶段通过,并继续后续 expect 阶段

Scenario: exitCode 不匹配快速失败

  • WHEN cmd target 配置 expect.exitCode: [0] 且实际 exit code 为 1
  • THEN 系统 SHALL 立即返回 matched=false,并在 failure 中写入 phase=exitCode、path=exitCode、expected 和 actual

Scenario: durationMs 校验

  • WHEN cmd target 配置 expect.durationMs: {lte: 1000} 且实际执行耗时为 1500ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 phase 为 duration

Scenario: stdout 按配置顺序校验

  • WHEN cmd target 配置 expect.stdout 为两个 ContentRules第一条通过且第二条失败
  • THEN 系统 SHALL 先执行第一条 stdout 规则,再执行第二条,并将 failure.path 指向失败的 stdout[1]

Scenario: stderr 校验为空

  • WHEN cmd target 配置 expect.stderr: [{empty: true}] 且实际 stderr 为空字符串
  • THEN 系统 SHALL 判定 stderr 阶段通过

Scenario: stdout JSON 输出校验

  • WHEN cmd target 输出 stdout 为 {"status":"ok"} 且配置 expect.stdout: [{json: {path: "$.status", equals: "ok"}}]
  • THEN 系统 SHALL 判定 stdout 阶段通过

Scenario: stdout 失败后不检查 stderr

  • WHEN cmd target 同时配置 stdout 和 stderr 规则,且 stdout 规则失败
  • THEN 系统 SHALL 快速失败并 MUST NOT 继续执行 stderr 规则

Requirement: cmd checker 启动期配置校验

系统 SHALL 在启动期对 cmd checker 的配置契约和语义执行严格校验。Cmd target 的 cmd 分组 SHALL 只允许 execargscwdenvmaxOutputBytes 字段。Cmd expect SHALL 只允许 exitCodedurationMsstdoutstderr 字段。未知字段、非法类型、不可编译正则和 ReDoS 风险正则 MUST 导致启动期配置错误。expect.exitCode SHALL 保留原有有限整数数组语义,不限制到特定平台范围。

Scenario: cmd args 类型非法

  • WHEN YAML 中 cmd target 配置 cmd.args 不是字符串数组
  • THEN 系统 SHALL 以配置错误退出,提示 cmd.args 格式错误

Scenario: cmd env 值类型非法

  • WHEN YAML 中 cmd target 配置 cmd.env,且任一环境变量值不是字符串
  • THEN 系统 SHALL 以配置错误退出,提示 cmd.env 对应变量值必须为字符串

Scenario: cmd expect exitCode 类型非法

  • WHEN YAML 中 cmd target 配置 expect.exitCode 不是整数数组
  • THEN 系统 SHALL 以配置错误退出,提示 expect.exitCode 必须为整数数组

Scenario: cmd expect durationMs 非法

  • WHEN YAML 中 cmd target 配置 expect.durationMs 不是合法 ValueMatcher
  • THEN 系统 SHALL 以配置错误退出,提示 expect.durationMs 格式错误

Scenario: stdout 必须为 ContentRules 数组

  • WHEN YAML 中 cmd target 配置 expect.stdout 但其值不是数组
  • THEN 系统 SHALL 以配置错误退出,提示 expect.stdout 必须为数组

Scenario: stderr 必须为 ContentRules 数组

  • WHEN YAML 中 cmd target 配置 expect.stderr 但其值不是数组
  • THEN 系统 SHALL 以配置错误退出,提示 expect.stderr 必须为数组

Scenario: stdout text rule 空对象非法

  • WHEN YAML 中 cmd target 配置 expect.stdout: [{}]
  • THEN 系统 SHALL 以配置错误退出,提示 stdout 规则必须包含至少一个合法 matcher 或 extractor

Scenario: stderr text rule 未知字段非法

  • WHEN YAML 中 cmd target 配置 expect.stderr: [{foo: "bar"}]
  • THEN 系统 SHALL 以配置错误退出,提示 stderr 规则包含未知 matcher 或未知 extractor

Scenario: stdout regex 正则非法

  • WHEN YAML 中 cmd target 配置 expect.stdout: [{regex: "[invalid"}]
  • THEN 系统 SHALL 在启动期配置校验失败,而不是延迟到运行期抛错

Scenario: cmd expect 未知字段失败

  • WHEN YAML 中 cmd target 的 expect 包含 status: [200]maxDurationMs: 1000 或其他非 cmd expect 字段
  • THEN 系统 SHALL 以配置错误退出,提示 expect 包含未知字段