Log in

beisen-data-query

All-time installs
2,113

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

Other options

Summary

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

Raw SKILL.md

34.8K bytes
---
name: beisen-data-query
version: 2.0.19
description: "北森 HR 通用数据查询引擎。本 Skill 通过 beisen-cli staffservice 子命令集(sceneTool / searchFormTool / businessDataTool,以及 sceneToolMessageForCLI、menuSearch)实现自然语言到业务数据的 6 步查询流水线。当用户询问假期余额、考勤异常、下属信息、绩效情况、任职信息、组织架构等个人或团队业务数据时触发。本 Skill 是 beisen-employee-profile、beisen-attendance-leave、beisen-organization 三个业务域 Skill 的共享查询底层。"
category: 人力资源/数据查询
author: beisen
agent_created: false
allowed-tools: Bash, Read
requires-skills:
  - beisen-shared
requires-cli: ">=1.0.5"
---

# 员工数据查询

**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) 的"输出核心思路"章节

Security audits