- 合并 20+ 细粒度 spec 为粗粒度主题规范:dashboard、data-store、probe-engine、probe-api、probe-config 等 - 删除完全冗余规范:data-retention(被 probe-engine+data-store 覆盖)、backend-code-quality(DEVELOPMENT.md 已记录) - 补充 http-checker 规范至完整标准(配置+执行+expect+校验+observation),匹配代码 440 行实现 - 清理 tcp/udp/llm checker 规范中已废弃 defaults 配置段的残留 Scenario - 清理 checker-cohesion-structure 中的实现路径引用(src/server/...) - 统一所有 spec 格式(## Purpose 开头,去除 # Capability/Title 形式) - 更新 prompt-spec-review.md 审查提示文档
8.7 KiB
Purpose
定义 CheckResult 的 observation 数据模型、各 checker 类型 observation 结构、截断策略、序列化规则和 detail 动态构造机制。
Requirements
Requirement: Observation 数据模型
CheckResult SHALL 包含 observation: Record<string, unknown> | null 字段,用于承载 checker 执行过程中收集的结构化观测数据。observation 为 null 表示执行过程中无法形成有意义的领域观测数据(如进程 spawn 失败、内部异常、请求在拿到响应前失败且无可记录元数据等场景)。各 checker SHALL 自行定义 observation 的内部结构,不做跨 checker 类型的统一约束。
Scenario: 正常执行返回 observation
- WHEN checker 执行成功、expect 断言失败或产生可收集上下文的负向结果
- THEN CheckResult.observation SHALL 包含该 checker 类型定义的完整观测数据
Scenario: 异常执行返回 null observation
- WHEN checker 执行过程中发生无法收集领域观测数据的异常
- THEN CheckResult.observation SHALL 为 null
Requirement: HTTP Checker Observation
HTTP checker 的 observation SHALL 包含 statusCode(number)、headers(Record<string, string>,截断)、bodyPreview(string | null,截断)、contentType(string | null)、contentLength(number | null)。
Scenario: 正常 HTTP 响应
- WHEN HTTP 请求成功返回
- THEN observation SHALL 包含响应状态码、截断后的响应 headers、响应体预览、Content-Type 和 Content-Length,即使未配置 body expect 也 SHALL 采集 bodyPreview
Scenario: HTTP 请求失败
- WHEN HTTP 请求因网络错误或超时失败
- THEN observation SHALL 为 null
Requirement: TCP Checker Observation
TCP checker 的 observation SHALL 包含 connected(boolean)、connectTimeMs(number | null)、banner(string | null,截断)、error(string | null)。
Scenario: TCP 连接成功且读取 banner
- WHEN TCP 连接成功并读取到 banner
- THEN observation SHALL 包含 connected=true、连接耗时、截断后的 banner 内容
Scenario: TCP 连接失败
- WHEN TCP 连接失败
- THEN observation SHALL 包含 connected=false 和错误信息
Requirement: UDP Checker Observation
UDP checker 的 observation SHALL 包含 responded(boolean)、durationMs(number)、responseSize(number | null)、responsePreview(string | null,截断)、sourceAddress(string | null)、sourcePort(number | null)、error(string | null)。durationMs 用于 API 序列化层生成包含耗时的 UDP detail 摘要。
Scenario: UDP 收到响应
- WHEN UDP 发送数据后收到响应
- THEN observation SHALL 包含 responded=true、响应大小、截断后的响应预览、来源地址和端口
Scenario: UDP 未收到响应
- WHEN UDP 发送数据后超时未收到响应
- THEN observation SHALL 包含 responded=false
Requirement: ICMP Checker Observation
ICMP checker 的 observation SHALL 包含 alive(boolean)、transmitted(number)、received(number)、packetLoss(number)、avgLatencyMs(number | null)、maxLatencyMs(number | null)、minLatencyMs(number | null)、error(string | null)。
Scenario: ICMP 正常返回统计
- WHEN ping 命令成功执行并解析出统计数据
- THEN observation SHALL 包含完整的 ICMPStats 字段
Scenario: ICMP 命令失败
- WHEN ping 命令未找到或超时
- THEN observation SHALL 为 null 或包含 error 字段
Requirement: DB Checker Observation
DB checker 的 observation SHALL 包含 connected(boolean)、rowCount(number | null)、rowsPreview(unknown[] | null,截断前 N 行)、error(string | null)。
Scenario: 数据库查询成功
- WHEN 数据库连接和查询成功
- THEN observation SHALL 包含 connected=true、行数、截断后的行预览
Scenario: 仅探活无查询
- WHEN 数据库配置仅探活连接(无 query)
- THEN observation SHALL 包含 connected=true,rowCount 和 rowsPreview 为 null
Requirement: CMD Checker Observation
CMD checker 的 observation SHALL 包含 exitCode(number | null)、stdoutPreview(string | null,截断)、stderrPreview(string | null,截断)、error(string | null)。
Scenario: 命令正常执行
- WHEN 命令执行完成
- THEN observation SHALL 包含退出码、截断后的 stdout 和 stderr 预览
Scenario: 命令 spawn 失败
- WHEN 命令进程无法启动
- THEN observation SHALL 为 null
Requirement: LLM Checker Observation
LLM checker SHALL 保留执行期 LlmCheckObservation.outputText 完整文本用于 expect 校验,并从执行期 observation 派生持久化 observation。持久化 observation SHALL 包含 provider(string)、mode(string)、model(string)、http({ status, statusText, headers } | null,headers 截断)、finishReason(string | null)、rawFinishReason(string | null)、outputPreview(string | null,截断)、outputLength(number | null)、usage({ inputTokens, outputTokens, totalTokens } | null)、stream({ completed, firstTokenMs } | null)、warnings(string[])。
Scenario: LLM HTTP 模式成功
- WHEN LLM 以 HTTP 模式成功执行
- THEN observation SHALL 包含 provider、mode、model、HTTP 元数据、finish 原因、截断后的输出预览、完整输出长度和 token 用量
Scenario: LLM Stream 模式成功
- WHEN LLM 以 stream 模式成功执行
- THEN observation SHALL 额外包含 stream 观测数据(completed、firstTokenMs)
Requirement: Observation 截断策略
各 checker SHALL 对 observation 中的大文本和集合字段执行截断,防止存储膨胀。
Scenario: HTTP body 截断
- WHEN HTTP 响应体超过 1024 字符
- THEN bodyPreview SHALL 截断为前 1024 字符
Scenario: HTTP headers 截断
- WHEN HTTP 响应 headers 超过 20 个
- THEN headers SHALL 仅保留前 20 个
Scenario: TCP banner 截断
- WHEN TCP banner 内容超过 256 字符
- THEN banner SHALL 截断为前 256 字符
Scenario: UDP response 截断
- WHEN UDP 响应预览超过 512 字符
- THEN responsePreview SHALL 截断为前 512 字符
Scenario: DB rows 截断
- WHEN 查询返回超过 5 行
- THEN rowsPreview SHALL 仅保留前 5 行
Scenario: CMD stdout/stderr 截断
- WHEN stdout 或 stderr 超过 1024 字符
- THEN 对应 Preview 字段 SHALL 截断为前 1024 字符
Scenario: LLM output 截断
- WHEN LLM 输出文本超过 512 字符
- THEN outputPreview SHALL 截断为前 512 字符
Scenario: LLM headers 截断
- WHEN LLM 响应 headers 超过 20 个
- THEN headers SHALL 仅保留前 20 个
Requirement: Observation 序列化规则
observation SHALL 使用 JSON.stringify 序列化为 TEXT 格式存入 SQLite,使用 JSON.parse 反序列化读出。不引入额外的序列化依赖。
Scenario: 写入 observation
- WHEN 存储 CheckResult 到数据库
- THEN observation 字段 SHALL 使用 JSON.stringify 序列化后存入 TEXT 列;observation 为 null 时 SHALL 存入 SQL NULL
Scenario: 读取 observation
- WHEN 从数据库读取 CheckResult
- THEN observation 字段 SHALL 使用 JSON.parse 反序列化;SQL NULL 值 SHALL 映射为 null
Scenario: 使用 SQLite CLI 直接查看
- WHEN 开发者使用 sqlite3 CLI 工具查看 check_results 表
- THEN observation 列 SHALL 为人可读的 JSON 文本
Requirement: Detail 动态构造
CheckResult SHALL 包含 detail: string | null 字段(替代原 statusDetail),该字段 SHALL 不持久化到数据库,而是在 API 序列化层根据 target type 从 observation 动态构造。每个 checker SHALL 提供 buildDetail(observation) 方法,定义该 checker 类型的人可读摘要格式。
Scenario: API 返回 detail 字段
- WHEN API 序列化 CheckResult 返回给前端
- THEN 系统 SHALL 根据 target type 调用对应 checker 的 buildDetail 方法,从 observation 动态生成 detail 字段
Scenario: observation 为 null 时
- WHEN observation 为 null
- THEN detail SHALL 为 null
Scenario: 各 checker 的 detail 格式
- WHEN 各 checker 的 buildDetail 被调用
- THEN HTTP SHALL 返回
"HTTP {statusCode}"格式;TCP SHALL 返回连接状态和 banner 摘要;UDP SHALL 返回响应状态和大小摘要;Ping SHALL 返回存活状态、平均延迟和丢包率摘要;ICMP SHALL 返回存活状态、平均延迟和丢包率摘要;DB SHALL 返回连接状态或行数摘要;CMD SHALL 返回"exitCode={N}"格式;LLM SHALL 返回 provider、mode、状态码、finish 原因、输出长度和 token 用量摘要