Files
opencode-build/skills/metadata-validator/SKILL.md
T
2026-06-22 10:08:52 +08:00

7.6 KiB

name, description
name description
metadata-validator 当需要校验某个数据需求中候选的表、字段、join 关联和时间字段是否真实存在于工作区元数据中时使用。触发词包括"validate metadata"、"check if table exists"、"field mapping"、"join key validation"、"确认表/字段"、"校验 schema"、"这个字段在哪张表"、"口径对得上吗"。递归扫描工作区中的元数据文件(JSON / Markdown / CSV / Excel / YAML / DDL / 数据字典),并产出标准化的 Validation Result 和 Field Mapping。

Metadata Validator(元数据校验器)

概述(Overview)

本 skill 在需求的"期望表/字段"和工作区元数据中的"实际 schema"之间架起桥梁。输出会被 logic-plannersql-context-builder 原样消费,二者不得重复校验。

核心原则:绝不臆测表名、字段名或 join 关系。 如果某候选在元数据中无法证实存在,将其作为 pending_question 暴露,状态停在 NEED_USER_CONFIRMATION

何时使用(When to Use)

使用场景:

  • requirements-analysis 已经产出候选表/字段,需要确认它们在真实元数据中存在
  • 用户询问"这张表/这个字段是否存在"、"表 X 的元数据在哪份文件里"、"业务字段映射到哪个物理列"
  • 需要检测 join key、时间列、可用于聚合的数值列
  • 即将写 SQL,必须防止出现幻觉字段名

不要使用场景:

  • 用户已经提供并确认了精确的表名+列名 — 直接进入 logic-planner
  • 任务是无数据仓库上下文的纯代码生成

输入(Inputs)

  1. 来自 requirements-analysis 的:
    • candidate_tables: 用户提到或隐含的表名列表
    • candidate_fields: 业务字段名及其建议所在表
    • business_logic: 计算逻辑的简短描述
  2. 工作区元数据:当前工作目录下任何符合元数据约定的文件(见下文)

工作流(Workflow)

digraph metadata_validator {
    "接收候选表/字段" [shape=box];
    "递归扫描工作区中的元数据文件" [shape=box];
    "将每个文件解析为规范化的 (table, field, type) 记录" [shape=box];
    "检查候选表是否存在" [shape=box];
    "检查候选字段是否在其所属表中存在" [shape=box];
    "对缺失字段做模糊匹配" [shape=box];
    "检测 join key 与时间列" [shape=box];
    "所有检查都通过?" [shape=diamond];
    "构建 Field Mapping" [shape=box];
    "输出 Validation Result (VALIDATED)" [shape=box];
    "输出 Validation Result (NEED_USER_CONFIRMATION)" [shape=box];

    "接收候选表/字段" -> "递归扫描工作区中的元数据文件";
    "递归扫描工作区中的元数据文件" -> "将每个文件解析为规范化的 (table, field, type) 记录";
    "将每个文件解析为规范化的 (table, field, type) 记录" -> "检查候选表是否存在";
    "检查候选表是否存在" -> "检查候选字段是否在其所属表中存在";
    "检查候选字段是否在其所属表中存在" -> "对缺失字段做模糊匹配";
    "对缺失字段做模糊匹配" -> "检测 join key 与时间列";
    "检测 join key 与时间列" -> "所有检查都通过?";
    "所有检查都通过?" -> "构建 Field Mapping" [label="yes"];
    "所有检查都通过?" -> "输出 Validation Result (NEED_USER_CONFIRMATION)" [label="no"];
    "构建 Field Mapping" -> "输出 Validation Result (VALIDATED)";
}

元数据发现(Metadata Discovery)

  • 递归扫描当前工作目录(及其所有子目录) — 不要假设存在 metadata/ 目录

  • 文件名常常形似表名(例如 loan_order.jsoncustomer_info.mddim_product.csv),但绝不要只信任文件名 — 必须打开文件,确认里面的表标识符

  • 支持的格式(按内容自动识别,不按扩展名):

    • JSON / JSONL
    • YAML
    • Markdown 表格 / 标题
    • CSV(带表头)
    • Excel(.xlsx.xls) — 用 openpyxlpandas.read_excel
    • DDL / CREATE TABLE 语句
    • 自由形式的数据字典(解析键值行或 field | type | comment 表格)
  • 在校验之前,先把每个文件转成规范化的记录格式:

    tables:
      - table: <物理表名>
        source_file: <相对路径>
        fields:
          - name: <字段名>
            type: <string|int|long|double|decimal|date|timestamp|boolean|...>
            comment: <可选>
    

校验规则(Validation Rules)

全部以下规则都要执行。任意一条失败 ⇒ 状态为 NEED_USER_CONFIRMATION

  1. 表存在性 — 每个候选表必须出现在解析后的元数据中
  2. 字段存在性 — 每个候选字段必须出现在其候选所属表中
  3. 字段归属 — 字段可能存在但属于另一张表;绝不能悄悄替换
  4. 类型合理性 — 聚合目标(sum / avg / count)必须为数值型;时间过滤字段必须为 date/timestamp/字符串型日期
  5. 必要字段 — 如果业务逻辑中常见字段缺失(统计指标、时间、join key、维度),要标记出来
  6. 模糊匹配 — 对每个缺失字段,按名称相似度打分(customer_idcust_idcust_nocustomer_no)和 Levenshtein 距离,给出 Top-N
  7. join 检测 — 在已校验的表之间,查找共享的 *_id*_no*_code 列。如果存在多个可能的 join key,必须询问
  8. 时间列消歧 — 列出每张表中所有时间类字段(create_timeapply_timetxn_dateupdate_timedt);询问哪一个决定时间粒度
  9. 覆盖度 — 验证维度、指标、过滤列、排序键是否都存在

禁止行为(Forbidden Behaviors)

自我说服 现实
"文件名是 loan_order.json,肯定就是这张表" 文件名只是提示,必须解析文件内容确认。
"字段存在于某处,所以 join 没问题" 错误的表归属会让 join 失效。永远要校验归属。
"用户八成指的是 cust_no,直接用吧" 必须作为候选暴露并询问,绝不能自动替换。
"时间字段我猜一个就行" 多个时间字段时必须询问。粒度决定整条查询。
"这份元数据够了,不必再扫" 永远要递归扫描。一个文件可能描述多张表。

输出契约(Output Contract)

输出是一份单一的 YAML 文档,下游 skill 原样消费。

validation_result:
  validated_tables:
    - <table_name>
  validated_fields:
    - <table_name>.<field_name>
  missing_tables: []
  missing_fields:
    - <field_name_not_found_anywhere>
  candidate_fields:
    <missing_field_name>:
      - <candidate_1>
      - <candidate_2>
  candidate_tables:
    <missing_table_name>:
      - <candidate_1>
  join_candidates:
    - left: <table_a>.<field>
      right: <table_b>.<field>
      confidence: <high|medium|low>
  time_field_candidates:
    <table_name>:
      - <field>
      - <field>
  metadata_sources:
    - <相对路径指向元数据文件>
  pending_questions:
    - "<面向用户的问题,最好给出 A/B/C 选项>"
  field_mapping:
    <business_field_name>:
      table: <物理表>
      column: <物理字段>
      type: <数据类型>
  status: <VALIDATED | NEED_USER_CONFIRMATION>

field_mapping 是下游 logic-plannersql-context-builder唯一权威来源。如果某个业务字段没有映射,该需求无法继续 — 把它加入 pending_questions

完成判定(Completion Criteria)

仅当以下全部成立时,才允许状态 VALIDATED:

  • 每个候选表都出现在 validated_tables
  • 每个候选字段都有 field_mapping 条目
  • 所有 join key 都已确定(或显然到可以用 high 置信度推断)
  • 查询粒度对应的时间列已确定
  • pending_questions 为空

其余情况 ⇒ NEED_USER_CONFIRMATION 并停止。不得继续进入 logic-planner