1
0
Files
DiAL/openspec/specs/checker-cohesion-structure/spec.md
lanyuanxiaoyao 26f0bfe104 docs: 归档 checker 内聚化重构变更,同步 delta specs 到主规范
- 归档 refactor-checker-coherence 变更至 archive/2026-05-13-refactor-checker-cohesion/
- 新增主规范 checker-cohesion-structure(12 条需求)
- 更新主规范 checker-runner-abstraction(新增 base interface 类型相关场景)
2026-05-13 15:02:59 +08:00

8.2 KiB
Raw Blame History

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.tstypes.tsschema.tsexecute.tsexpect.tsbody.tsvalidate.ts

Scenario: Command checker 目录完整性

  • WHEN 开发者查看 src/server/checker/runner/command/ 目录
  • THEN 该目录 SHALL 包含 index.tstypes.tsschema.tsexecute.tsexpect.tstext.tsvalidate.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/defaults/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 共享的断言基础设施。

Scenario: expect 共享类型位置

  • WHEN 任何 checker 需要使用断言相关的共享类型(如 ExpectResult
  • THEN 这些类型 SHALL 从 src/server/checker/expect/types.ts 导入

Scenario: operator 断言引擎位置

  • WHEN 任何 checker 需要使用 applyOperatorevaluateJsonPathcheckExpectValue
  • THEN 这些函数 SHALL 从 src/server/checker/expect/operator.ts 导入

Scenario: duration 断言位置

  • WHEN 任何 checker 需要使用 checkDuration
  • THEN 该函数 SHALL 从 src/server/checker/expect/duration.ts 导入

Scenario: failure 构造器位置

  • WHEN 任何 checker 需要使用 errorFailuremismatchFailure
  • THEN 这些函数 SHALL 从 src/server/checker/expect/failure.ts 导入

Scenario: operator 校验位置

  • WHEN 任何 checker 的 validate 需要使用 validateOperatorObject
  • THEN 该函数 SHALL 从 src/server/checker/expect/validate-operator.ts 导入

Scenario: ExpectResult 类型位置

  • WHEN 任何 checker 需要使用 ExpectResult 类型
  • 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 类型和存储相关类型。

Scenario: types.ts 不包含 checker 专属类型

  • WHEN 开发者查看顶层 types.ts
  • THEN 该文件 SHALL NOT 包含 HttpTargetConfigResolvedHttpTargetCommandExpectConfigBodyRuleTextRule 等 checker 专属类型

Scenario: types.ts 保留 base 类型

  • WHEN 开发者查看顶层 types.ts
  • THEN 该文件 SHALL 包含 ResolvedTargetBaseRawTargetConfigDefaultsConfigCheckResultExpectOperatorCheckFailureStoredTargetStoredCheckResultJsonValue 等公共类型

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]: unknownSHALL NOT 包含 command?http? 等 checker 专属字段

Scenario: 各 checker validate 自行 narrow defaults

  • WHEN checker 的 validate() 方法需要访问自身的 defaults 配置
  • THEN checker SHALL 从 DefaultsConfig 中通过 defaults[configKey] 获取并自行 narrow 为具体类型