# Beisen Data Query

> 北森 HR 通用数据查询引擎。本 Skill 通过 beisen-cli staffservice 子命令集（sceneTool / searchFormTool / businessDataTool，以及 sceneToolMessageForCLI、menuSearch）实现自然语言到业务数据的 6 步查询流水线。当用户询问假期余额、考勤异常、下属信息、绩效情况、任职信息、组织架构等个人或团队业务数据时触发。本 Skill 是 beisen-employee-profile、beisen-attendance-leave、beisen-organization 三个业务域 Skill 的共享查询底层。

- Skill: `ahang1598/beisen-data-query` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add ahang1598/beisen-data-query`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ahang1598/beisen-data-query/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: ahang1598 (https://skillmd.com/u/ahang1598)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/ahang1598/beisen-data-query

---


# 员工数据查询

**CRITICAL — 开始前 MUST 读取 [../beisen-shared/SKILL.md](../beisen-shared/SKILL.md)**

> **CLI 调用方式**：本 Skill 中工具通过 `beisen-cli staffservice` 的子命令调用：
> - `beisen-cli staffservice employeeData sceneTool`
> - `beisen-cli staffservice employeeData searchFormTool --params '{"intentionId":"<id>"}'`
> - `beisen-cli staffservice employeeData businessDataTool --data '{"intentionId":"<id>","search":[...]}'`
> - `beisen-cli staffservice employeeData sceneToolMessageForCLI --params '{"intentionId":"<id>"}'`
>
> 下文流水线中以逻辑名 `SceneTool` / `SearchFormTool` / `BusinessDataTool` / `SceneToolMessage` 指代上述子命令。

**本 Skill 是 beisen-cli 所有 read-only 数据查询场景的统一入口。** 其他业务域 Skill（`beisen-employee-profile`、`beisen-attendance-leave`、`beisen-organization`）中的场景查询通过引用本 Skill 实现。

## 任务目标
- 本 Skill 用于：根据用户自然语言输入，识别数据查询意图，匹配查询场景，提取筛选参数，获取业务数据并智能总结为可读答案
- 能力包含：意图识别、场景匹配、参数提取、数据检索、智能总结、关联菜单展示
- 触发条件：用户询问个人/团队业务数据（如假期余额、考勤异常、下属信息、绩效情况等）

## 静默执行（硬性规则，适用于全部步骤）
**你输出的每个字用户都看得见，不存在"内部思考/过程说明"通道。**
- 意图判断、场景匹配、参数提取、数据查询、降级切换全部在内部静默完成，禁止写成任何文字。禁止示例（均为真实事故）："用户问XX，这是一个关于XX的查询，让我判断……""场景'XX'（intentionId: …）强命中""SearchFormTool 返回空字段列表，说明……""根据 data-query 的降级规则，需静默退出……""菜单搜索结果与XX无语义关联""按申请时间降序，取最新一条记录"
- 工具轮零文本：直接调用工具，调用前后不输出任何文字（"让我先读取相关技能指令并探测可用场景"等一律禁止）
- 面向用户的文字只允许出现在最终答案轮（或必要的追问/确认）

## 操作步骤

### 步骤一：判断意图类型
根据用户输入判断是否为数据查询意图。**数据查询意图必须具备明确的数据询问结构**，即包含以下特征之一及以上：
- 疑问词/疑问句式（"多少""有没有""是否""哪些"）
- 数量/余额/记录类诉求（"还剩""余额""记录"）
- 时间范围 + 指标（"本月考勤""今年的绩效"）
- 明确主体 + 指标组合（"李白的任职信息""我团队的工时"）

**询问结构以整句为单位判定**：整句必须是向系统求取数据的疑问或请求表达；若整句是名词性短语、标题或描述性文案，即使内部嵌有形似"主体+指标"的片段（如描述文案里的"我有这个视图权限"）或数量词字样，也不构成数据询问结构。

分类处理：
- **数据查询意图**（具备上述询问结构，如"我还有多少年假"、"李白本月是否有考勤异常"）→ 进入步骤二
- **非数据查询意图**：以下情况均不走本流程，**静默退出**：
  - 用户询问企业政策、功能入口位置、操作导航
  - **输入为裸名词、功能名式短语或疑似某个功能/页面/菜单的名称或描述性文本**（如"我的目标""日报"，或一段菜单描述文案）——即使其中出现"查询""视图""权限""数据"等字样，或嵌有第一人称、形似"主体+指标"的片段，只要整句不具备数据询问结构，就不是数据查询意图
- 多轮对话时，结合最近 10 条对话滚动判断意图，并将代词（他/她/那个人）和省略主语的表达替换为前文已出现的具体人名
- 静默退出时：不输出任何判断过程、解释说明或提示文案，交由 Agent 继续路由（菜单唤起或知识问答）

### 步骤二：匹配查询场景
1. 调用 `SceneTool` 获取租户已配置的查询场景列表：
```bash
beisen-cli staffservice employeeData sceneTool
```
```json
{
  "code": "200",
  "data": [
    {
      "intentionId": "场景意图ID",
      "scene": "场景指令",
      "sceneLabel": "场景名称",
      "description": "场景描述"
    }
  ]
}
```
2. 结合用户问题和`SceneTool`返回的 `sceneLabel`、`description` 判断是否命中。**命中标准为强命中，需同时满足两个条件**：
   - ①用户问题具有数据询问结构（见步骤一）；
   - ②该场景提供的数据能**直接回答**用户的问题。
   仅词面相似（用户输入中恰好出现与场景名/描述重叠的字样）不构成命中，缺任一条件均视为无场景命中。匹配比对是内部过程，**禁止在回答中输出场景清单、逐个排查分析或"让我看看/让我重新检查"式的推理文字**
3. 若命中多个场景且无法确定唯一匹配 → 输出简短追问让用户确认（如"你是想查考勤记录还是假期余额？"），用户确认后再继续
4. 若仅命中 1 个场景 → 直接使用
5. 若无场景强命中 → 说明当前租户不支持该项数据查询，**按"非数据查询意图"降级处理**：立即静默结束本流程，交由菜单唤起或知识问答处理（同步骤一）。此时不输出任何文案，包括但不限于"暂不支持查询XX""没有找到数据"、场景分析过程、自行编造的查询建议或菜单入口
6. 命中后，用 `intentionId` 调用 `SceneToolMessage` 获取输出要求和关联菜单：
```bash
beisen-cli staffservice employeeData sceneToolMessageForCLI --params '{"intentionId":"<id>"}'
```
```json
{
  "code": "200",
  "data": {
    "outputPromptWords": "输出要求",
    "menus": ["菜单ID1", "菜单ID2"]
  }
}
```

### 步骤三：获取搜索字段并提取筛选参数
1. **SearchFormTool 必须调用，严禁跳过**（真实事故：跳过本步骤、复用其他场景的 fieldName 导致查询返回错误数据）：用命中的 `intentionId` 调用 `SearchFormTool`，获取**本场景**支持筛选的字段：
```bash
beisen-cli staffservice employeeData searchFormTool --params '{"intentionId":"<id>"}'
```
```json
{
  "code": "200",
  "data": [
    {
      "fieldName": "字段编码",
      "fieldText": "字段显示名",
      "fieldDataType": "字段类型",
      "num": "字段序号",
      "dataSourceItems": [{"id1": "value1"}, {"id2": "value2"}],
    }
  ]
}
```
2. **前置检查（门控）**：检查返回字段中是否存在 `fieldDataType = "部门单选"` 的字段——
   - **存在**：本场景支持组织范围查询（场景 A/B/C 可用），可传 `businessParameters.userFindOrgType` 和部门字段 value → 进入第 4 点走 7 级决策表
   - **不存在**：本场景仅支持查本人（优先级 1）/权限范围（优先级 2）/指定人（优先级 3）。若用户问法属于以下组织范围查询（A/B/C/所在 类），**一律静默退出**，交由菜单唤起或知识问答处理，不输出任何文案、不降级为查指定人：

     | 用户问法类型 | 判定条件 | 示例 | 处理 |
     |------------|---------|------|------|
     | A 类 | 他人+范围词+无具体部门名 | "麦店长负责的部门的休假情况" | 静默退出 |
     | B 类 | 无具体人名+具体部门名 | "一体化产品部的休假情况" | 静默退出 |
     | C 类 | 他人+范围词+具体部门名 | "麦店长负责的一体化产品部休假" | 静默退出 |
     | 所在类 | 他人+所在+具体部门名 | "麦店长所在的一体化产品部休假" | 静默退出 |

     若用户问法仅涉及本人/权限范围/指定人（如"我的休假情况""麦店长的休假"），则正常进入第 3 点提取参数
3. 根据字段信息和用户问题提取筛选参数，详细提取规则见 [references/business-rules.md](references/business-rules.md) 的"参数提取规则"章节。**身份判定只依据用户原文的显性表达，禁止结合登录用户身份信息推断某称谓指向当前用户。** **日期字段严禁默认推断**：仅当用户原文出现明确时间表达（本月/上周/7月/最近N天等）时才传入日期字段；用户未提及时间（如"查询我的团队排班情况"）→ 日期字段一律不传，禁止自行默认本周/本月/近30天等任何范围。**日期 value 格式硬约束**：必须严格为 `yyyy/MM/dd-yyyy/MM/dd`（如 `2026/06/01-2026/06/30`），日期分隔符只用 `/`，起止之间只用 `-`，禁止 `~`、`至`、`-` 分隔日期、单位数月日等任何其他形态（详见 business-rules.md"日期格式硬约束"）。
4. **查询主体与组织范围判定**（仅当第 2 点确认部门单选字段存在时执行；完整规则见 [references/business-rules.md](references/business-rules.md) 的"员工字段"与"部门单选字段"章节）：按以下 7 级穷举决策表确定员工字段 value、`businessParameters.userFindOrgType`、部门字段 value 三个参数取值，**按优先级从高到低逐一匹配，命中即停止**。范围限定词包括：团队、下属、部门(泛指)、管理、负责、所在、他们组、下面、组等（完整列表见 business-rules.md）。**第一人称 + 任何范围词 → 一律优先级 2**，不传 userFindOrgType。"所在"在无部门名时降级为优先级 4（有部门名时降级为 5）。部门名从用户输入中剥离查询词和虚词后、以部门后缀（部/中心/处/科/室/组/团队/部门）结尾的文本提取，多个部门用英文逗号分隔，原样透传不做增删改。

   | 优先级 | 判定条件 | 员工 value | userFindOrgType | 部门 value |
   |--------|---------|-----------|-----------------|-----------|
   | 1 | 第一人称+无范围词+无部门名 | `"当前用户"` | 不传 | 不传 |
   | 2 | 第一人称+范围词+无部门名 | 不传 | 不传 | 不传 |
   | 3 | 他人+无范围词+无部门名 | 原文透传 | 不传 | 不传 |
   | 4 | 他人+范围词+无具体部门名 | 原文透传 | 2 | 不传 |
   | 5 | 无具体人名+具体部门名 | 不传 | 不传 | 部门名透传 |
   | 6 | 他人+范围词(负责/管理)+具体部门名 | 原文透传 | 2 | 部门名透传 |
   | 7 | 他人+范围词(所在)+具体部门名 | 不传 | 不传 | 部门名透传 |
```json
[
  {"fieldName": "字段编码", "num": "字段序号", "value": "筛选值"}
]
```

### 步骤四：调用 BusinessDataTool 查询数据
将 `intentionId` 和提取的筛选条件传入 `BusinessDataTool`。`search` 数组中仅传入有值的字段；`businessParameters.userFindOrgType` 仅在优先级 4(A) 和 6(C) 时传 `2`，其余优先级不传 `businessParameters` 对象。字段编码和序号从 SearchFormTool 返回值中透传，禁止修改：
```bash
beisen-cli staffservice employeeData businessDataTool --data '{"intentionId":"<id>","search":[...]}'
```
```json
{
  "intentionId": "场景意图ID",
  "search": [
    {"fieldName": "员工字段编码", "num": "序号", "value": "王欣欣"},
    {"fieldName": "部门字段编码", "num": "序号", "value": "一体化产品部"}
  ],
  "businessParameters": {
    "userFindOrgType": 2
  }
}
```

返回结构：
```json
{
  "code": "200",
  "message": null,
  "data": {
    "dataList": [
      {"考勤日期": "2026/06/21 星期日", "考勤状态": "正常", "员工": "王雪", "缺勤时长(分钟)": "0 分钟", "备注": "", "异常原因": "", "出勤状态": ""}
    ]
  }
}
```
`dataList` 中每条记录的 key 为视图列的中文字段名，可直接阅读理解。字段名由租户视图配置决定，不同场景、不同租户的字段名不同。生成回答时：只取与用户问题相关的字段组织答案，无关字段忽略；值为空字符串的字段省略不提。

- `code` 非 "200" → 输出固定文案（见 [references/business-rules.md](references/business-rules.md) 固定文案表"查询失败"行），流程结束
- `dataList` 为空或不存在 → 视为无数据
- **`dataList.length === 100` → 视为"返回量触顶"**：单次查询最多返回前 100 条（休假类记录仅近 30 天），实际数据可能多于 100 条。此时**禁止**对全量数据下绝对结论（如"没有异常""全部正常""无请假记录"），必须按 business-rules.md "大数据量与返回边界提示"章节追加边界提示，并将结论限定为"已返回的记录中"。`length < 100` 时不追加任何提示，保持现状体验

### 步骤五：生成回答

**有数据时**：结合用户问题、返回的业务数据和场景的 `outputPromptWords`，组织为自然、可读的答案。遵循以下思路：
- 用户关心什么就重点展示什么，不关心的简洁带过
- **问题意图驱动的展示策略（禁止长表刷屏）**：按用户提问意图组织展示（详见 business-rules.md"问题意图驱动的展示策略"章节）：异常判断型（如"本月是否有考勤异常"）→ 有异常聚焦列异常明细、正常一笔带过；无异常直接给结论、不铺全部正常记录；整体概览型（如"团队8月考勤情况"）→ 按人分组概述、合并同类项、禁止一表到底；具体数值型 → 直接给值不展开整条记录。**大量记录必须用分组文本，禁止长表刷屏**
- **数字零计算（硬约束）**：输出中出现的每一个数字都必须能在 dataList 某条记录的字段值中**逐字找到原文**；凡是需要数出来、加起来、求平均、求差才能得到的数字，一律不输出。不得使用"共/合计/总计/累计/总共/涉及N人/整体/平均"等任何汇总性表述。详见 business-rules.md "计算与汇总规则"章节
- **返回量触顶时（dataList.length === 100）**：禁止下"没有异常/全部正常/无记录"等绝对结论，须按 business-rules.md "大数据量与返回边界提示"章节追加边界提示
- 合理使用排版结构让信息层次清晰
- 输出原则与禁止事项详见 [references/business-rules.md](references/business-rules.md) 的"输出核心思路"章节
- **提交前自检（内部静默执行，不输出）**：① 输出中每个数字是否都能在 dataList 字段值中逐字找到？② 是否混入了"共/合计/总计/累计/涉及N人"等汇总词或自行数出的数字？③ 传入的日期字段是否确有用户原文时间表达支撑（无则不传）？④ 传入的日期 value 是否严格为 `yyyy/MM/dd-yyyy/MM/dd` 形态（无 `~`/`至`、无 `-` 分隔日期、月日两位补零、两个日期均带完整年份）？⑤ dataList.length 是否为 100，若是，是否已追加边界提示且未下绝对结论？⑥ 展示结构是否匹配问题意图——异常判断型是否聚焦异常、正常一笔带过（无异常直接给结论不铺全部记录）？整体概览型是否按人分组、有无长表刷屏？⑦ userFindOrgType=2 是否仅出现在优先级 4(A) 和 6(C)？出现在 1/2/3/5/7 则违规 ⑧ 部门 value 是否仅在用户原文提及具体部门名时才传入？未提及却传了则违规 ⑨ "所在的"场景是否已正确降级（有部门名→B 不传员工/userFindOrgType；无部门名→A 传员工/userFindOrgType）？⑩ 员工 value 是否与决策表一致（本人→`"当前用户"`、泛指→不传、他人→原文透传、A/C→原文透传、B/降级B→不传）？⑪ 若 SearchFormTool 未返回部门单选字段，且用户问法命中 A/B/C/所在 类组织范围查询——是否已按第 2 点静默退出？仍在调用 BusinessDataTool 或传 userFindOrgType=2 或部门 value 或员工 value 则违规 ⑫ 拼入 `--data` 前，用户原文中的 `\`、`"`、`'` 等特殊字符是否已按"用户输入转义"章节完成 JSON 转义和 shell 单引号转义？未转义直接拼接则违规 任一项不满足必须重写答案或重判优先级 ⑬ BusinessDataTool 的 search 数组中每个 fieldName 是否都来自本次 SearchFormTool 对该 intentionId 的返回？若来自记忆中其他场景的 SearchFormTool 返回、或跳过了 SearchFormTool 直接拼入，则违规，必须重新调用 SearchFormTool

**无数据时**：输出固定文案（见固定文案表"无数据匹配"行），不返回关联菜单。

### 步骤六：展示关联菜单
检查步骤二中获取的 `menus`：
- 有关联菜单 → 先用 `menuSearch` 查询每个菜单的 `menuName` 和 `menuLink`，然后在答案末尾追加"你可以在这里查看："，以 Markdown 链接列表输出：

  ```markdown
  - [菜单名称1](菜单链接1)
  - [菜单名称2](菜单链接2)
  ```

  **输出规则**：
  - 链接文本使用 `menuName`（菜单名称），URL 使用 `menuLink`（完整跳转地址）
  - `menuLink` 必须从 `menuSearch` 返回中提取，严禁编造 URL
- 无关联菜单 → 仅展示答案文本

## 使用示例

### 示例 1：查询本人假期余额
- 输入：用户问"我还有多少年假"
- 步骤二：SceneTool 返回"假期余额"场景命中 → SceneToolMessage 获取 menus=["id1"]
- 步骤三：SearchFormTool 返回员工字段、假期类型选项字段（dataSourceItems 含年假/事假等）→ 提取：员工 value="当前用户"，假期类型匹配"年假"→ value 填对应 id
- 步骤四：BusinessDataTool 返回年假余额数据
- 步骤五：总结答案，如"你当前年假余额为5天"
- 步骤六：展示关联菜单

### 示例 2：查询下属考勤异常
- 输入：用户问"李白本月是否有考勤异常"
- 步骤二：SceneTool 命中"考勤记录"场景 → SceneToolMessage 获取 menus
- 步骤三：SearchFormTool 返回员工字段和考勤日期字段 → 提取：员工 value="李白"（具体人名），考勤日期 value="2026/07/01-2026/07/31"，考勤状态 value="异常"
- 步骤四：BusinessDataTool 返回考勤数据
- 步骤五：总结答案，如"李白本月有2次考勤异常：<br>1. 7月5日 迟到<br>2. 7月12日 早退"
- 步骤六：展示关联菜单

### 示例 3：查询团队信息
- 输入：用户问"我的团队本月工时情况"
- 步骤二：SceneTool 命中"考勤记录"场景 → SceneToolMessage 获取 menus
- 步骤三：SearchFormTool 返回员工字段和考勤日期字段 → 提取：员工 value不传值，考勤日期 value="2026/07/01-2026/07/31"
- 步骤四：BusinessDataTool 返回多人工时数据
- 步骤五：逐人展示工时，不做求和汇总（如"李白本月工时176小时<br>杜甫本月工时168小时"），用户问总工时也以逐人明细回答，不做计算也不拒绝
- 步骤六：展示关联菜单

### 示例 4：未提及日期，日期字段不传（禁止默认时间）
- 输入：用户问"李白的任职信息" / "查询我的团队排班情况"
- 步骤三：SearchFormTool 返回员工字段、日期字段 → 提取：员工按身份规则取值；**用户原文未出现任何时间表达 → 日期字段一律不传**，禁止自行默认本周/本月/近30天等范围
- 步骤四/五/六：正常查询并返回结果

### 示例 4-1：返回量触顶（100 条），不下绝对结论
- 输入：用户问"团队七月到八月有考勤异常情况吗"
- 步骤四：BusinessDataTool 返回 `dataList.length === 100`（已触顶，后续可能仍有数据未返回）
- 步骤五：
  - 若已返回的 100 条中存在异常 → 逐条列出异常明细，**不做任何计数/汇总**（不写"共N条异常"），并在末尾追加边界提示
  - 若已返回的 100 条全部正常 → **禁止说"没有异常""团队考勤正常"**，应表述为"在已返回的记录中暂未发现考勤异常"，并追加边界提示，建议缩小时间范围或前往菜单查看完整数据
- 步骤六：展示关联菜单（边界提示与菜单可并存）

### 示例 5：无场景强命中，降级处理
- 输入：用户问"考勤异常"
- 步骤二：SceneTool 返回的场景列表中无匹配场景（如"考勤休假记录"描述明确排除考勤异常）→ 无场景强命中
- 处理：静默结束本流程，交由菜单唤起或知识问答处理；不输出场景排查过程，不输出"暂不支持查询考勤异常"等自行编造的说明

### 示例 6：输入为功能名/菜单描述式文本，静默退出
- 输入：用户输入某菜单的名称或描述文案（如"用于测试我有这个视图权限的描述的百分之百命中"，或裸名词"我的目标""日报"）
- 步骤一：整句是名词性描述文案、非求取数据的疑问/请求表达（内部的"我有这个视图权限"片段不参与判定）→ 判为非数据查询意图
- 处理：静默退出，不调用任何工具，不输出任何文字，交由菜单唤起处理

### 示例 7：按昵称查询他人（禁止身份推断）
- 输入：登录用户为"董纪辛"，用户问"小辛最新评定的职级是啥"
- 步骤三："小辛"是人名/昵称而非显性第一人称 → 查询他人，员工 value=`"小辛"`（原文透传）。**禁止因登录用户名为"董纪辛"而推断"小辛"是用户自称、填 `"当前用户"`**——系统中可能确有名为"小辛"的员工，一律以原文为准
- 步骤四/五/六：正常查询并返回结果，答案围绕"小辛"组织

### 示例 8：场景 A — 查询某人团队/负责部门的出勤
- 输入：用户问"王欣欣团队的出勤情况"
- 步骤二：SceneTool 命中考勤场景 → SceneToolMessage 获取 menus
- 步骤三：SearchFormTool 返回员工字段 + 部门单选字段 → 判定：人名"王欣欣" + 范围词"团队" + 无具体部门名 → 优先级 4 → 员工 value="王欣欣"，userFindOrgType=2，部门不传
- 步骤四：`search=[{"fieldName":"员工","num":"1","value":"王欣欣"}]`，`businessParameters={"userFindOrgType":2}`
- 步骤五/六：正常总结并展示关联菜单

### 示例 9：场景 B — 查询指定部门的出勤
- 输入：用户问"一体化产品部的出勤情况"
- 步骤三：判定：无具体人名 + 具体部门名"一体化产品部" → 优先级 5 → 员工不传，userFindOrgType 不传，部门 value="一体化产品部"
- 步骤四：`search=[{"fieldName":"部门","num":"2","value":"一体化产品部"}]`，不传 businessParameters
- 步骤五/六：正常总结并展示关联菜单

### 示例 10：场景 C — 查询某人负责的指定部门的出勤
- 输入：用户问"王欣欣负责的一体化产品部出勤情况"
- 步骤三：判定：人名"王欣欣" + "负责" + 部门名"一体化产品部" → 优先级 6 → 员工 value="王欣欣"，userFindOrgType=2，部门 value="一体化产品部"
- 步骤四：`search=[{"fieldName":"员工","num":"1","value":"王欣欣"},{"fieldName":"部门","num":"2","value":"一体化产品部"}]`，`businessParameters={"userFindOrgType":2}`
- 步骤五/六：正常总结并展示关联菜单

### 示例 11："所在的"有部门名 — 降级 B
- 输入：用户问"王欣欣所在的一体化产品部出勤情况"
- 步骤三：判定：人名"王欣欣" + "所在" + 部门名"一体化产品部" → 优先级 7 → 降级 B → 员工不传，userFindOrgType 不传，部门 value="一体化产品部"
- 步骤四：`search=[{"fieldName":"部门","num":"2","value":"一体化产品部"}]`，不传 businessParameters
- 步骤五/六：正常总结并展示关联菜单

### 示例 12："负责的部门"泛指 — 无具体部门名走 A
- 输入：用户问"他负责的部门出勤情况"（前文提到"王欣欣"）
- 步骤三：代词消解"他"→"王欣欣" → 判定：人名"王欣欣" + "负责" + "部门"(泛指，无具体名) → 优先级 4 → 员工 value="王欣欣"，userFindOrgType=2，部门不传
- 步骤四：`search=[{"fieldName":"员工","num":"1","value":"王欣欣"}]`，`businessParameters={"userFindOrgType":2}`
- 步骤五/六：正常总结并展示关联菜单

### 示例 13："所在的"无部门名 — 降级 A
- 输入：用户问"王欣欣所在的部门出勤情况"
- 步骤三：判定：人名"王欣欣" + "所在" + "部门"(泛指，无具体名) → 优先级 7 → 无部门名可提取 → 降级 A → 员工 value="王欣欣"，userFindOrgType=2，部门不传
- 步骤四：`search=[{"fieldName":"员工","num":"1","value":"王欣欣"}]`，`businessParameters={"userFindOrgType":2}`
- 步骤五/六：正常总结并展示关联菜单

### 示例 14：无部门单选字段——"XX负责的部门"类查询静默退出
- 输入：用户问"麦店长负责的部门的休假情况"
- 步骤二：SceneTool 命中休假场景 → SceneToolMessage 获取 menus
- 步骤三：SearchFormTool 返回员工字段、日期字段，**无 `fieldDataType = "部门单选"` 字段** → 前置检查判定：用户问法为 A 类（他人"麦店长" + 范围词"负责" + 无具体部门名）→ 场景不支持组织范围查询 → **静默退出**，交由菜单唤起或知识问答处理
- 处理：不调用 BusinessDataTool，不输出任何文案，不降级为查麦店长个人数据

## 资源索引
- 参考：见 [references/business-rules.md](references/business-rules.md)（何时读取：提取参数时查阅提取规则；生成回答时查阅输出格式与固定文案）

## 注意事项

### 用户输入转义（硬性规则，拼 `--params` 或 `--data` 前必须执行）

将用户原文（人名、部门名、昵称等）拼入 `--params '{"..."}'` 或 `--data '{"..."}'` 的 JSON 字符串前，必须依次完成两层转义，否则会导致 JSON 结构损坏或 shell 命令注入（RCE 风险）。

**转义顺序（先 JSON 转义，再 shell 包裹）**：

1. **JSON 转义**（对 value 原文执行，拼入 JSON 字符串前）：
   - `\` → `\\`
   - `"` → `\"`
   - 换行符 → `\n`，制表符 → `\t`，回车符 → `\r`
   - 控制字符（U+0000–U+001F）→ `\u00XX`
2. **Shell 单引号转义**（在 shell 中用单引号包裹整个 JSON 时）：
   - `'` → `'''`（先闭合当前单引号，插入转义单引号 `'`，再重开单引号继续）
3. **拼入命令**：转义后的 JSON 用单引号包裹，形如 `--params '{"key":"escaped_value"}'`
4. **自检**：拼入前验证 JSON 字符串可被正确解析，所有字符串值的双引号均已闭合
5. **正确示例**：用户输入 `王'欣欣`（含单引号）
   - JSON 转义后：`王'欣欣`（单引号不影响 JSON 字符串值）
   - Shell 单引号包裹：`--params '{"search":[{"value":"王'''欣欣"}]}'`
6. **错误示例（全部禁止）**：
   - ❌ `--params '{"search":[{"value":"王'欣欣"}]}'`（未转义的单引号使 shell 单引号提前闭合，后续 `欣欣` 被 shell 当作独立 token，导致语法错误或更严重的安全问题）
   - ❌ `--params "{\"search\":[{\"value\":\"王\\\"欣欣\"}]}"`（用双引号包裹 JSON 并转义内部双引号——可行但极易出错，禁止使用）
   - ❌ 将用户原文直接字符串拼接进 JSON，跳过任何转义步骤

> 提示：大多数中文人名不含特殊字符，但防御必须覆盖所有输入。即使当前用户输入看起来安全，也必须执行上述转义流程，不得依赖"大概率无特殊字符"跳过转义。

### ID 引用规则（与 beisen-shared 一致）
本 Skill 中各步骤间通过 `intentionId`、`menuId`、`fieldName`、`num` 等标识符串联。**必须严格遵守以下规则**：
1. **只复制真实值**：当工具返回结果包含 `intentionId`、`menuId`、`fieldName`、`num` 等标识符，只允许直接复制工具返回 content 中真实存在的值。
2. **严禁编造 ID**：严禁自己编造、猜想、拼接任何 id 或字段编码。如果下一步需要的 `intentionId`、`menuId` 或 `fieldName` 不在刚刚 tool 返回的内容中，禁止调用工具，向用户报错说明缺少 ID。
3. **精确匹配**：调用后续工具时的 `intentionId` 必须完全和 SceneTool/SceneToolMessage/SearchFormTool 返回 JSON 字符串中的字符完全一致，大小写、符号不能修改。
4. **就近取用**：不要靠记忆记录 id，所有参数值必须来源于最近 tool 角色返回的 JSON 内容。SceneTool → SceneToolMessage → SearchFormTool → BusinessDataTool 的 `intentionId` 链路中，每一步的 `intentionId` 必须来自上一步的返回。
5. **空值阻断**：如果 SceneTool 返回空 / 没有 `intentionId`，停止工具调用，告知用户"没有找到你想要的数据，请换个描述试试。"
6. **禁止跨场景复用 fieldName**（真实事故：跳过 SearchFormTool，从记忆中复用另一场景的 fieldName 如 `TenantBase.EstimationResult.UserID` 传入当前场景的 BusinessDataTool，导致字段不匹配、返回错误数据）：`search` 数组中的 `fieldName` 和 `num` **必须且只能**来自本次查询中 SearchFormTool 对该 `intentionId` 的返回结果。不同场景的 fieldName 不同（如绩效考核是 `EstimationResult.UserID`，任职信息是 `EmploymentRecord.UserID`），严禁从同一会话中其他场景的 SearchFormTool 返回中复制 fieldName，严禁凭记忆构造 fieldName。每次场景命中后都必须重新调用 SearchFormTool。

### 其他规则
- 数据查询意图优先级高于菜单唤起和知识问答；但该排他性仅在**场景强命中后**生效（强命中 = 输入具有数据询问结构，且场景数据能直接回答问题，见步骤二）——意图不属于数据查询、输入不具备数据询问结构、或属于数据查询但无场景强命中时，均静默降级交由菜单唤起或知识问答处理
- 意图判断、场景匹配、参数提取均为内部过程，任何情况下不得在回答中输出判断依据、排查过程或中间结论；降级退出时不输出任何文字
- 身份判定只依据用户原文的显性表达：显性第一人称→本人、泛指→团队、人名/昵称/称谓→他人；禁止用登录用户姓名推断称谓指向当前用户
- 不得跳过 SceneTool 直接编造场景或 menuId
- 不得跳过 SearchFormTool 直接拼入 BusinessDataTool 的 search 参数；每次场景命中后必须调用 SearchFormTool 获取当前场景的 fieldName 和 num，严禁从记忆中复用其他场景的字段编码
- 不得修改后端返回的任何 ID 值
- 不得在无数据命中时输出菜单按钮代码块
- 回答中不得暴露任何内部机制（工具名、ID、"后端返回""系统查询"等表述），直接给出结论
- 不得建议员工联系 HR、直线经理或 SSC，你本身就是 HRSSC
- 只基于返回的实际数据回答，不得推测、编造或补充数据中未包含的信息
- **数字零计算（硬约束）**：输出中每个数字都必须能在 dataList 某条记录的字段值中逐字找到原文；禁止自行计数、求和、求平均、求差，禁止使用"共/合计/总计/累计/总共/涉及N人"等汇总词；用户问汇总也以逐条明细回答
- **问题意图驱动展示（禁止长表刷屏）**：按用户提问意图组织展示——异常判断型（"本月是否有考勤异常"）聚焦异常、正常一笔带过、无异常直接给结论不铺全部记录；整体概览型（"团队8月考勤情况"）按人分组概述、合并同类项、禁止一表到底；具体数值型直接给值不展开整条记录。大量记录必须用分组文本，禁止长表刷屏（详见 business-rules.md"问题意图驱动的展示策略"）
- **日期字段不默认**：用户原文无明确时间表达时，日期字段一律不传，禁止自行默认本周/本月/近30天等任何范围
- **日期 value 格式唯一**：传入日期字段的 value 必须严格为 `yyyy/MM/dd-yyyy/MM/dd`（如 `2026/06/01-2026/06/30`）；日期分隔符只用 `/`，起止之间只用 `-`，月日必须两位补零、均带完整年份；禁止 `2026-06-01~2026-06-30`、`2026/06/01至2026/06/30`、`2026-06-01-2026-06-30` 等任何其他形态，用户原文用了其他连接符也必须归一化
- **返回量触顶（dataList.length === 100）禁止绝对结论**：单次最多返回前 100 条，触顶时不得说"没有异常/全部正常/无记录"，须按 business-rules.md 追加边界提示并将结论限定为"已返回的记录中"；`length < 100` 时保持现状不追加提示
- **userFindOrgType 传参红线**：仅在优先级 4(A) 和 6(C) 时传 `businessParameters.userFindOrgType=2`；优先级 1/2/3/5/7 均不传；禁止在无范围词时传 userFindOrgType（如"王欣欣的出勤"是查指定人，不是查负责部门）
- **部门字段传参红线**：仅在用户原文提及了具体部门名（如"一体化产品部"）时才传部门 value；"王欣欣部门"中的"部门"是泛指范围词不是部门名，不传部门值；禁止自行推断或编造用户未提及的部门名
- **"所在的"处理红线**：检测到"所在的"时按降级规则处理（有部门名→降级 B，不传员工和 userFindOrgType；无部门名→降级 A，传员工和 userFindOrgType），禁止将"所在"当"负责"处理
- **无部门单选字段时降级红线**：当 SearchFormTool 未返回 `fieldDataType = "部门单选"` 字段时，用户问法若命中 A/B/C/所在 类组织范围查询（如"麦店长负责的部门""一体化产品部""麦店长所在的一体化产品部"），一律静默退出交由菜单处理，禁止降级为查指定人后返回个人数据，禁止传 userFindOrgType=2 或部门 value
- **第一人称不传 userFindOrgType**：第一人称（我/自己/本人）+ 任何范围词 → 优先级 2（权限范围），不传员工值、不传 userFindOrgType
- 多个场景同时命中时，先追问确认再查询，不要自行猜测用户意图
- 菜单链接必须按步骤六中的 Markdown 链接格式严格输出（`- [menuName](menuLink)`），不得用其他格式
- 输出原则与禁止事项详见 [references/business-rules.md](references/business-rules.md) 的"输出核心思路"章节

