- 移除 DefaultsConfig 类型、ProbeConfig.defaults 字段 - 移除 CheckerSchemas.defaults、ResolveContext.defaults、CheckerValidationInput.defaults - 更新所有 checker schema/resolve/validate 删除 defaults 合并逻辑 - 更新 config-loader 不再读取传递 defaults - 更新测试、README、DEVELOPMENT、probes.example.yaml - 重新生成 probe-config.schema.json(不含 defaults) - 同步 delta specs 到主规范 - 归档 openspec change
154 lines
8.5 KiB
Markdown
154 lines
8.5 KiB
Markdown
## Purpose
|
||
|
||
定义 checker 模块的内聚化组织结构,确保每个 checker 以独立目录形式存在,包含其全部类型定义、schema 声明、语义校验、执行逻辑和断言逻辑。同时定义共享的 expect/ 和 schema/ 基础设施,以及严格的依赖方向约束。
|
||
|
||
## Requirements
|
||
|
||
### Requirement: Checker 目录内聚结构
|
||
每个 checker SHALL 以独立目录形式存在于 `src/server/checker/runner/<type>/`,目录内 SHALL 包含该 checker 的全部类型定义、schema 声明、语义校验、执行逻辑和断言逻辑。
|
||
|
||
#### Scenario: HTTP checker 目录完整性
|
||
- **WHEN** 开发者查看 `src/server/checker/runner/http/` 目录
|
||
- **THEN** 该目录 SHALL 包含 `index.ts`、`types.ts`、`schema.ts`、`execute.ts`、`expect.ts`、`body.ts`、`validate.ts`
|
||
|
||
#### Scenario: Cmd checker 目录完整性
|
||
- **WHEN** 开发者查看 `src/server/checker/runner/cmd/` 目录
|
||
- **THEN** 该目录 SHALL 包含 `index.ts`、`types.ts`、`schema.ts`、`execute.ts`、`expect.ts`、`text.ts`、`validate.ts`
|
||
|
||
#### Scenario: 新增 checker 最小改动
|
||
- **WHEN** 开发者新增一个 checker 类型(如 dns)
|
||
- **THEN** 开发者 SHALL 只需创建 `src/server/checker/runner/dns/` 目录及其内部文件,并在 `runner/index.ts` 注册列表中添加一行 import 和一行数组项
|
||
|
||
### Requirement: Checker 目录文件职责
|
||
每个 checker 目录内的文件 SHALL 遵循统一的职责划分。
|
||
|
||
#### Scenario: index.ts 仅做 re-export
|
||
- **WHEN** 开发者查看某 checker 的 `index.ts`
|
||
- **THEN** 该文件 SHALL 仅包含对 `execute.ts` 中 Checker 类的 re-export,不包含任何逻辑
|
||
|
||
#### Scenario: types.ts 包含该 checker 全部专属类型
|
||
- **WHEN** 开发者需要该 checker 的配置类型、resolved 类型或 expect 类型
|
||
- **THEN** 这些类型 SHALL 全部定义在该 checker 目录的 `types.ts` 中,不在顶层 `types.ts` 中
|
||
|
||
#### Scenario: schema.ts 包含 TypeBox schema 定义
|
||
- **WHEN** 开发者需要该 checker 的 config 或 expect schema
|
||
- **THEN** 这些 schema SHALL 定义在该 checker 目录的 `schema.ts` 中
|
||
|
||
#### Scenario: execute.ts 包含 Checker 类实现
|
||
- **WHEN** 开发者需要查看该 checker 的执行逻辑
|
||
- **THEN** Checker 类(实现 CheckerDefinition 接口)SHALL 定义在 `execute.ts` 中
|
||
|
||
#### Scenario: validate.ts 包含该 checker 全部语义校验
|
||
- **WHEN** 开发者需要查看该 checker 的配置校验逻辑
|
||
- **THEN** 该 checker 专属的语义校验函数 SHALL 全部定义在 `validate.ts` 中
|
||
|
||
#### Scenario: expect.ts 包含该 checker 专属断言
|
||
- **WHEN** 开发者需要查看该 checker 的断言逻辑
|
||
- **THEN** 该 checker 专属的断言函数 SHALL 定义在 `expect.ts` 中
|
||
|
||
### Requirement: 断言基础设施目录
|
||
系统 SHALL 在 `src/server/checker/expect/` 目录中提供所有 checker 共享的断言基础设施。共享 expect 目录 SHALL 使用 Raw/Resolved expectation 术语和 value/content/keyed/status/headers 模块边界。
|
||
|
||
#### Scenario: expect 共享类型位置
|
||
- **WHEN** 任何 checker 需要使用断言相关的共享类型(如 `ExpectationResult`、`ValueExpectation`、`ContentExpectations` 或 `KeyedExpectations`)
|
||
- **THEN** 这些类型 SHALL 从 `src/server/checker/expect/types.ts` 导入
|
||
|
||
#### Scenario: value 断言引擎位置
|
||
- **WHEN** 任何 checker 需要使用 `applyValueMatcher`、`evaluateJsonPath`、`resolveValueExpectation` 或 `checkValueExpectation`
|
||
- **THEN** 这些函数 SHALL 从 `src/server/checker/expect/value.ts` 导入
|
||
|
||
#### Scenario: content 和 keyed 断言位置
|
||
- **WHEN** 任何 checker 需要执行内容数组或键值表 expectation
|
||
- **THEN** SHALL 分别从 `src/server/checker/expect/content.ts` 和 `src/server/checker/expect/keyed.ts` 导入共享函数
|
||
|
||
#### Scenario: failure 构造器位置
|
||
- **WHEN** 任何 checker 需要使用 `errorFailure` 或 `mismatchFailure`
|
||
- **THEN** 这些函数 SHALL 从 `src/server/checker/expect/failure.ts` 导入
|
||
|
||
#### Scenario: expectation 校验位置
|
||
- **WHEN** 任何 checker 的 validate 需要校验 Raw value、Raw content 或 Raw keyed expectation
|
||
- **THEN** 对应函数 SHALL 从 `src/server/checker/expect/validate.ts` 导入
|
||
|
||
#### Scenario: ExpectationResult 类型位置
|
||
- **WHEN** 任何 checker 需要使用 `ExpectationResult` 类型
|
||
- **THEN** 该类型 SHALL 从 `src/server/checker/expect/types.ts` 导入
|
||
|
||
### Requirement: Schema 目录结构
|
||
系统 SHALL 在 `src/server/checker/schema/` 目录中组织配置 schema 体系,替代原 `config-contract/` 目录。
|
||
|
||
#### Scenario: schema 目录包含 builder
|
||
- **WHEN** 系统需要从 registry 动态构建整体配置 schema
|
||
- **THEN** 该逻辑 SHALL 位于 `src/server/checker/schema/builder.ts`
|
||
|
||
#### Scenario: schema 目录包含 fragments
|
||
- **WHEN** checker 的 schema.ts 需要引用共享 schema 片段(如 durationSchema、sizeSchema)
|
||
- **THEN** 这些片段 SHALL 从 `src/server/checker/schema/fragments.ts` 导入
|
||
|
||
#### Scenario: schema 目录包含 Ajv 校验入口
|
||
- **WHEN** config-loader 需要执行契约校验
|
||
- **THEN** 校验入口 SHALL 位于 `src/server/checker/schema/validate.ts`
|
||
|
||
#### Scenario: schema 目录包含 issue 工具
|
||
- **WHEN** 任何校验逻辑需要构造 ConfigValidationIssue
|
||
- **THEN** issue 类型和工具函数 SHALL 从 `src/server/checker/schema/issues.ts` 导入
|
||
|
||
### Requirement: 工具函数归集
|
||
系统 SHALL 在 `src/server/checker/utils.ts` 中提供纯工具函数。
|
||
|
||
#### Scenario: parseSize 位置
|
||
- **WHEN** 任何模块需要解析 size 字符串(如 "100MB")
|
||
- **THEN** `parseSize` SHALL 从 `src/server/checker/utils.ts` 导入
|
||
|
||
#### Scenario: parseDuration 位置
|
||
- **WHEN** 任何模块需要解析 duration 字符串(如 "30s")
|
||
- **THEN** `parseDuration` SHALL 从 `src/server/checker/utils.ts` 导入
|
||
|
||
### Requirement: 依赖方向约束
|
||
checker 系统内的模块依赖 SHALL 遵循严格的分层方向。
|
||
|
||
#### Scenario: checker 之间无横向依赖
|
||
- **WHEN** 开发者查看任何 checker 目录的 import 语句
|
||
- **THEN** 该 checker SHALL NOT 导入其他 checker 目录的任何模块
|
||
|
||
#### Scenario: expect/ 不依赖 runner/
|
||
- **WHEN** 开发者查看 `expect/` 目录的 import 语句
|
||
- **THEN** `expect/` 中的文件 SHALL NOT 导入 `runner/` 目录的任何模块
|
||
|
||
#### Scenario: schema/ 不依赖 runner/ 的具体 checker
|
||
- **WHEN** 开发者查看 `schema/` 目录的 import 语句
|
||
- **THEN** `schema/` 中的文件 SHALL 仅通过 `CheckerDefinition` 接口与 checker 交互,SHALL NOT 直接导入具体 checker 目录
|
||
|
||
### Requirement: 显式注册列表
|
||
系统 SHALL 在 `src/server/checker/runner/index.ts` 中使用显式 import 列表注册所有 checker。
|
||
|
||
#### Scenario: 注册入口结构
|
||
- **WHEN** 开发者查看 `runner/index.ts`
|
||
- **THEN** 该文件 SHALL 包含所有 checker 的静态 import 和一个 checker 实例数组,通过循环调用 `registry.register()` 完成注册
|
||
|
||
#### Scenario: 新增 checker 注册
|
||
- **WHEN** 开发者新增一个 checker
|
||
- **THEN** 开发者 SHALL 在 `runner/index.ts` 中添加一行 import 和一行数组项,无需修改其他文件
|
||
|
||
### Requirement: 公共类型文件瘦身
|
||
顶层 `src/server/checker/types.ts` SHALL 仅保留跨 checker 共享的 base 类型和存储相关类型;expect 专属类型 SHALL 放在 `src/server/checker/expect/types.ts`。
|
||
|
||
#### Scenario: types.ts 不包含 checker 或 expect 专属类型
|
||
- **WHEN** 开发者查看顶层 `types.ts`
|
||
- **THEN** 该文件 SHALL NOT 包含 `HttpTargetConfig`、`ResolvedHttpTarget`、`RawCommandExpectConfig`、`ContentExpectation` 等 checker 专属或 expect 专属类型
|
||
|
||
#### Scenario: types.ts 保留 base 类型
|
||
- **WHEN** 开发者查看顶层 `types.ts`
|
||
- **THEN** 该文件 SHALL 包含 `ResolvedTargetBase`、`RawTargetConfig`、`DefaultsConfig`、`CheckResult`、`CheckFailure`、`StoredTarget`、`StoredCheckResult`、`JsonValue` 等公共类型
|
||
|
||
#### Scenario: ResolvedTargetBase 替代联合类型
|
||
- **WHEN** engine、store、config-loader 需要引用 resolved target 类型
|
||
- **THEN** 这些模块 SHALL 使用 `ResolvedTargetBase` interface,不再使用硬编码联合类型
|
||
|
||
#### Scenario: DefaultsConfig 为宽松 base 形式
|
||
- **WHEN** 开发者查看顶层 `types.ts` 中的 `DefaultsConfig`
|
||
- **THEN** 该 interface SHALL 仅包含公共字段(`interval?`、`timeout?`)和 index signature(`[checkerKey: string]: unknown`),SHALL NOT 包含 `cmd?`、`http?` 等 checker 专属字段
|
||
|
||
#### Scenario: 各 checker validate 自行 narrow defaults
|
||
- **WHEN** checker 的 `validate()` 方法需要访问自身的 defaults 配置
|
||
- **THEN** checker SHALL 从 `DefaultsConfig` 中通过 `defaults[configKey]` 获取并自行 narrow 为具体类型
|