refactor: expect 类型模型重构,Raw/Resolved 双层分离与断言基础设施内聚
- 重命名 ContentRules→ContentExpectations, KeyValueExpect→KeyedExpectations - 新增 Raw/Resolved 双层模型:resolve 阶段物化为执行计划,store 持久化 Raw 快照 - HTTP body 按需读取:status/headers 失败或无 body expectation 时不读取 body - 新增 displayValueExpectation() 解包 failure.expected 用户可读展示 - 修复 checkEarlyTimeout 独立 lte/lt 检查,修复 KeyedExpectations JSON Schema - 新增 expect/value.ts(resolve/check/display)、keyed.ts、content.ts、headers.ts、status.ts - 删除旧 normalize.ts/matcher.ts/validate-matcher.ts/key-value.ts - 更新 DEVELOPMENT.md:expect 五层管线表、displayValueExpectation、1.7↔1.10 交叉引用 - 同步 13 个 main specs,归档 refactor-expect-type-model 变更(62/62 tasks)
This commit is contained in:
@@ -146,38 +146,57 @@
|
||||
- **THEN** HttpChecker 的语义校验 SHALL 抛出校验错误,提示 URL 格式不合法
|
||||
|
||||
### Requirement: 存储序列化通过 registry 获取展示格式
|
||||
系统 SHALL 在 `ProbeStore.syncTargets()` 中通过 `checkerRegistry.get(t.type).serialize(t)` 获取每个 target 的展示摘要(`target` 列)和配置 JSON(`config` 列),替代 `buildTargetDisplay()` / `buildTargetConfig()` 中的类型分支。
|
||||
系统 SHALL 在 `ProbeStore.syncTargets()` 中通过 `checkerRegistry.get(t.type).serialize(t)` 获取每个 target 的展示摘要(`target` 列)和配置 JSON(`config` 列),替代 `buildTargetDisplay()` / `buildTargetConfig()` 中的类型分支。系统 SHALL 将 `targets.expect` 持久化为 resolved target 上的 Raw expect 快照,而不是运行期 Resolved expect 执行计划。
|
||||
|
||||
#### Scenario: 序列化委托 checker
|
||||
- **WHEN** store 同步 targets 表
|
||||
- **THEN** store SHALL 对每个 target 调用对应 checker 的 `serialize()` 方法获取 `{ target, config }`
|
||||
|
||||
#### Scenario: expect 持久化使用 rawExpect
|
||||
- **WHEN** store 同步带 expect 的 target 到 targets 表
|
||||
- **THEN** store SHALL 将 `rawExpect` 序列化写入 `targets.expect`,MUST NOT 将包含 `kind` 的 Resolved content expectation 写入该列
|
||||
|
||||
### Requirement: Checker resolve 生成 Raw 与 Resolved expect
|
||||
每个 checker 的 `resolve()` SHALL 在解析 checker 专属 target 配置时,同时保留变量替换后的 Raw expect 快照并生成运行期 Resolved expect 执行计划。Raw expect SHALL 用于配置快照持久化;Resolved expect SHALL 用于 checker `execute()`。`config-loader` SHALL 继续通过 registry 委托 checker resolve,MUST NOT 在中间层理解 checker 专属 expect 字段。
|
||||
|
||||
#### Scenario: resolve 输出双 expect 模型
|
||||
- **WHEN** config-loader 解析一个带 `expect.durationMs: 1000` 的 target
|
||||
- **THEN** 对应 checker 的 resolved target SHALL 包含 Raw expect 中的 `durationMs: 1000`,并在 Resolved expect 中包含 `{equals: 1000}` 形式的运行期 matcher
|
||||
|
||||
#### Scenario: 中间层不感知 checker expect 字段
|
||||
- **WHEN** 新增 checker 定义自己的 Raw/Resolved expect 字段
|
||||
- **THEN** config-loader SHALL 只调用该 checker 的 `validate()` 和 `resolve()`,不新增 checker 类型分支
|
||||
|
||||
### Requirement: 共享 expect 断言函数
|
||||
系统 SHALL 在 `src/server/checker/expect/` 中提供可被多个 checker 复用的 expect 基础设施。共享基础设施 SHALL 包含 matcher、content rules、key-value expect、failure 构造和 ReDoS 校验。checker 专用的状态类断言 SHALL 保留在对应 checker 目录,或在多个 checker 复用时移动到共享模块。仅被单个 checker 使用且不属于通用 matcher/content/key-value 模型的断言模块 SHALL 位于该 checker 目录内。
|
||||
系统 SHALL 在 `src/server/checker/expect/` 中提供可被多个 checker 复用的 expect 基础设施。共享基础设施 SHALL 包含 value expectation、content expectations、keyed expectations、status code 断言、headers keyed 断言、failure 构造和 ReDoS 校验。checker 专用的状态类断言 SHALL 保留在对应 checker 目录,或在多个 checker 复用时移动到共享模块。仅被单个 checker 使用且不属于通用 value/content/keyed/status/header 模型的断言模块 SHALL 位于该 checker 目录内。
|
||||
|
||||
#### Scenario: 共享 ValueMatcher 断言
|
||||
#### Scenario: 共享 ValueExpectation 断言
|
||||
- **WHEN** 任何 checker 需要对数字、字符串、布尔或 JSON value 执行 matcher 匹配
|
||||
- **THEN** SHALL 调用共享 matcher 工具执行 `equals`、`contains`、`regex`、`exists`、`empty`、`gt`、`gte`、`lt` 和 `lte` 语义
|
||||
- **THEN** SHALL 调用共享 value expectation 工具执行 `equals`、`contains`、`regex`、`exists`、`empty`、`gt`、`gte`、`lt` 和 `lte` 语义
|
||||
|
||||
#### Scenario: 共享 ContentRules 断言
|
||||
#### Scenario: 共享 ContentExpectations 断言
|
||||
- **WHEN** HTTP body、LLM output、Cmd stdout/stderr、UDP response 或 TCP banner 需要执行返回内容校验
|
||||
- **THEN** SHALL 调用共享 content rules 工具,而不是在 checker 目录内复制 contains/regex/json/css/xpath 逻辑
|
||||
- **THEN** SHALL 调用共享 content expectations 工具,而不是在 checker 目录内复制 contains/regex/json/css/xpath 逻辑
|
||||
|
||||
#### Scenario: 共享 KeyValueExpect 断言
|
||||
#### Scenario: 共享 KeyedExpectations 断言
|
||||
- **WHEN** HTTP 或 LLM checker 需要校验响应 headers,或 DB checker 需要校验 rows 中的列值
|
||||
- **THEN** SHALL 调用共享 key-value expect 工具,并按调用方规则决定 key 是否大小写敏感
|
||||
- **THEN** SHALL 调用共享 keyed expectations 工具,并按调用方规则决定 key 是否大小写敏感
|
||||
|
||||
#### Scenario: 共享 headers 断言
|
||||
- **WHEN** HTTP 或 LLM checker 需要校验响应 headers
|
||||
- **THEN** SHALL 调用共享 header expectation 包装函数,确保 header key 大小写不敏感
|
||||
|
||||
#### Scenario: 共享 regex ReDoS 校验
|
||||
- **WHEN** 任一 matcher 或 content rule 配置 `regex`
|
||||
- **WHEN** 任一 matcher 或 content expectation 配置 `regex`
|
||||
- **THEN** SHALL 调用共享 ReDoS 校验工具在启动期拒绝危险正则
|
||||
|
||||
#### Scenario: 共享 failure 构造
|
||||
- **WHEN** 任何 checker 需要构造 CheckFailure 对象
|
||||
- **THEN** SHALL 调用 `expect/failure.ts` 中的 `errorFailure()` 或 `mismatchFailure()`,并保留 actual 截断策略
|
||||
|
||||
#### Scenario: HTTP 专用 status 断言
|
||||
#### Scenario: 共享 status 断言
|
||||
- **WHEN** HTTP 或 LLM checker 需要校验响应状态码
|
||||
- **THEN** SHALL 复用同一 status 断言函数,支持精确状态码和 `1xx` 到 `5xx` 范围模式
|
||||
- **THEN** SHALL 复用共享 status code 断言函数,支持精确状态码和 `1xx` 到 `5xx` 范围模式
|
||||
|
||||
### Requirement: 超时控制由引擎注入 signal
|
||||
Checker 实现的 `execute()` MUST 使用 `ctx.signal` 感知超时,不得自行创建 `AbortController` 或 `setTimeout` 用于超时控制。Cmd checker 和 ping checker 可在 signal abort 时 `proc.kill()` 以确保子进程被终止。
|
||||
|
||||
Reference in New Issue
Block a user