diff --git a/data-structure-fetcher/SKILL.md b/data-structure-fetcher/SKILL.md
new file mode 100644
index 0000000..b60508b
--- /dev/null
+++ b/data-structure-fetcher/SKILL.md
@@ -0,0 +1,103 @@
+---
+name: data-structure-fetcher
+description: 通过文本实体匹配→向量检索→大模型加权汇总三步流程,从数据字典库中智能匹配业务需求所需的数据源及字段。当用户需要了解数据结构、查找表字段、查询数据字典或询问有哪些数据可用时,使用此技能。
+---
+
+# 数据结构获取 Skill
+
+## 技能描述
+
+采用**三步匹配流程**,直接调用脚本获取数据源:
+1. **向量检索**:调用 `embedding_api_call.py`,传入用户完整问题
+2. **文本实体匹配**:从问题中提取核心实体,对**每个实体**依次调用 `wenben_api_call.py`
+3. **加权汇总**:解析两份结果 → 加权融合(向量 0.6 + 文本 0.4)→ 输出推荐 Top 5 表
+
+## 目录结构
+
+```
+data-structure-fetcher/
+├── SKILL.md
+└── scripts/
+ ├── embedding_api_call.py # 向量检索脚本
+ └── wenben_api_call.py # 文本匹配脚本
+```
+
+## 使用方法
+
+### 步骤 1:提取查询实体
+
+从用户问题中提取核心业务实体/关键词。例如:
+- "统计各投诉处理部门的投诉受理量" → 提取:"投诉"、"部门"、"受理量"
+
+### 步骤 2:调用向量检索(一次)
+
+```bash
+python /root/.config/opencode/skills/data-structure-fetcher/scripts/embedding_api_call.py "用户完整问题" 10
+```
+
+### 步骤 3:调用文本匹配(每个实体依次调用)
+
+```bash
+python /root/.config/opencode/skills/data-structure-fetcher/scripts/wenben_api_call.py "实体1" 5
+python /root/.config/opencode/skills/data-structure-fetcher/scripts/wenben_api_call.py "实体2" 5
+# ... 每个实体依次调用
+```
+
+**注意**:所有实体的返回结果需**合并去重**,作为文本匹配的总结果。
+
+### 步骤 4:解析脚本返回结果
+
+两个脚本均返回 **Markdown 表格格式**,需从中提取结构化信息:
+- **向量检索结果**:包含 `distance` 字段(相似度,越小越匹配)
+- **文本匹配结果**:不包含 `distance` 字段
+
+每个结果包含:
+- `ID`:库名.表名(如 `db_dwd.dwd_crm_srv_complaint_rt`)
+- `元数据`:JSON 格式,含 `schema_name`、`table_name`、`table_cn_name`、`table_comment`、`table_owner`、`field_count`
+- `文档内容`:字段清单,格式如 `字段名(类型)、字段中文名、...`
+
+### 步骤 5:加权融合排序
+
+```
+综合得分 = 向量归一化得分 × 0.6 + 文本归一化得分 × 0.4
+```
+
+- **向量得分**:`score = 1 - distance`,然后 min-max 归一化到 [0,1]
+- **文本得分**:按命中顺序归一化(首次出现得分最高)
+- **来源标记**:
+ - `both` — 两个源都命中(★ 最高置信度)
+ - `vector_only` — 仅向量命中(□)
+ - `text_only` — 仅文本命中(□)
+
+### 步骤 6:输出 Top 5 推荐表
+
+```
+================================================================================
+📊 推荐数据源 Top 5
+================================================================================
+
+★ 1. db_dwd.dwd_crm_srv_complaint_rt
+ 中文名:投诉整合层主表
+ 表注释:投诉业务整合宽表
+ 综合得分:0.9200
+ 来源:both (向量=0.950, 文本=0.875)
+ 负责人:蒋平川
+
+□ 2. db_dwa.dwa_crm_base_sr_compln_3rd
+ 中文名:投诉三级延伸全量宽表
+ 综合得分:0.8000
+ 来源:vector_only (向量=0.820, 文本=0.000)
+ 负责人:郭鑫超
+
+================================================================================
+```
+
+## 触发指令
+
+- "查找相关表"、"推荐数据源"、"这个指标用哪些表"
+- "查询数据结构"、"有哪些表可以统计 XX"
+- "需要了解数据结构"、"查找表字段"、"查询数据字典"
+
+## 被 requirement-analyzer 调用
+
+当 `requirement-analyzer` 进入模块 3(数据源匹配)时,自动调用本 skill,按上述流程执行脚本并汇总结果。
diff --git a/data-structure-fetcher/scripts/embedding_api_call.py b/data-structure-fetcher/scripts/embedding_api_call.py
new file mode 100644
index 0000000..1aca77b
--- /dev/null
+++ b/data-structure-fetcher/scripts/embedding_api_call.py
@@ -0,0 +1,124 @@
+import sys
+import requests
+import json
+import os
+
+# =========================
+# 1. 配置
+# =========================
+# 这里填写你刚才启动的 Flask 服务地址
+# 如果是本机运行,通常是 http://127.0.0.1:5001
+# 如果是服务器远程访问,请替换为服务器的 IP 地址
+API_URL = "http://127.0.0.1:5001/search"
+
+def query_table_metadata(query_text, top_k=10):
+ """
+ 调用 Flask 接口并返回 Markdown 格式的字符串
+
+ Args:
+ query_text (str or list): 查询内容,可以是字符串或字符串列表
+ top_k (int): 返回结果数量
+
+ Returns:
+ str: 格式化的 Markdown 字符串
+ """
+
+ # 1. 准备请求数据
+ payload = {
+ "q": query_text,
+ "top_k": top_k
+ }
+
+ headers = {
+ "Content-Type": "application/json"
+ }
+
+ print(f"🔍 正在查询: '{query_text}' ...")
+
+ try:
+ # 2. 发送 POST 请求
+ # 设置 timeout 防止接口卡死
+ response = requests.post(API_URL, json=payload, headers=headers, timeout=10)
+
+ # 检查 HTTP 状态码
+ if response.status_code != 200:
+ return f"❌ 请求失败,状态码: {response.status_code}, 错误信息: {response.text}"
+
+ # 3. 解析 JSON 响应
+ res_json = response.json()
+
+ if res_json.get("status") != "success":
+ return f"❌ 接口返回错误: {res_json.get('error')}"
+
+ data_list = res_json.get("data", [])
+
+ # 4. 生成 Markdown 内容
+ md_output = generate_markdown(data_list)
+
+ return md_output
+
+ except requests.exceptions.ConnectionError:
+ return "❌ 连接错误:无法连接到 Flask 服务,请检查 IP 地址和端口,或确认服务是否启动。"
+ except requests.exceptions.Timeout:
+ return "❌ 请求超时:服务器响应时间过长。"
+ except Exception as e:
+ return f"❌ 发生未知错误: {str(e)}"
+
+def generate_markdown(data_list):
+ """
+ 将接口返回的数据列表转换为 Markdown 表格
+ """
+ if not data_list:
+ return "⚠️ 未查询到任何数据。"
+
+ md_lines = []
+
+ # 遍历每一个查询结果(支持批量查询)
+ for item in data_list:
+ query = item.get("query")
+ results = item.get("results", [])
+
+ # 添加查询标题
+ md_lines.append(f"### 🔎 查询结果:{query}")
+ md_lines.append(f"共找到 {len(results)} 条相关表信息:\n")
+
+ # 添加表头
+ md_lines.append("| ID | 相似度 (Distance) | 元数据 (Metadata) | 文档内容 (Document) |")
+ md_lines.append("| :--- | :---: | :--- | :--- |")
+
+ # 添加每一行数据
+ for res in results:
+ doc_id = res.get("id", "N/A")
+ distance = res.get("distance")
+ # 格式化距离,保留4位小数
+ dist_str = f"{distance:.4f}" if distance is not None else "N/A"
+
+ metadata = res.get("metadata", {})
+ # 将元数据字典转为字符串,去除单引号以便Markdown显示更整洁
+ meta_str = json.dumps(metadata, ensure_ascii=False)
+
+ document = res.get("document", "")
+ # 简单的清洗,防止文档内容里的换行符破坏表格结构
+ document = document.replace("\n", " ").replace("|", "/")
+
+ md_lines.append(f"| {doc_id} | {dist_str} | {meta_str} | {document} |")
+
+ md_lines.append("\n---\n") # 分割线
+
+ return "\n".join(md_lines)
+
+# =========================
+# 5. 主程序入口 (测试用)
+# =========================
+if __name__ == "__main__":
+ # 获取命令行参数,例如: python client.py "查询内容" 10
+ if len(sys.argv) > 1:
+ query_input = sys.argv[1]
+ k_input = int(sys.argv[2]) if len(sys.argv) > 2 else 5
+ else:
+ # 默认值
+ query_input = "按日分投诉"
+ k_input = 10
+
+ result_md = query_table_metadata(query_input, top_k=k_input)
+ print(result_md)
\ No newline at end of file
diff --git a/data-structure-fetcher/scripts/wenben_api_call.py b/data-structure-fetcher/scripts/wenben_api_call.py
new file mode 100644
index 0000000..e5da53b
--- /dev/null
+++ b/data-structure-fetcher/scripts/wenben_api_call.py
@@ -0,0 +1,121 @@
+import sys
+import requests
+import json
+import os
+
+# =========================
+# 1. 配置
+# =========================
+# 这里填写你刚才启动的 Flask 服务地址
+# 如果是本机运行,通常是 http://127.0.0.1:5001
+# 如果是服务器远程访问,请替换为服务器的 IP 地址
+API_URL = "http://127.0.0.1:5001/like"
+
+def query_table_metadata(query_text, top_k=5):
+ """
+ 调用 Flask 接口并返回 Markdown 格式的字符串
+
+ Args:
+ query_text (str or list): 查询内容,可以是字符串或字符串列表
+ top_k (int): 返回结果数量
+
+ Returns:
+ str: 格式化的 Markdown 字符串
+ """
+
+ # 1. 准备请求数据
+ payload = {
+ "q": query_text,
+ "top_k": top_k
+ }
+
+ headers = {
+ "Content-Type": "application/json"
+ }
+
+ print(f"🔍 正在查询: '{query_text}' ...")
+
+ try:
+ # 2. 发送 POST 请求
+ # 设置 timeout 防止接口卡死
+ response = requests.post(API_URL, json=payload, headers=headers, timeout=10)
+
+ # 检查 HTTP 状态码
+ if response.status_code != 200:
+ return f"❌ 请求失败,状态码: {response.status_code}, 错误信息: {response.text}"
+
+ # 3. 解析 JSON 响应
+ res_json = response.json()
+
+ if res_json.get("status") != "success":
+ return f"❌ 接口返回错误: {res_json.get('error')}"
+
+ data_list = res_json.get("data", [])
+
+ # 4. 生成 Markdown 内容
+ md_output = generate_markdown(data_list)
+
+ return md_output
+
+ except requests.exceptions.ConnectionError:
+ return "❌ 连接错误:无法连接到 Flask 服务,请检查 IP 地址和端口,或确认服务是否启动。"
+ except requests.exceptions.Timeout:
+ return "❌ 请求超时:服务器响应时间过长。"
+ except Exception as e:
+ return f"❌ 发生未知错误: {str(e)}"
+
+def generate_markdown(data_list):
+ """
+ 将接口返回的数据列表转换为 Markdown 表格
+ """
+ if not data_list:
+ return "⚠️ 未查询到任何数据。"
+
+ md_lines = []
+
+ # 遍历每一个查询结果(支持批量查询)
+ for item in data_list:
+ query = item.get("query")
+ results = item.get("results", [])
+
+ # 添加查询标题
+ md_lines.append(f"### 🔎 查询结果:{query}")
+ md_lines.append(f"共找到 {len(results)} 条相关表信息:\n")
+
+ # 添加表头
+ md_lines.append("| ID | 元数据 (Metadata) | 文档内容 (Document) |")
+ md_lines.append("| :--- | :--- | :--- |")
+
+ # 添加每一行数据
+ for res in results:
+ doc_id = res.get("\ufeffid", "N/A")
+
+ metadata = res.get("metadata", {})
+ # 将元数据字典转为字符串,去除单引号以便Markdown显示更整洁
+ meta_str = json.dumps(metadata, ensure_ascii=False)
+
+ document = res.get("document", "")
+ # 简单的清洗,防止文档内容里的换行符破坏表格结构
+ document = document.replace("\n", " ").replace("|", "/")
+
+ md_lines.append(f"| {doc_id} | {meta_str} | {document} |")
+
+ md_lines.append("\n---\n") # 分割线
+
+ return "\n".join(md_lines)
+
+# =========================
+# 5. 主程序入口 (测试用)
+# =========================
+if __name__ == "__main__":
+ # 获取命令行参数,例如: python client.py "查询内容" 10
+ if len(sys.argv) > 1:
+ query_input = sys.argv[1]
+ k_input = int(sys.argv[2]) if len(sys.argv) > 2 else 5
+ else:
+ # 默认值
+ query_input = "投诉"
+ k_input = 5
+
+ result_md = query_table_metadata(query_input, top_k=k_input)
+ print(result_md)
\ No newline at end of file
diff --git a/model-design-generator/SKILL.md b/model-design-generator/SKILL.md
new file mode 100644
index 0000000..19541c4
--- /dev/null
+++ b/model-design-generator/SKILL.md
@@ -0,0 +1,418 @@
+---
+name: model-design-generator
+description: 根据数据需求技术规范文档生成模型设计技术规范文档
+---
+
+# 模型设计技能 (Model Design Skill)
+
+## 技能描述
+
+本技能根据用户输入的**数据需求技术规范文档**,自动生成对应的**模型设计技术规范文档**,包含 SQL 编排步骤、目标表属性信息、目标表字段信息等完整设计内容。
+
+## 输入输出
+
+### 输入
+- **输入类型**:MD 文件路径(数据需求技术规范文档的文件路径)或目录路径
+- **输入来源**:
+ - 用户传入具体文件路径:直接使用该文件
+ - 用户传入目录路径:自动选取文件名中日期最新的 `REQ-DATA-*.md` 文件
+- **输入示例**:
+ - 文件路径:`202604/skills_design/v2/data/REQ-DATA-20260409142709-001.md`
+ - 目录路径:`202604/skills_design/v2/data/` → 自动选取 `REQ-DATA-20260409142709-001.md`(最新的)
+
+### 输出
+- **输出类型**:Markdown + JSON 格式文本(模型设计技术规范文档)
+- **输出内容**:
+ 1. 编排目标表生成流程(SQL 编排步骤)- Markdown 表格
+ 2. 目标表属性信息 - JSON 格式
+ 3. 目标表字段信息 - JSON 格式
+
+---
+
+## 可配置参数
+
+以下参数按**输出模板的表结构**组织,方便后续统一修改:
+
+---
+
+### 表 1:编排目标表生成流程 - 字段规则与配置
+
+输出模板字段:`步骤序号 | sql 编排内容解释 | 输入源表 | 加工字段口径 | 输出表名 | 输出表字段`
+
+| 输出字段 | 填写规则 | 默认值/配置项 | 说明 |
+|----------|----------|---------------|------|
+| 步骤序号 | 按 `step01`, `step02`, `step03`... 顺序编号,步骤数根据加工复杂度决定 | 无,按步骤生成 | 标识处理步骤顺序 |
+| sql 编排内容解释 | 根据加工逻辑自然语言描述 | 无,AI 生成 | 描述该步骤的加工目的和操作 |
+| 输入源表 | 从需求文档"所用数据源及字段"表提取 | 无,从输入提取 | 该步骤依赖的源表列表 |
+| 加工字段口径 | 从需求文档"输出表字段 - 字段加工逻辑"提取并整理 | 无,从输入提取 | 字段的加工规则说明 |
+| 输出表名 | 临时表:`${db_tmp_env}.${temp_table.prefix}${temp_table.suffix}`
目标表:`${db_eda_env}.${target_table.prefix}_xxx` | `db_tmp_env`(**保留占位符**)
`db_eda_env`(**保留占位符**)
`temp_table.prefix=tmp_prj004_ads_rpt`(**展开为实际值**)
`temp_table.suffix=_01,_02...`(**展开为实际值**)
`target_table.prefix=prj004_ads_rpt`(**展开为实际值**) | 最后一步输出目标表,中间步骤输出临时表;**输出时内部变量需展开,外部变量保留** |
+| 输出表字段 | 从需求文档"输出表字段"提取,逗号分隔 | 无,从输入提取 | 该步骤产出的字段列表 |
+
+---
+
+### 表 2:目标表属性信息 - 字段规则与配置
+
+输出模板字段:`数据目录 | 数据源 | 表编码 | 描述 | 数据源类型 | 表名称 | 数据归口条线 | 是否已上传至集团 | 是否可共享 | 技术人员 | 技术人员电话 | 维护人员 | 维护人员电话 | 管理人员 | 管理人员电话 | 增量/全量 | 是否有敏感信息`
+
+| 输出字段 | 填写规则 | 默认值/配置项 | 说明 |
+|----------|----------|---------------|------|
+| 数据目录 | 从需求文档"输出表名 - 数据目录"提取,或按业务类型匹配 | `table_attr.data_catalog=指标层 - 客户服务` | 可选值:`指标层 - 客户服务`、`明细层 - 投诉`、`汇总层 - 业务` 等 |
+| 数据源 | 从需求文档"所用数据源及字段"涉及的源表归纳 | 无,从输入提取 | 描述数据来源,如"投诉工单、组织机构" |
+| 表编码 | 从需求文档"输出表名 - 表英文名称"提取 | 无,从输入提取 | 输出表的英文表名 |
+| 描述 | 从需求文档"输出表名 - 表描述"提取 | 无,从输入提取 | 表的业务含义描述 |
+| 数据源类型 | 固定值或从需求文档提取 | `table_attr.data_source_type=paimon` | 可选值:`paimon`、`hive`、`mysql` 等 |
+| 表名称 | 从需求文档"输出表名 - 表中文名称"提取 | 无,从输入提取 | 输出表的中文表名 |
+| 数据归口条线 | 从需求文档"需求提出方"映射 | `table_attr.business_line=客户服务部` | 业务归属部门 |
+| 是否已上传至集团 | 固定默认值 | `table_attr.is_uploaded=否` | `是`/`否` |
+| 是否可共享 | 固定默认值 | `table_attr.is_shareable=是` | `是`/`否` |
+| 技术人员 | 默认配置 | `table_attr.tech_name=张三` | 技术负责人姓名 |
+| 技术人员电话 | 默认配置 | `table_attr.tech_phone=13800138000` | 技术负责人电话 |
+| 维护人员 | 默认配置 | `table_attr.maint_name=李四` | 数据维护人员姓名 |
+| 维护人员电话 | 默认配置 | `table_attr.maint_phone=13900139000` | 数据维护人员电话 |
+| 管理人员 | 默认配置 | `table_attr.mgr_name=王五` | 数据管理人员姓名 |
+| 管理人员电话 | 默认配置 | `table_attr.mgr_phone=13700137000` | 数据管理人员电话 |
+| 增量/全量 | 从需求文档"运行频次"映射 | `table_attr.load_type=增量` | `增量`/`全量`,日/周/月频次→增量 |
+| 是否有敏感信息 | 固定默认值 | `table_attr.has_sensitive=否` | `是`/`否` |
+
+---
+
+### 表 3:目标表字段信息 - 字段规则与配置
+
+输出模板字段:`字段编码 | 字段名称 | 字段类型 | 字段分类 | 排序 | 是否自增 | 是否需脱敏 | 描述`
+
+#### 3.1 各输出字段规则总览
+
+| 输出字段 | 填写规则 | 默认值/配置项 | 说明 |
+|----------|----------|---------------|------|
+| 字段编码 | 从需求文档"输出表字段 - 输出字段英文名"提取 | 无,从输入提取 | 字段英文名,snake_case 格式 |
+| 字段名称 | 从需求文档"输出表字段 - 输出字段中文名"提取 | 无,从输入提取 | 字段中文名 |
+| 字段类型 | 按"3.2 字段类型映射"转换 | 见下方 3.2 节 | 需求类型→数据库类型 |
+| 字段分类 | 按"3.3 字段分类规则"自动识别 | 见下方 3.3 节 | 维度/标识/指标/扩展/分区 |
+| 排序 | 从 1 开始自增 | `field.sort_start=1` | 连续递增,无跳号 |
+| 是否自增 | 固定默认值 | `field.auto_increment=否` | `是`/`否` |
+| 是否需脱敏 | 固定默认值 | `field.mask_required=否` | `是`/`否` |
+| 描述 | 从需求文档"字段业务含义"+"加工逻辑"整理 | 无,AI 生成 | 字段含义 + 加工规则说明 |
+
+#### 3.2 字段类型映射配置
+
+| 需求文档类型 | 目标数据库类型 | 配置项 | 说明 |
+|--------------|----------------|--------|------|
+| string | `STRING` | `type_map.string=STRING` | 字符串类型 |
+| bigint | `BIGINT` | `type_map.bigint=BIGINT` | 大整数 |
+| int | `INT` | `type_map.int=INT` | 整数 |
+| timestamp | `TIMESTAMP` | `type_map.timestamp=TIMESTAMP` | 时间戳 |
+| date | `STRING` | `type_map.date=STRING` | 日期(格式 yyyy-MM-dd) |
+| double/decimal | `DECIMAL(18,2)` | `type_map.decimal=DECIMAL(18,2)` | 小数 |
+
+#### 3.3 字段分类规则配置
+
+| 字段分类 | 识别特征(字段名/业务含义) | 配置项 | 示例 |
+|----------|----------------------------|--------|------|
+| 标识字段 | 含 `id`、`code`、`nbr`、唯一标识类 | `class.identifier.keys=id,code,nbr` | `idx_nbr`、`complaint_id`、`org_id` |
+| 维度字段 | 名称类 (`name`)、类型类 (`type`)、描述类 | `class.dimension.keys=name,type,desc` | `dept_name`、`bureau_name`、`complaint_type` |
+| 指标字段 | 数值类、统计类、含 `num`/`amt`/`value`/`cnt` | `class.metric.keys=num,amt,value,cnt` | `complaint_accept_num`、`idx_value` |
+| 分区字段 | 含 `day_id`、`stat_date`、`dt`、`date` | `class.partition.keys=day_id,stat_date,dt,date` | `day_id`、`stat_date` |
+
+#### 3.4 预置字段配置(可选追加)
+
+**说明**:默认不追加预置字段,目标表字段与需求文档"输出表字段"保持一致。如需追加运维或分区字段,可通过以下配置项控制:
+
+| 预置类型 | 配置项 | 默认值 | 说明 |
+|----------|--------|--------|------|
+| 运维字段 | `preset.etl.enabled` | `false` | 是否追加 `etl_time`、`etl_remark` |
+| 分区字段 | `preset.partition.enabled` | `false` | 是否追加 `day_id` |
+| 分区字段名 | `preset.partition.field` | `day_id` | 分区字段名称 |
+
+---
+
+## 处理流程
+
+### Step 1: 解析输入并提取信息
+
+**1.1 输入文件处理**
+
+- 如果用户传入的是**文件路径**:直接读取该文件
+- 如果用户传入的是**目录路径**:
+ - 列出目录下所有 `REQ-DATA-*.md` 文件
+ - 按文件名中的日期时间戳排序(YYYYMMDDHHMMSS 部分)
+ - 自动选取最新的文件
+
+**1.2 读取并解析需求文档**
+
+读取 MD 文件,从数据需求技术规范文档中提取以下信息:
+
+1. **需求基础信息**:需求编号、需求描述、需求提出方等
+2. **输出表信息**:表名(中/英文)、数据目录、表描述
+3. **输出字段信息**:字段名、字段类型、加工逻辑、来源表
+4. **数据源信息**:库名、表名、字段信息
+
+**1.3 与用户确认关键信息(多轮对话)**
+
+在生成模型设计文档前,**必须**与用户确认以下关键信息:
+
+```
+请确认以下关键信息是否正确:
+
+【输入文件】
+- 文件路径:
+- 需求编号:<需求编号>
+
+【输出表信息】
+- 目标表名:<表英文名称>
+- 表中文名称:<表中文名称>
+- 数据目录:<数据目录>
+
+【字段信息】
+- 字段总数: 个
+- 分区字段:
+- 运行频次:<日/周/月等>
+
+以上信息是否正确?如无误请回复"正确"或"继续",如有问题请指出需要修改的内容。
+```
+
+**等待用户确认后才能继续生成。**
+
+**输出文件命名规则**:
+- 直接从输入文件名转换,将前缀 `REQ` 替换为 `MDDS`(Model Design Document Specification)
+- 输入文件名:`REQ-DATA-YYYYMMDDHHMMSS-XXX.md`
+- 输出文件名:`MDDS-DATA-YYYYMMDDHHMMSS-XXX.md`
+- 示例:
+ - 输入文件:`REQ-DATA-20260316142709-001.md`
+ - 输出文件:`MDDS-DATA-20260316142709-001.md`
+
+### Step 2: 生成编排步骤(对应表 1)
+
+**在用户确认关键信息后**,根据字段加工逻辑和数据依赖关系,生成 SQL 编排步骤:
+
+```
+编排规则:
+1. 识别数据依赖链:来源表 → 中间处理 → 目标表
+2. 按处理复杂度拆分步骤,每步一个明确目标:
+ - 简单场景(2 步):step01 清洗关联 → step02 补全写入
+ - 中等场景(3~4 步):增加中间聚合、多表关联等步骤
+ - 复杂场景(5~6 步):多层嵌套加工、多次关联转换等
+3. 每步骤包含:编排内容解释、输入源表、加工字段口径、输出表名、输出表字段
+4. 临时表命名:`${db_tmp_env}.${temp_table.prefix}${temp_table.suffix}`
+ - `${db_tmp_env}` 保留占位符格式,不展开
+ - `${temp_table.prefix}` 展开为实际值:`tmp_prj004_ads_rpt`
+ - `${temp_table.suffix}` 展开为实际值:`_01`, `_02`...
+ - 示例输出:`${db_tmp_env}.tmp_prj004_ads_rpt_01`
+5. 目标表命名:`${db_eda_env}.${target_table.prefix}_xxx`
+ - `${db_eda_env}` 保留占位符格式,不展开
+ - `${target_table.prefix}` 展开为实际值:`prj004_ads_rpt`
+ - `_xxx` 从需求文档"输出表名 - 表英文名称"提取(去掉库名后的表名部分)
+ - 示例输出:`${db_eda_env}.prj004_ads_rpt_kfb_idx_rt`
+```
+
+**字段填写说明**:
+- 步骤序号:按 `step01`, `step02`, `step03`... 顺序编号,步骤数根据加工复杂度决定
+- sql 编排内容解释:AI 根据加工逻辑自然语言描述
+- 输入源表:从需求文档"所用数据源及字段"表提取
+- 加工字段口径:从需求文档"输出表字段 - 字段加工逻辑"提取并整理
+- 输出表名:最后一步输出目标表,中间步骤输出临时表
+ - 临时表格式:`${db_tmp_env}.tmp_prj004_ads_rpt_01`(`${db_tmp_env}`保留,内部前缀和 suffix 展开)
+ - 目标表格式:`${db_eda_env}.prj004_ads_rpt_xxx`(`${db_eda_env}`保留,内部前缀和表名展开)
+- 输出表字段:从需求文档"输出表字段"提取,逗号分隔
+
+### Step 3: 生成目标表属性(对应表 2)
+
+**在用户确认编排步骤后**,根据需求文档的表信息和默认配置生成:
+
+```
+映射规则:
+- 数据目录 ← 需求文档"数据目录"字段(或 table_attr.data_catalog 默认值)
+- 数据源 ← 需求文档涉及的源表业务主题(从输入提取)
+- 表编码 ← 输出表英文名(从输入提取)
+- 描述 ← 需求文档表描述(从输入提取)
+- 数据源类型 ← table_attr.data_source_type
+- 表名称 ← 输出表中文名称(从输入提取)
+- 数据归口条线 ← table_attr.business_line
+- 是否已上传至集团 ← table_attr.is_uploaded
+- 是否可共享 ← table_attr.is_shareable
+- 技术人员/电话 ← table_attr.tech_name/tech_phone
+- 维护人员/电话 ← table_attr.maint_name/maint_phone
+- 管理人员/电话 ← table_attr.mgr_name/mgr_phone
+- 增量/全量 ← 根据运行频次映射 (table_attr.load_type)
+- 是否有敏感信息 ← table_attr.has_sensitive
+```
+
+### Step 4: 生成目标表字段(对应表 3)
+
+**在用户确认目标表属性后**,根据需求文档的字段信息进行转换:
+
+```
+映射规则:
+1. 字段编码 ← 输出字段英文名(从输入提取)
+2. 字段名称 ← 输出字段中文名(从输入提取)
+3. 字段类型 ← 按"3.2 字段类型映射"转换
+4. 字段分类 ← 按"3.3 字段分类规则"自动分类
+5. 排序 ← 从 field.sort_start 开始自增
+6. 是否自增 ← field.auto_increment
+7. 是否需脱敏 ← field.mask_required
+8. 描述 ← 字段业务含义 + 加工逻辑说明(AI 整理)
+9. 预置字段(默认不追加):
+ - 运维字段:当 preset.etl.enabled=true 时追加 etl_time、etl_remark
+ - 分区字段:当 preset.partition.enabled=true 时追加 day_id
+```
+
+---
+
+## 输出模板结构
+
+生成的模型设计文档遵循以下结构:
+
+```markdown
+# 模型设计需求模板
+
+## 1. 编排目标表生成流程
+
+| 步骤序号 | sql 编排内容解释 | 输入源表 | 加工字段口径 | 输出表名 | 输出表字段 |
+|----|----|----|----|----|----|
+| step01 | ... | ... | ... | ... | ... |
+
+## 2. 目标表属性信息
+
+```json
+{
+ "${target_table_name}": {
+ "data_catalog": "指标层 - 客户服务",
+ "data_source": "投诉工单、组织机构",
+ "table_code": "prj004_ads_rpt_xxx",
+ "description": "表描述",
+ "data_source_type": "paimon",
+ "table_name": "表中文名称",
+ "business_line": "客户服务部",
+ "is_uploaded": "否",
+ "is_shareable": "是",
+ "tech_name": "张三",
+ "tech_phone": "13800138000",
+ "maint_name": "李四",
+ "maint_phone": "13900139000",
+ "mgr_name": "王五",
+ "mgr_phone": "13700137000",
+ "load_type": "增量",
+ "has_sensitive": "否"
+ }
+}
+```
+
+## 3. 目标表字段信息
+
+```json
+{
+ "${target_table_name}": [
+ {
+ "field_code": "字段英文名",
+ "field_name": "字段中文名",
+ "field_type": "STRING",
+ "field_category": "维度",
+ "sort_order": 1,
+ "is_auto_increment": "否",
+ "mask_required": "否",
+ "description": "字段业务含义和加工规则说明"
+ }
+ ]
+}
+```
+
+---
+
+## 版本信息
+
+- **技能版本**:v2.1
+- **创建日期**:2026-04-08
+- **更新日期**:2026-04-10
+- **适用场景**:电信数据仓库 ADS 层模型设计
+- **输入模板版本**:数据需求技术规范文档 v5
+- **输出模板版本**:模型设计技术规范文档 v1
+- **新增功能**:
+ - 支持目录路径输入,自动选取最新日期的需求文档
+ - 多轮对话引导,分步确认关键信息
+
+---
+
+## 使用示例
+
+### 调用方式
+
+**场景 1:用户传入具体文件路径**
+
+```
+用户:请根据 202604/skills_design/v2/data/REQ-DATA-20260409142709-001.md 生成模型设计文档
+```
+
+**场景 2:用户传入目录路径,自动选取最新文件**
+
+```
+用户:请根据 202604/skills_design/v2/data/ 目录下的需求文档生成模型设计
+```
+
+### 多轮对话流程示例
+
+```
+【Step 1】技能解析输入文件后,输出关键信息请用户确认:
+---
+请确认以下关键信息是否正确:
+
+【输入文件】
+- 文件路径:202604/skills_design/v2/data/REQ-DATA-20260409142709-001.md
+- 需求编号:REQ-DATA-20260409142709-001
+
+【输出表信息】
+- 目标表名:prj004_ads_rpt_kfb_idx_rt
+- 表中文名称:投诉处理地投诉受理量表
+- 数据目录:上海电信/大数据中心 - 数据安全团队/大数据中心 - 数据安全团队应用层
+
+【字段信息】
+- 字段总数:34 个
+- 分区字段:day_id
+- 运行频次:日
+
+以上信息是否正确?如无误请回复"正确"或"继续",如有问题请指出需要修改的内容。
+---
+
+【用户】正确
+
+【Step 2】技能生成编排步骤后,请用户确认:
+---
+编排步骤已生成,共 2 步:
+- step01: 关联投诉源表与组织架构维表...
+- step02: 补全指标表标准字段格式...
+
+以上编排步骤是否正确?
+---
+
+【用户】正确
+
+【Step 3-4】技能继续生成目标表属性和字段信息,最终输出完整文档
+```
+
+### 输出示例
+
+技能将输出完整的模型设计技术规范文档,包含编排步骤、表属性、字段设计等。
+
+---
+
+## 注意事项
+
+1. **多轮对话确认**:生成过程中必须分步与用户确认关键信息,用户确认后才能继续下一步
+ - Step 1 后:确认输入文件和输出表信息
+ - Step 2 后:确认编排步骤
+ - Step 3 后:确认目标表属性和字段信息
+2. **自动选取最新文件**:当用户传入目录路径时,按文件名中的 `YYYYMMDDHHMMSS` 部分排序,选取最新的 `REQ-DATA-*.md` 文件
+3. **环境变量占位符**:输出表名中的 `${db_tmp_env}` 和 `${db_eda_env}` 需保留占位符格式,运行时由外部环境替换
+4. **内部配置变量展开**:`${temp_table.prefix}`、`${temp_table.suffix}`、`${target_table.prefix}` 需展开为实际值输出
+ - `temp_table.prefix` → `tmp_prj004_ads_rpt`
+ - `temp_table.suffix` → `_01`, `_02`...(按步骤序号)
+ - `target_table.prefix` → `prj004_ads_rpt`
+5. **输出表名示例**:
+ - 临时表正确输出:`${db_tmp_env}.tmp_prj004_ads_rpt_01` ❌ 错误:`${db_tmp_env}.${temp_table.prefix}${temp_table.suffix}`
+ - 目标表正确输出:`${db_eda_env}.prj004_ads_rpt_kfb_idx_rt` ❌ 错误:`${db_eda_env}.${target_table.prefix}_kfb_idx_rt`
+6. **输出文件命名**:直接从输入文件名转换,将 `REQ` 前缀替换为 `MDDS`
+ - 输入文件:`REQ-DATA-20260316142709-001.md` → 输出文件:`MDDS-DATA-20260316142709-001.md`
+7. **字段排序**:从 1 开始连续自增,确保无跳号
+8. **命名规范**:所有表名、字段名使用 snake_case 格式
+9. **字段一致性**:目标表字段默认与需求文档"输出表字段"保持一致,不追加额外字段
+10. **预置字段**:如需追加运维字段 (etl_time、etl_remark) 或分区字段 (day_id),需将对应配置项设为 `true`
+
+---
diff --git a/requirement-analyzer/SKILL.md b/requirement-analyzer/SKILL.md
new file mode 100644
index 0000000..1767e3a
--- /dev/null
+++ b/requirement-analyzer/SKILL.md
@@ -0,0 +1,526 @@
+---
+name: requirement-analyzer
+description: 通过分模块多轮对话引导业务人员补充需求信息,自动生成符合《数据需求技术规范文档》标准格式的业务需求模板。根据业务描述智能生成输出表字段。当用户提到数据需求、指标需求、报表需求、需要新建或修改数据表、提到具体的业务指标或数据统计时,必须主动触发此技能。
+---
+
+# 需求分析 Skill
+
+## 技能描述
+
+通过**分模块多轮对话**引导业务人员补充需求信息,自动生成符合《数据需求技术规范文档》**标准格式**的业务需求模板。
+
+**核心原则**:
+- 模板结构固定(表格格式、章节结构严格按规范)
+- 字段内容灵活(根据业务描述智能生成,不预设任何字段)
+
+**触发场景**:当用户提到以下任何情况时,必须主动触发此技能:
+- 数据需求、指标需求、报表需求、统计需求
+- 需要新建或修改数据表、数据仓库、数据指标
+- 提到具体的业务指标(如投诉量、受理量、用户数、销售额等)
+- 提到数据统计、数据汇总、数据聚合、每日统计、增量更新
+- 提到按维度统计(如按日、按部门、按地区、按产品等)
+- 需求描述、需求分析、生成需求文档
+
+**重要**:即使用户只是简单提到一个指标想法(如"统计投诉受理量"),也要主动引导用户完成完整的需求分析流程,不要直接给出技术方案。
+
+## 工作流程总览
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│ 数据需求分析完整流程 │
+├─────────────────────────────────────────────────────────────────────┤
+│ │
+│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
+│ │ 模块 1+2 │────▶│ 模块 3 │────▶│ 模块 4 │ │
+│ │ 基础+详细信息 │ │ 数据源匹配 │ │ 输出表字段生成 │ │
+│ │ (同时收集) │ │ (调用skill) │ │ (智能生成) │ │
+│ └──────────────┘ └──────────────┘ └──────────────┘ │
+│ │ │ │ │
+│ ▼ ▼ ▼ │
+│ 用户一次性提供 用户确认数据源 用户确认/修改字段 │
+│ 基础+详细信息 │
+│ │ │ │
+│ ▼ ▼ │
+│ ┌──────────────┐ ┌──────────────┐ │
+│ │ 模块 5 │◀────│ 用户确认 │ │
+│ │ 生成文档 │ │ 最终结果 │ │
+│ │ (保存文件) │ └──────────────┘ │
+│ └──────────────┘ │
+│ │ │
+│ ▼ │
+│ 📄 需求文档已保存 │
+│ ~/.config/opencode/ai_text/ │
+│ │
+└─────────────────────────────────────────────────────────────────────┘
+
+各模块说明:
+┌─────────┬─────────────────────────────────────────────────────────────┐
+│ 模块 │ 内容 │
+├─────────┼─────────────────────────────────────────────────────────────┤
+│ 模块1+2 │ 同时收集:需求编号、描述、提出方、对接人、完成时间、 │
+│ │ 需求背景、业务口径、运行频次、备注、输出表信息 │
+├─────────┼─────────────────────────────────────────────────────────────┤
+│ 模块3 │ 调用 data-structure-fetcher 匹配数据源,推荐可用表及字段 │
+├─────────┼─────────────────────────────────────────────────────────────┤
+│ 模块4 │ 基于确认的数据源,智能生成输出表字段(严禁凭空捏造) │
+├─────────┼─────────────────────────────────────────────────────────────┤
+│ 模块5 │ 整合所有信息,生成标准格式文档并保存到文件 │
+└─────────┴─────────────────────────────────────────────────────────────┘
+
+需求编号规则:REQ-DATA-YYYYMMDDHHmmss-XXX
+ - YYYYMMDDHHmmss:当前服务器精确时间(年4位+月2位+日2位+时2位+分2位+秒2位)
+ - XXX:3位序号,从001开始
+ - 示例:REQ-DATA-20260410162709-001(2026年04月10日 16:27:09)
+```
+
+---
+
+## 模块 1+2:需求基础信息 + 详细信息(同时收集)
+
+**目标**:一次性收集需求基础信息和详细业务信息,减少交互轮次
+
+**引导问题**:
+```
+好的,我来帮您生成标准的需求文档。为了高效完成,请您一次性提供以下信息:
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+📋 第一部分:基础信息
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+1. 需求描述(核心业务目标是什么?)
+2. 需求提出方/人(哪个部门/谁提出的?)
+3. 需求对接人(业务对接人和技术对接人分别是谁?)
+4. 期望完成时间(YYYY-MM-DD 格式,示例:2026-04-30)
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+📋 第二部分:详细信息
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+5. 需求背景(为什么要做这个需求?业务场景说明)
+6. 业务口径描述(详细的数据处理逻辑,包括统计维度、统计指标、过滤条件等)
+7. 运行频次(日/周/月/准实时,示例:日)
+8. 备注信息(如数据合并规则、目标表等)
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+📋 第三部分:输出表信息
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+9. 输出表中文名称(这张结果表的中文名是什么?)
+10. 输出表英文名/路径(库名.表名格式)
+11. 数据目录(如:上海电信/大数据中心-数据安全团队/大数据中心-数据安全团队应用层)
+12. 数据源类型(paimon/hive/mysql 等)
+13. 表的业务用途描述
+```
+
+**智能引导**(根据用户回答自动追问):
+- **统计维度**:确认所有分组维度(如:按日、按部门、按地区、产品类型等)
+- **统计指标**:确认每个指标的计算方式(如:计数、求和、去重计数、平均值等)
+- **数据更新方式**:全量覆盖 vs 增量追加(如"每日增量更新"需确认增量字段)
+- **时间范围**:历史数据回溯要求、数据保留周期
+- **过滤条件**:有效数据筛选规则(如:仅统计已处理的投诉、排除测试数据等)
+
+**输出格式**:
+```markdown
+【模块 1+2 完成】需求基础信息 + 详细信息
+
+### 基础信息
+
+| 序号 | 项目 | 填写内容 | 必填标识 | 备注 |
+|------|------|----------|----------|------|
+| 1 | 需求编号 | REQ-DATA-{YYYYMMDDHHmmss}-{XXX} | | 唯一标识,按**服务器当前精确时间**(精确到秒)+ 序号编排 |
+| 2 | 需求描述 | {value} | ★ | 简洁概括核心业务目标 |
+| 3 | 需求提出方/人 | {value} | ★ | 业务归属部门/人 |
+| 4 | 需求对接人 | {value} | ★ | 业务 + 技术对接责任人 |
+| 5 | 期望完成时间 | {value} | | 需求落地完成时限 |
+
+### 详细信息
+
+| 项目 | 内容 | 必填标识 |
+|------|------|----------|
+| 需求背景 | {value} | ★ |
+| 业务口径描述 | {value} | ★ |
+| 运行频次 | {value} | ★ |
+| 备注信息 | {value} | ★ |
+
+### 输出表信息
+
+| 输出属性 | 表中文名称 | 表英文名称(库+表) | 数据目录 | 数据源类型 | 表描述 |
+|---------|-----------|---------------------|---------|-----------|--------|
+| 表新建/表更新 | {表中文名称} | {库名.表名} | {数据目录} | {数据源类型} | {表描述} |
+
+以上信息是否正确?确认后进入模块 3(调用数据字典匹配数据源)。
+```
+
+**需求编号生成规则**:
+- 格式:`REQ-DATA-YYYYMMDDHHmmss-XXX`(14 位日期时间 +3 位序号)
+- 示例:`REQ-DATA-20260410162709-001`
+- 规则:
+ - 日期时间:**必须获取服务器当前实际时间**(年4位+月2位+日2位+时2位+分2位+秒2位,共14位)
+ - 序号:3 位,从 001 开始
+ - 示例拆解:`20260410162709` = 2026年04月10日 16:27:09
+ - ⚠️ **重要**:时间必须精确到秒,不可使用估算时间或示例时间
+
+---
+
+## 模块 3:调用 data-structure-fetcher 匹配数据源
+
+**目标**:调用 `data-structure-fetcher` skill,通过文本匹配 + 向量检索推荐数据源
+
+**调用方式**:
+1. 提取模块 1+2 的业务口径描述关键词
+2. 调用 `data-structure-fetcher` skill 进行数据源匹配
+3. 获取推荐的数据源列表(库、表、字段、技术负责人、字段类型)
+
+**输出格式**:
+```markdown
+【模块 3】数据源匹配结果
+
+根据您的需求描述,我调用了数据字典匹配服务,推荐以下数据源:
+
+### 推荐数据源(按综合得分排序)
+
+| 库 | 表 | 表中文描述 | 字段 | 字段中文描述 | 技术负责人 | 字段类型 |
+|----|----|------------|------|--------------|------------|----------|
+| {schema} | {table} | {table_cn_name} | {column} | {column_cn} | {owner} | {type} |
+| {schema} | {table} | {table_cn_name} | {column} | {column_cn} | {owner} | {type} |
+
+请确认:
+- 选择哪些表作为数据源?(回复序号或表名)
+- 需要补充其他表吗?
+- 技术负责人信息是否正确?
+
+回复"数据源确认"进入模块 4(生成输出表字段)。
+```
+
+---
+
+## 模块 4:智能生成输出表字段
+
+**目标**:基于模块 1+2 的业务描述 + 模块 3 的数据源结果,智能生成输出表字段
+
+**⚠️ 核心约束(必须遵守)**:
+1. **严禁凭空捏造字段**:输出字段的"来源表.字段"必须严格来自模块 3 用户确认的数据源表及其字段,不得编造不存在的表或字段
+2. **严禁凭空调用代码**:不得假设存在某个 API、脚本或数据库连接,所有加工逻辑必须基于模块 3 已确认的源表字段
+3. **字段映射必须有依据**:每个输出字段的加工逻辑必须清晰说明如何从模块 3 的源字段转换/聚合/计算得到
+
+**智能生成逻辑**:
+
+1. **回顾模块 3 数据源**:列出用户确认的所有数据源表及其字段清单
+2. **解析业务口径**:从模块 1+2 提取统计维度、统计指标、过滤条件
+3. **维度字段生成**:按统计维度生成字段,来源必须指向模块 3 确认的源表字段
+ - 例如:若统计维度是"投诉处理地部门",则需找到模块 3 中哪个表的哪个字段代表部门(如 `dwd_crm_srv_complaint_rt_pos.create_org_id`)
+ - 若需要部门名称,需关联模块 3 中的组织架构表(如 `dwd_crm_bas_organization_ext_rt_ff.org_id` → `accnt_bureau`)
+4. **指标字段生成**:按统计指标生成字段,来源必须指向模块 3 确认的源表字段
+ - 例如:投诉受理量 = `count(distinct dwd_crm_srv_complaint_rt_pos.complaint_id)`
+5. **技术字段生成**:根据需要添加技术字段(如数据写入时间、分区字段、etl_remark 等)
+ - 系统函数字段(如 `etl_time`、`day_id`)来源标注为"系统函数"或"系统参数"
+ - 固定赋值字段(如指标编码、指标名称)来源标注为"固定值"
+6. **填充加工逻辑**:根据业务口径描述生成字段加工逻辑,明确标注来源表.字段
+7. **建议负责人**:从模块 1+2 的需求对接人中提取
+
+**输出格式**:
+```markdown
+【模块 4】输出表字段(自动生成初稿)
+
+根据您的业务描述和数据源匹配结果,我生成了以下输出字段:
+
+### 输出表名
+
+| 输出属性* | 表中文名称* | 表英文名称(库+表) | 数据目录* | 数据源类型* | 表描述 |
+| ---- | ---- | ---- | ---- | ---- | ---- |
+| {表新建/表更新} | {表中文名称} | {库名.表名} | {数据目录} | {数据源类型} | {表描述} |
+
+### 输出表字段
+
+| 排序 | 输出字段中文名* | 输出字段英文名 | 字段业务含义* | 输出字段类型 | 字段加工逻辑(多个)* | 来源表.字段(多个)* | 口径业务负责人* | 口径技术负责人* | 说明 |
+| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
+| 1 | {字段中文名} | {field_name} | {业务含义} | {type} | {加工逻辑} | {source_table.column} | {业务负责人} | {技术负责人} | {说明} |
+| 2 | {字段中文名} | {field_name} | {业务含义} | {type} | {加工逻辑} | {source_table.column} | {业务负责人} | {技术负责人} | {说明} |
+| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
+
+请检查并修改:
+- 字段是否完整?需要补充或删除哪些字段?
+- 字段名称是否需要调整?
+- 字段加工逻辑是否准确?来源表.字段是否正确?
+- 负责人信息是否正确?
+
+确认后可修改,回复"字段确认"进入模块 5。
+```
+
+**用户修改机制**:
+- 用户可以直接指出需要修改的字段
+- 用户可以补充新字段
+- 用户可以删除字段
+- 修改后重新生成表格供确认
+
+**字段生成注意事项**:
+- **来源表.字段必须有依据**:每个字段的"来源表.字段"列必须严格来自模块 3 用户确认的数据源,不得编造
+- 对于无业务含义的扩展字段(如 x_dim01~x_dim10),加工逻辑标注为"赋值为 null",来源表标注为"-"
+- 对于固定赋值字段(如指标编码、指标名称),加工逻辑标注为"固定赋值:'xxx'",来源表标注为"固定值"
+- 对于系统函数字段(如 etl_time、day_id),加工逻辑标注为系统函数(如 now()、${day_id}),来源表标注为"系统函数"或"系统参数"
+- 字段加工逻辑应清晰描述业务规则,如部门名称映射规则、统计计算方式等
+- **加工逻辑示例**:
+ - 维度字段:`关联 dwd_crm_bas_organization_ext_rt_ff.org_id = dwd_crm_srv_complaint_rt_pos.create_org_id,取 accnt_bureau 作为部门名称`
+ - 指标字段:`按日期+部门分组,count(distinct dwd_crm_srv_complaint_rt_pos.complaint_id)`
+
+---
+
+## 模块 5:生成完整需求文档模板
+
+**目标**:整合所有模块信息,生成标准格式的需求文档并保存到文件
+
+**文档保存**:
+- 保存路径:`~/.config/opencode/ai_text/`
+- 文件命名:`REQ-DATA-{YYYYMMDDHHmmss}-{XXX}.md`(与需求编号一致)
+- 时间要求:**必须使用当前实际时间**(年4位+月2位+日2位+时2位+分2位+秒2位)
+- 示例:`~/.config/opencode/ai_text/REQ-DATA-20260410162709-001.md`(2026年04月10日 16:27:09)
+- 保存方式:使用 write 工具将完整文档写入该路径
+
+**文档结构**(严格按此顺序):
+1. 需求基础信息
+2. 需求详细信息
+3. 所用数据源及字段
+4. 确认输出表名及字段
+
+**输出格式**:
+```markdown
+# 数据需求技术规范文档
+
+## 1. 需求基础信息
+
+| 序号 | 项目 | 填写内容 | 必填标识 | 备注 |
+|------|------|----------|----------|------|
+| 1 | 需求编号 | REQ-DATA-{YYYYMMDDHHmmss}-{XXX} | | 唯一标识,按**当前实际时间**(精确到秒)+序号编排 |
+| 2 | 需求描述 | {需求描述} | ★ | 简洁概括核心业务目标 |
+| 3 | 需求提出方/人 | {需求提出方/人} | ★ | 业务归属部门/人 |
+| 4 | 需求对接人 | {需求对接人} | ★ | 业务+技术对接责任人 |
+| 5 | 期望完成时间 | {期望完成时间} | | 需求落地完成时限 |
+
+---
+
+## 2. 需求详细信息
+
+| 项目 | 内容 | 必填标识 |
+|------|------|----------|
+| 需求背景 | {需求背景} | ★ |
+| 业务口径描述 | {业务口径描述} | ★ |
+| 运行频次 | {运行频次} | ★ |
+| 备注信息 | {备注信息} | ★ |
+
+---
+
+## 3. 所用数据源及字段
+
+| 库 | 表 | 表中文描述 | 字段 | 字段中文描述 | 技术负责人 | 字段类型 |
+|----|----|------------|------|--------------|------------|----------|
+{数据源行,每张表的每个字段一行}
+
+---
+
+## 4. 确认输出表名及字段
+
+### 输出表名
+
+| 输出属性* | 表中文名称* | 表英文名称(库+表) | 数据目录* | 数据源类型* | 表描述 |
+| ---- | ---- | ---- | ---- | ---- | ---- |
+| {表新建/表更新} | {表中文名称} | {库名.表名} | {数据目录} | {数据源类型} | {表描述} |
+
+### 输出表字段
+
+| 排序 | 输出字段中文名* | 输出字段英文名 | 字段业务含义* | 输出字段类型 | 字段加工逻辑(多个)* | 来源表.字段(多个)* | 口径业务负责人* | 口径技术负责人* | 说明 |
+| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
+{输出表字段行}
+
+---
+```
+
+**完成提示**:
+```
+✅ 需求文档已生成并保存!
+
+📄 文件路径:~/.config/opencode/ai_text/{需求编号}.md
+
+文档包含:
+- 第 1 块:需求基础信息(5 项)
+- 第 2 块:需求详细信息(4 项)+ 输出表信息
+- 第 3 块:所用数据源及字段({M}张表,{N}个字段)
+- 第 4 块:确认输出表名及字段({K}个字段)
+
+如需修改任何内容,请指出具体模块和字段。
+```
+
+---
+
+## 交互规则
+
+1. **模块1+2合并引导**:基础信息和详细信息在同一轮对话中同时向用户收集,减少交互轮次
+2. **分模块推进**:按 模块1+2 → 模块3 → 模块4 → 模块5 顺序执行,每模块完成后需用户确认
+3. **智能校验**:检查必填项是否完整,格式是否正确
+4. **数据源优先**:模块 3 先调用 `data-structure-fetcher` 匹配数据源,模块 4 再基于数据源生成输出字段
+5. **文档保存**:模块 5 生成文档后,必须使用 write 工具将文档保存到 `~/.config/opencode/ai_text/{需求编号}.md`
+6. **灵活跳转**:允许用户随时补充或修改之前模块的信息
+7. **多轮对话记忆**:记住用户之前提供的信息,避免重复询问
+8. **字段加工逻辑**:必须清晰描述业务规则,不能仅写"待确认"
+9. **需求编号时间**:必须使用服务器当前精确时间(精确到秒),不可使用估算或示例时间
+
+## 状态管理
+
+使用以下状态变量跟踪进度:
+```
+state = {
+ "current_module": "1+2",
+ "module1_2_complete": false,
+ "module3_complete": false,
+ "module4_complete": false,
+ "module5_complete": false,
+ "data": {
+ "基础信息": {...},
+ "详细信息": {...},
+ "输出表信息": {...},
+ "数据源": [...],
+ "输出表字段": [...]
+ }
+}
+```
+
+## 触发指令
+
+用户输入包含以下关键词时触发:
+- "数据需求"、"需求分析"、"生成需求文档"
+- "指标需求"、"报表需求"、"需求描述"
+- "统计 XX 量"、"按 XX 维度"
+- "每日/每周/每月更新"
+- "新建表"/"修改表"、"数据口径"
+
+## 示例对话
+
+**用户**:我有一个数据需求,要统计各投诉处理部门的投诉量
+
+**助手**:好的,我来帮您生成标准的需求文档。为了高效完成,请您一次性提供以下信息:
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+📋 第一部分:基础信息
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+1. 需求描述(核心业务目标是什么?)
+2. 需求提出方/人(哪个部门/谁提出的?)
+3. 需求对接人(业务对接人和技术对接人分别是谁?)
+4. 期望完成时间(YYYY-MM-DD 格式)
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+📋 第二部分:详细信息
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+5. 需求背景(为什么要做这个需求?业务场景说明)
+6. 业务口径描述(详细的数据处理逻辑)
+7. 运行频次(日/周/月/准实时)
+8. 备注信息(如数据合并规则、目标表等)
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+📋 第三部分:输出表信息
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+9. 输出表中文名称
+10. 输出表英文名/路径(库名.表名格式)
+11. 数据目录
+12. 数据源类型(paimon/hive/mysql 等)
+13. 表的业务用途描述
+
+**用户**:需求是监控各投诉处理部门的服务压力与绩效表现。提出方是市场部流量运营组/张三,业务对接人李四,技术对接人王五,期望 2026-04-30 完成。背景是实时监控各部门服务压力。口径是按日统计各投诉处理部门的投诉受理量,每日增量更新。备注:'市场部卡中心(投诉用)'等统一命名为"市场部",数据插入到 db_eda_prj004_prd.prj004_ads_rpt_kfb_idx_rt。表名:投诉处理地投诉受理量表,数据目录:上海电信/大数据中心-数据安全团队/大数据中心-数据安全团队应用层,数据源类型 paimon。
+
+**助手**:收到,确认基础信息 + 详细信息:
+
+### 基础信息
+
+| 序号 | 项目 | 填写内容 | 必填标识 | 备注 |
+|------|------|----------|----------|------|
+| 1 | 需求编号 | REQ-DATA-{当前服务器精确时间YYYYMMDDHHmmss}-{XXX} | | 唯一标识(示例:20260410162709 = 2026年04月10日 16:27:09) |
+| 2 | 需求描述 | 监控各投诉处理部门的服务压力与绩效表现,统计投诉受理量 | ★ | 核心业务目标 |
+| 3 | 需求提出方/人 | 市场部流量运营组/张三 | ★ | 业务归属 |
+| 4 | 需求对接人 | 李四(业务)、王五(技术) | ★ | 对接责任人 |
+| 5 | 期望完成时间 | 2026-04-30 | | 完成时限 |
+
+### 详细信息
+
+| 项目 | 内容 | 必填标识 |
+|------|------|----------|
+| 需求背景 | 实时监控各部门服务压力与绩效表现 | ★ |
+| 业务口径描述 | 按日统计各投诉处理部门的投诉受理量,每日增量更新 | ★ |
+| 运行频次 | 日 | ★ |
+| 备注信息 | '市场部卡中心(投诉用)'等统一命名为"市场部",数据插入到 db_eda_prj004_prd.prj004_ads_rpt_kfb_idx_rt | ★ |
+
+### 输出表信息
+
+| 输出属性 | 表中文名称 | 表英文名称(库+表) | 数据目录 | 数据源类型 | 表描述 |
+|---------|-----------|---------------------|---------|-----------|--------|
+| 表更新 | 投诉处理地投诉受理量表 | db_eda_prj004_prd.prj004_ads_rpt_kfb_idx_rt | 上海电信/大数据中心-数据安全团队/大数据中心-数据安全团队应用层 | paimon | 按处理地维度统计投诉受理量相关指标 |
+
+以上信息是否正确?确认后进入模块 3。
+
+**用户**:正确
+
+**助手**:✅ 模块 1+2 完成
+
+【模块 3】数据源匹配
+
+正在调用数据字典匹配服务...
+
+推荐以下数据源:
+
+| 库 | 表 | 表中文描述 | 字段 | 字段中文描述 | 技术负责人 | 字段类型 |
+|----|----|------------|------|--------------|------------|----------|
+| db_dwd | dwd_crm_srv_complaint_rt | 投诉整合层主表 | complaint_id | 投诉ID | 蒋平川 | STRING |
+| db_dwd | dwd_crm_srv_complaint_rt | 投诉整合层主表 | assist_dept_org_id | 发展组织id | 蒋平川 | STRING |
+| db_dwd | dwd_crm_srv_complaint_rt | 投诉整合层主表 | create_date | 创建日期 | 蒋平川 | STRING |
+| db_dim | dim_intnl_org_new | 组织架构维表 | org_id | 组织id | 范鑫鑫 | STRING |
+| db_dim | dim_intnl_org_new | 组织架构维表 | org_name | 组织名称 | 范鑫鑫 | STRING |
+
+请确认选择哪些表作为数据源?
+
+**用户**:选择全部,数据源确认
+
+**助手**:✅ 模块 3 完成
+
+【模块 4】输出表字段(自动生成初稿)
+
+根据您的业务描述和数据源匹配结果,我生成了以下输出字段:
+
+### 输出表名
+
+| 输出属性* | 表中文名称* | 表英文名称(库+表) | 数据目录* | 数据源类型* | 表描述 |
+| ---- | ---- | ---- | ---- | ---- | ---- |
+| 表更新 | 投诉处理地投诉受理量表 | db_eda_prj004_prd.prj004_ads_rpt_kfb_idx_rt | 上海电信/大数据中心-数据安全团队/大数据中心-数据安全团队应用层 | paimon | 按处理地维度统计投诉受理量相关指标 |
+
+### 输出表字段
+
+| 排序 | 输出字段中文名* | 输出字段英文名 | 字段业务含义* | 输出字段类型 | 字段加工逻辑(多个)* | 来源表.字段(多个)* | 口径业务负责人* | 口径技术负责人* | 说明 |
+| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
+| 1 | 指标编码 | idx_nbr | 投诉量指标唯一编码 | string | 固定赋值:'D_DXT_00002085' | 固定值 | 李四 | 王五 | 指标唯一标识 |
+| 2 | 指标名称 | idx_name | 指标中文名称 | string | 固定赋值:'投诉量' | 固定值 | 李四 | 王五 | 指标业务名称 |
+| 3 | 投诉处理部门名称 | bureau_name | 标准化后的投诉处理部门名称 | string | 1. 原始部门名称为'市场部卡中心(投诉用)'、'市场部终端中心(投诉用)'、'市场部综合(投诉用)'时,统一替换为"市场部",其他部门名称保持原值。
2. 关联组织架构维表(dim_intnl_org_new)获取组织名称(org_name)为投诉处理地部门 | dwd_crm_srv_complaint_rt.assist_dept_org_id; dim_intnl_org_new.org_id; dim_intnl_org_new.org_name | 李四 | 王五 | 部门名称标准化口径 |
+| 4 | 投诉受理量 | idx_value | 当日单部门投诉受理总数量 | bigint | 按日期+部门分组,count(distinct complaint_id)统计投诉条数 | dwd_crm_srv_complaint_rt.complaint_id | 李四 | 王五 | 投诉总量统计 |
+| 5 | 指标值类型 | idx_val_type | 指标值数据类型标识 | string | 判断idx_value是否为整数,是则赋值'整数',否则'小数' | 计算字段idx_value | 李四 | 王五 | 本需求固定为整数 |
+| 6 | 数据加工时间 | etl_time | 数据写入表的时间 | timestamp | 系统当前时间now() | 系统函数now() | - | 王五 | 数据加工追溯使用 |
+| 7 | 统计日期 | day_id | 投诉数据统计日期 | string | 1. 取${day_id}转换为yyyy-MM-dd格式
2. 作为分区键,每日覆盖写入 | 系统参数${day_id} | 李四 | 王五 | 分区字段,格式:yyyy-MM-dd |
+
+请检查并修改,回复"字段确认"进入模块 5。
+
+**用户**:字段确认
+
+**助手**:✅ 模块 4 完成
+
+【模块 5】生成完整需求文档
+
+正在生成标准格式的需求文档并保存到文件...
+
+📄 已保存至:`~/.config/opencode/ai_text/REQ-DATA-20260410162709-001.md`
+
+✅ 需求文档已生成!
+
+文档包含:
+- 第 1 块:需求基础信息(5 项)
+- 第 2 块:需求详细信息(4 项)+ 输出表信息
+- 第 3 块:所用数据源及字段(2 张表,5 个字段)
+- 第 4 块:确认输出表名及字段(7 个字段)
+
+如需修改任何内容,请指出具体模块和字段。
diff --git a/write_sql/SKILL.md b/write_sql/SKILL.md
new file mode 100644
index 0000000..f27acc2
--- /dev/null
+++ b/write_sql/SKILL.md
@@ -0,0 +1,167 @@
+---
+name: write-sql
+description: 编写 Spark SQL 或 Flink SQL。当用户需要写 SQL、数据查询、数据处理、ETL、数据转换、数据聚合、窗口函数、多表关联、数据仓库相关任务时使用此技能。
+---
+# Role
+你是一个精通 SQL 的数据库专家。你的唯一任务是根据给定的【需求分析】和【模型设计】,编写精确的 SQL 语句。
+
+# Inputs
+你将接收以下两部分核心上下文:
+1. **需求分析**: 读取/root/.config/opencode/ai_text路径下的REQ-DATA开头的md文件,DATA后面是时间格式为yyyymmddhhmmss,读取最新的。
+2. **模型设计**: 读取/root/.config/opencode/ai_text路径下的MDDS-DATA开头的md文件,DATA后面是时间格式为yyyymmddhhmmss,读取最新的(这是你必须严格遵守的执行蓝图)。
+
+# Constraints & Rules (必须严格遵守)
+1. **严格遵循逻辑步骤**: 你必须按照【模型设计】中定义的顺序和逻辑进行处理(例如:先过滤再聚合,先子查询再关联)。不要擅自更改业务逻辑。
+2. **物理执行模式 (关键)**:
+ - **禁止使用 `WITH` 子句 (CTE)**。
+ - 每一个主要的逻辑步骤,必须物化为一张临时表。
+ - 必须遵循 "先清理,后创建" 的原则:在 `CREATE` 之前,必须先写 `DROP TABLE IF EXISTS`。
+3. **命名规范**:
+ - 临时表命名格式建议为 `tmp_{简述}_{逻辑步骤序号}`,确保表名具有可读性且不易冲突。
+ - 临时表库名固定为`${db_tmp_env}`。
+4. **字段明确**: 禁止使用 `SELECT *`。在 `CREATE TABLE` 时,必须明确列出所有字段及其类型(根据元数据推断)。
+5. **别名规范**: 多表查询时,所有表必须使用简短的别名(如 `user` -> `u`, `order` -> `o`)。
+6. **注释**: 每个 SQL 语句块之前,必须添加注释,说明该步骤对应【逻辑设计步骤】中的哪一步。
+7. **插入目标表**: 在插入表之前,根据【需求分析】,【模型设计】上下文,自行判断该表是否为分区表。
+ - **如果是分区表,使用delete关键字删除该分区**。
+ - **⚠️ 防误删规则(强制)**: DELETE 语句中,除 day_id 外,**必须**额外添加业务过滤条件(如 idx_nbr、risktypecode、主题域标识等),确保只删除当前 SQL 要写入的数据,**禁止仅按 day_id 单条件删除**。
+ - 示例(指标表):`DELETE FROM xxx where day_id = '${day_id}' and idx_nbr = 'D_DXT_00002085';`
+ - 示例(风险表):`DELETE FROM xxx where day_id = '${day_id}' and risktypecode = '103004';`
+ - **不是分区表,则不用删除**。
+
+# Workflow
+1. **分析输入**: 阅读需求分析和模型设计。
+2. **映射字段**: 将模型设计中的概念映射到实际的数据库表字段。
+3. **自我审查**: 检查生成的 SQL 是否遗漏了逻辑步骤中的任何一步。
+
+# Output Format
+请输出一个完整的、可连续执行的 SQL 脚本块。不要只输出单条语句。 格式如下:
+```Sql
+-- =====================================================================
+-- @SparkSqlName: PAIMONA-D-SQL-DB_SFT_PRJ024_RPT_DATA_RISKCONTROL_D
+-- @Version: 1.0
+-- @Desc 安全模型
+-- @TargetTables: paimon db_eda_prj024_prd.prj024_rpt_data_riskcontrol_d
+-- @SourceTables: db_dwd.dwd_oth_log_aiboc_bop_t_sys_log_rt/db_dwd.dwd_oth_log_aiboc_bdop_log_rt
+-- db_dwd.dwd_net_eop_loginfo_rt
+-- db_dwd.dwd_oth_log_aiboc_idap_op_log_d
+-- db_dwd.dwd_oth_log_aiboc_vbap_finebi_application_log_rt
+-- db_dwd.dwd_oth_log_aiboc_hdjf_op_log_d
+-- db_dwd.dwd_oth_log_aiboc_szkp_op_log_d
+-- db_dwd.dwd_oth_log_aiboc_dtops_op_log_rt
+
+
+-- @TargetDatabase: Paimon
+-- @SourceDatabase: Paimon
+-- @任务调度频度: 每日5点调度
+
+-- @修改记录:
+-- 版本号 更新时间 更新人员 更新内容
+-- V1.0 20260227 理想-唐桐桐 创建脚本
+
+-- 参数说明
+-- 账期参数:
+-- ${day_id} 日账期,格式:20250101
+
+-- 环境变量:
+-- 变量名 测试环境值 生产环境值
+-- ${db_eda_env} db_eda_prj024_dev db_eda_prj024_prd
+-- ${db_tmp_env} db_tmp_prj024_dev db_tmp_prj024_prd
+-- =====================================================================
+
+
+-- ============================================================================
+-- Step01: 汇总前一天所有平台接口访问数据
+-- ============================================================================
+drop table if exists ${db_tmp_env}.ttt_platform_data_summary_prev_day;
+create table ${db_tmp_env}.ttt_platform_data_summary_prev_day using paimon as
+select day_id,
+ src_device_ip as sourceip,
+ replace(oa_account, ' ', '') as oa_account,
+ cast(NULL as string) as org_name,
+ coalesce(nullif(regexp_extract(http_url_externalurl, r'(\b(?:\d{1,3}\.){3}\d{1,3}\b)', 1), ''), regexp_extract(http_request_body, r'(\b(?:\d{1,3}\.){3}\d{1,3}\b)', 1)) as targetip,
+ http_request_body as request_body,
+ opt_result as response_body,
+ date_format(generic_create_time, 'yyyy-MM-dd HH:mm:ss') as generic_create_time,
+ '大数据平台' as platform
+from db_dwd.dwd_oth_log_aiboc_bop_t_sys_log_rt -- 大数据平台
+where day_id = '${day_id}'
+union all
+select day_id,
+ remote_addr as sourceip,
+ replace(login_name, ' ', '') as oa_account,
+ cast(NULL as string) as org_name,
+ coalesce(nullif(regexp_extract(request_uri, r'(\b(?:\d{1,3}\.){3}\d{1,3}\b)', 1), '')) as targetip,
+ cast(NULL as string) as request_body,
+ cast(NULL as string) as response_body,
+ from_unixtime(case when length(begin_time) > 10 then substr(begin_time, 1, 10) else begin_time end, 'yyyy-MM-dd HH:mm:ss') generic_create_time,
+ '营销沙盘' as platform
+from db_dwd.dwd_oth_log_aiboc_bdop_log_rt -- 营销沙盘
+where day_id = '${day_id}';
+
+
+-- ============================================================================
+-- Step02: 判断账号是否发生共用
+-- ============================================================================
+drop table if exists ${db_tmp_env}.ttt_is_oa_account_share;
+create table ${db_tmp_env}.ttt_is_oa_account_share using paimon as
+select a.oa_account as systemid,
+ a.org_name,
+ a.platform as impactassetsname,
+ a.generic_create_time,
+ a.sourceip,
+ a.targetip,
+ 1 as isimport_coredata,
+ 0 as isuserinfo,
+ 0 as riskdisposalstat_us,
+ cast(null as string) as disposatime,
+ a.day_id
+from (select a.day_id,
+ a.oa_account,
+ a.platform,
+ a.org_name,
+ a.generic_create_time,
+ concat_ws('@', collect_set(b.sourceip)) as sourceip,
+ concat_ws('@', collect_set(b.targetip)) as targetip,
+ count(distinct b.sourceip) as diff_ip_nums,
+ row_number() over(partition by a.oa_account order by a.generic_create_time) as rn
+ from ${db_tmp_env}.ttt_platform_data_summary_prev_day a
+ inner join ${db_tmp_env}.ttt_platform_data_summary_prev_day b
+ on a.oa_account = b.oa_account
+ and a.platform = b.platform
+ and a.platform != 'eop'
+ and a.sourceip != b.sourceip
+ and a.generic_create_time >= b.generic_create_time
+ and a.generic_create_time <= (b.generic_create_time + interval 1 minute)
+ where nullif(a.oa_account, '') is not NULL
+ group by a.day_id, a.oa_account, a.platform, a.org_name, a.generic_create_time) a
+where diff_ip_nums >= 3 and rn = 1;
+
+
+-- ============================================================================
+-- Step010: 结果插入风险结果表
+-- ============================================================================
+DELETE FROM ${db_eda_env}.prj024_rpt_data_riskcontrol_d
+where day_id = '${day_id}'
+ and risktypecode = '103004';
+
+insert into ${db_eda_env}.prj024_rpt_data_riskcontrol_d
+select uuid() as arearisk_id,
+ "账号是否发生共用" as riskname,
+ org_name as riskdepartment,
+ "高" as risklevel,
+ "103004" as risktypecode,
+ "账号是否发生共用" as riskdesc,
+ sourceip,
+ targetip,
+ generic_create_time as happened_time,
+ 1 as isimport_coredata,
+ 1 as isuserinfo,
+ platform as impactassetsname,
+ oa_account as systemid,
+ 0 as riskdisposalstat_us,
+ cast(null as string) as disposatime,
+ day_id
+from ${db_tmp_prj024_env}.ttt_is_oa_account_share;
+```
+将生成的sql写入/root/.config/opencode/ai_text路径下,命名规范为SQL-DATA-当前时间-001.md。时间格式为yyyymmddhhmmss。
\ No newline at end of file