# 流程查询（workflow.search / workflow.todoStat）

> **分段索引 —— 本文件约 108 KB / 835 行，必须按段读：整读会超单次读取上限被明确拒绝**（Read 单次上限约 **20,000 tokens ≈ 100 KB / 800 行**）；**开头的契约段（1-244 行，约 30 KB）一次就能读完**，其余段落按本索引的行区间分次读。**
> 被拒时按报错提示改用 `offset`/`limit`、**回到本文件按行段重读**即可；**不要**去找宿主的落盘文件（`~/.workbuddy/projects/**/tool-results/**` 无读取权限，去读只会拿到 `Permission … has been denied`、白费一轮——"落盘 + 只回 2048 字节预览"那是**命令输出**超线时的行为，本文件的读取不走那条路）。
>
> | 段落 | 行区间 | 读取方式 |
> | --- | --- | --- |
> | **契约段**：本索引 + Operation + 输入参数（分类 + 大分类判定 / 筛选 / 时间 / filterFields / 分页排序）+ 执行模式与返回形态（含模式判定 `smartGrouping`）+ 待办时间默认语义 + 命令参数反思 + 执行流程 | 1-244 | **首轮一次读完**：`offset 1 limit 244`（约 30 KB，在单次上限内） |
> | `planJson` 批量编排 | 245-324 | 泛化待办 / 一次取多组数时读：`offset 245 limit 80` |
> | 汇报式分组骨架 + 七个维度 + 参与身份说明与分组去向 + 常见业务重点字段 + 汇总渲染规则 + 渲染红线 | 325-524 | 需要输出分组结果前读（分两次）：`offset 325 limit 100`、`offset 425 limit 100` |
> | 智能分组示例（各业务域样例，**仅供格式参照，不要照抄内容**） | 525-639 | 一般**不用读** |
> | **异常返回处理 + 澄清后回传**（澄清信封、修正指令、认证失效） | 640-702 | 拿到 `ok:false` 或 `NEEDS_CLARIFICATION` 时读：`offset 640 limit 63` |
> | 调用示例 | 703-781 | 需要时读：`offset 703 limit 79` |
> | 返回（返回结构 / 错误码 / 幂等口径） | 782-821 | 处理 `ok` / `error` 时读：`offset 782 limit 40` |
> | 注意 | 822-835 | 需要时读：`offset 822 limit 14` |
>
> 行号以本索引为准；**改本文件时同步更新本索引**。按 `##` 标题定位同样有效。

## 什么时候读取

用户要查询待办/已办/我发起的/全部流程，或按工作流、表单字段、节点、时间、紧急程度、发起人、标题/编号等条件筛选时读取本文件。也用于待办查询的「智能分组」取数规划与 `planJson` 批量编排。

涉及发起、操作、批量、编辑、共享等写意图时，本文件不适用，转对应写操作文档。

## Operation

| Operation | 固定规则 |
| --- | --- |
| `workflow.search` | CLI 按 OA 版本自动路由执行模式（智能分组/低版本）。`category` 必填；`current` 默认 1、`pageSize` 默认 10（最大 100）、`conditionType` 默认 `and`、`totalOnly` 默认 false。只读，无需 confirm。 |
| `workflow.todoStat` | `category` **必带且固定为 `todo`**（只统计待办，不支持其他分类）。**仅 OA ≥ `10.0.9909.01` 支持**；低版本不支持本 operation，待办查询直接走 `workflow.search`。不分页、无统计行。只读。 |

`workflow.todoStat` **不支持的 `workflow.search` 专有参数**（不要传，会报错或被忽略）：

- `current` / `pageSize`：本 operation 为**全量分组计数、不分页**（不消费分页参数）；
- `totalOnly`、`conditionType`、`batchType`、`planJson`、`queryJson`：均为 `workflow.search` 的查询/编排专有开关。

它的入参只有**查询筛选条件类字段**（`category` / `subCategory` / `tabid` / `workflow` / `workflowTerm` / `creator` / `creatorDept` / `creatorSubcom` / `requestName` / `requestMark` / `requestLevel` / `requestId` / `exRequestId` / `nodeId` / `flowStatus` / `createTime` / `receiveTime` / `finishTime` / `filterFields` / `sort` 等，与 `workflow.search` 的筛选条件一致）——**无分页、无编排、无批量**。

## 输入 —— 大分类 category

| category | 含义 | 未传 subCategory 的默认小分类 |
| --- | --- | --- |
| `todo` | 待办 | **低版本模式（OA < `10.0.9909.01`）= 待处理（7）；智能分组模式（OA ≥ `10.0.9909.01`）= 全部（0）** |
| `done` | 已办 | 默认全部 |
| `mine` | 我发起的 | 默认全部 |
| `all` | 全部 | 默认全部 |

`subCategory` 为细分 tab（名称或 tabid）；`tabid`/`tabName` 为等价细分入口。**用户未表达小分类时不要补传 `subCategory`/`tabid`/`tabName`**；其余分类默认全部。

### 大分类判定（先定 `category`）

`category` 只表示**这批流程属于哪个列表**，与问句里出现的其他条件（工作流、表单字段、时间、发起人、节点等）无关：

| 用户原话里的列表语义 | `category` |
| --- | --- |
| 待办 / 待我处理 / 要我审批 / 未处理 | `todo` |
| 已办 / 我处理过 / 审批过的 / 办理过 / 办结的 | `done` |
| 我发起的 / 我提交的 / 我创建的 / 我提的（**指流程发起人是我**） | `mine` |
| 全部流程 / 所有流程 / 不限定属于哪个列表 | `all` |

**两条红线（下列说法不得推出 `mine`）**：

1. **"我/我的"出现在筛选条件的取值里，不是列表语义**——"费用承担人是我""发起人是我""负责人是我"里的"我"只是该字段的筛选值（人员类字段值按当前用户处理），分类照上表另判。
2. **"提交/发起/创建"只作时间短语的修饰语时，不是列表语义**——"本月提交的""上周发起的""今天提的"只生成 `createTime`，与"我提交的"无关。

上表判不出来时：问句里还有别的筛选条件的，按条件跨列表查，用 `category: "all"`（`todo`/`mine` 都会漏掉不在该列表里的流程）；连筛选条件都没有的，先反问一次用户要查哪一批（待办/已办/我发起的/全部），**不要自行挑一个分类硬查**。

**禁止"先试一个分类"**：在 `todo`/`mine`/`all` 之间摇摆时，不要传当前更顺手的那个先跑一遍看结果——命令返回正常不代表分类猜对了（`mine` 少查、`all` 多查都不会报错），错的那一批会直接被渲染给用户。按上表与两条红线定好再做一次调用。

各分类的小分类（名称与 tabid）：

| 大分类 | 小分类（名称（tabid）） |
| --- | --- |
| `todo` | 全部（0）、待处理（7）、未读（1）、新反馈（2）、已查阅（3）、待阅（5）、超时（6）、被退回（8）、转发（4）、传阅（11）、抄送（9）、关注（10）、被督办（12）、被转办（13）、草稿（14） |
| `done` | 全部（50）、审批中（52）、已结束（51）、待回复（60）、未读（61）、已处理（53）、新反馈（62）、已阅（54）、关注（63）、抄送（55）、转发（56）、传阅（57）、超时已办（58）、超时自动处理（59）、已审批（64）、待退回（65）、暂停（66） |
| `mine` | 全部（100）、审批中（102）、新反馈（101）、已结束（103）、未读（104）、关注（105）、暂停（120） |
| `all` | 全部（300）、审批中（303）、已结束（304） |

## 输入 —— 筛选条件（映射到 schema 真实字段）

系统条件（紧急程度/标题/编号/发起人/节点/状态）必须用专用字段，不要塞进 `filterFields`；`filterFields` 只用于表单字段。

| 语义分组 | 字段（camelCase，与 schema 一致） | 取值约束 |
| --- | --- | --- |
| 工作流 | `workflow`（数组，多值 or）、`workflowTerm`（`in`/`notin`） | 元素支持 `名称(ID)`、纯数字 ID、纯名称。**纯名称由 CLI 调 workflowPathBrowser 解析**：唯一命中→直接用；**多命中或 0 命中→CLI 返回澄清信封（`ok:true` + `status=NEEDS_CLARIFICATION` + `data.candidates`），此时必须与用户确认后改用 `名称(ID)` 重发**（不要重复传纯名称试探） |
| 表单字段 | `filterFields`（对象数组） | 见「表单字段筛选」小节；只用于表单字段，不用于系统条件 |
| 发起时间 | `createTime` | `"开始 结束"`：YYYY-MM-DD，单边空串放开该端（见「时间条件」） |
| 操作时间 | `operateTime` | 同上；待办下忽略 |
| 接收时间 | `receiveTime` | 同上 |
| 完成时间 | `finishTime` | 同上 |
| 紧急程度 | `requestLevel` | 字符串（名称，CLI 按该环境实际等级列表转 ID）；**多命中且候选中无与所写完全一致的 → 澄清信封（候选见 `data.candidates`）**；**0 命中 → `ok:false` + `requestlevel_not_found`**（message 里列出当前环境全部等级），据此与用户确认后改用 `名称(ID)` 重发 |
| 标题 | `requestName`、`requestNameTerm`（`in`/`notin`/`eq`/`ne`） | like/精确 模糊 |
| 编号 | `requestMark`、`requestMarkTerm`（`in`/`notin`/`eq`/`ne`） | like/精确 模糊 |
| 发起人 | `creator`、`creatorDept`、`creatorSubcom` | 姓名/部门/分部；「我/我的」= 当前用户 |
| 工作流类型 | `workflowType` | 类型名；**多命中/0 命中时 CLI 返回澄清信封并列出候选**，改用 `名称(ID)` 重发 |
| 当前节点 ID | `nodeId`、`nodeIdTerm`（`in`/`notin`） | 节点 ID |
| 流程状态 | `flowStatus`、`flowStatusTerm`（`in`/`notin`） | `finish`（已结束）/ `normalFinish`（正常结束）/ `forceFinish`（强制结束）/ `notFinish`（未结束·审批中）——**传英文 key**，不接受中文；可逗号分隔多值 |
| 精确过滤/排除 | `requestId`、`exRequestId` | 逗号分隔多个 requestId |
| 排序 | `sort` | `"排序方式:asc\|desc"`，多组逗号分隔 |
| 条件关系 | `conditionType` | `and`（默认）/`or` |

用户原话中的任何筛选条件（时间、工作流、节点、紧急程度、发起人、标题/编号、表单字段）都要原传到对应字段，**不要为"先看全貌"而剥离条件**。

查询范围有歧义时，先向用户确认再调用，不要自行猜测范围硬查。

## 输入 —— 时间条件（`createTime`/`operateTime`/`receiveTime`/`finishTime` 共用同一解析规则）

取值一律是 `"开始 结束"`，日期为 `YYYY-MM-DD`；**CLI 不做中文时间归一化**——"本周/上月/近7天"这类相对日期词不会被解析，请自己换算成具体日期再传（如"本周接收且仍待办"→ `receiveTime: "2026-09-14 2026-09-20"`，一周以周一为起点）。

| 写法 | 实际语义 |
| --- | --- |
| `"2026-08-01 2026-08-31"` | `08-01 ≤ x ≤ 08-31` 双边闭区间（推荐） |
| `"2026-08-01 "`（结束留空串） | `x ≥ 08-01` 开放右边界 |
| `" 2026-08-07"`（开始留空串） | `x ≤ 08-07` 开放左边界 |
| `"2026-08-07"`（只传一个值，两侧无空白） | **自动补成 `"2026-08-07 2026-08-07"`，限到当天**（不是开放右边界——想要开放右边界必须传 `"2026-08-07 "` 末尾留空串） |

写法不是严格 `YYYY-MM-DD`、日期不存在（如 `2026-02-30`）、或起点晚于终点时，**该时间条件会被丢弃且不报错**（查询照常执行）——取值必须自己核对，不要指望 CLI 纠错。

**`category=todo`（待办）下 `operateTime` 会被忽略**（待办=还未处理，与"操作时间"语义矛盾）；其余三个时间条件正常生效。

## 输入 —— 表单字段筛选 filterFields

`filterFields` 为对象数组，每项 `{"fieldName":"...","term":"...","value":...}`：

- **必须同时传 `workflow`，且只能是一个工作流**——字段条件只在单个工作流的表单字段内匹配。未传 workflow 报 `field_require_workflow`；传多个报 `field_require_single_workflow`（此时先把候选工作流交给用户确认）。
- `fieldName` 取值优先级：`字段名(字段ID)` > 纯字段名。**纯字段名由 CLI 按该工作流的真实表单字段解析**（精确 → 包含匹配），因此**不需要模型事先拿到字段 ID**；解析不出时 CLI 报错并列出候选（见下）。
- **字段/取值解析不出唯一值一律澄清、绝不静默丢弃**（条件被丢弃时返回的是未筛选的全量数据，且看不出异常）：
  - 字段名 0 命中 / 多命中 → **澄清信封**（`status=NEEDS_CLARIFICATION`，`clarificationType=field`，`data.candidates` 为 `字段名(字段ID)` 清单）；
  - 选项/人员/浏览类字段的 `value` 不能唯一解析 → **澄清信封**（`clarificationType=fieldOption`，`data.candidates` 为该字段全部 `选项名(选项ID)`）；
  - 该工作流的表单字段元数据**读不到、或返回空清单** → **澄清信封**（`clarificationType=field_meta`，**无候选**）——此时无法生成任何字段条件，按 `data.clarificationQuestion` 如实告知用户，或改为不带 `filterFields` 查询；**不要**反复换字段名试探；
  - 字段类型与 term 不匹配 → `ok:false` + `field_term_unsupported`（如文本字段给 `gt`）；组件类型不支持作为条件 → `field_type_unsupported`。
- `value`：选项类字段用 `选项名称(选项ID)` 或选项名称；文本/人员传字符串、数值传数字或 `[min,max]`、日期传 `["开始","结束"]`（YYYY-MM-DD，可单边空串）。
- `term` 按字段类型：文本 `like/notLike/eq/ne/null/notnull`、数值 `gt/gte/lt/lte`、日期 `like`、选项/人员 `eq/ne/in`。数值 `gt`/`lt` 由 CLI 换算为严格边界区间。

## 输入 —— 分页、排序与计数开关

| 字段 | 默认 | 说明 |
| --- | --- | --- |
| `current` | 1 | 页码；用户明确要求翻页才传，模型不自行翻页 |
| `pageSize` | 10 | 每页条数，1–100；**按记忆偏好或用户要求**（本次用户明确指定 > 记忆偏好） |
| `sort` | 无 | `"排序方式:asc\|desc"` 多组逗号分隔 |
| `conditionType` | `and` | 多条件的组合关系 |
| `totalOnly` | false | 仅查数量不查列表（批量操作第一步查数量用） |
| `batchType` | 无 | 过滤允许对应批量操作的数据，取值 `submit`/`urge`/`read`/`share`/`forward`/`reject`；批量查询配合 `pageSize:100` |

批量查询（`batchType`）语义：`submit` 可批量提交、`urge` 可批量催办、`read` 可批量置已读、`share` 可批量共享、`forward` 可批量转发、`reject` 可批量退回；返回 `total` 用于判断是否还有下一轮。**这是"取操作目标"的查询方式，不是批量操作的前置步骤**：已有明确 `requestId`（上一轮查询结果 / 用户点名）时直接执行对应的批量单命令（`workflow.batchSubmit` / `batchRead` / `batchSupervise` / `batchShare` / `batchForward` / `batchReject`），只有目标是新范围、或命令报 `batch_gate_required` 时才用它取 ID。

## 执行模式与返回形态（重要）

CLI 按 OA 版本自动路由，**两种模式的返回形态不同，按实际返回内容直接渲染，不要互相套用规则**：

| | OA < `10.0.9909.01`（低版本模式） | OA ≥ `10.0.9909.01`（智能分组模式） |
| --- | --- | --- |
| 未明确小分类的 `todo` 默认 | 待处理（7） | 全部（0） |
| CLI 侧分组 | **有**——未明确小分类时按「紧急 → 超时 → 待处理」分组输出（附 `todoSummary`/`todoGroups`） | 无——不分组，纯卡片列表 |
| 顶部行 | **有**——未明确小分类时是分组汇总行（`共有 N 条流程待办：需您亲自处理的流程共 A 条…`）并可加「另有 K 条待阅流程。」；显式小分类时为 `共 N 条…当前显示第 X 页（M 条）。` | **无**——纯卡片列表，分组名/汇总由模型输出 |
| 紧急/超时探查 | 有：待处理范围内补查紧急/超时（有数据时提示"建议优先关注"） | 无（不探查） |
| 卡片摘要行 | **有**（标题/摘要/辅助三行；`batchType` 批量查询跳过摘要） | **无**（标题/辅助两行） |
| 序号定位 | 分组场景须显式传 `group`（`urgent`/`overdue`/`pending`）+ `index`；显式小分类时只传 `index` | 只传 `index`，不传 `group` |
| 分组标题 | 由 CLI 输出（`### 组名（共 N 条，第 X 页显示 M 条）`） | 由模型书写（`## 组名（N 条）`） |

**模式从哪看**：`workflow.memoryPrompt` 返回的 `oaContext.smartGrouping`（`true` = 智能分组模式，`false` = 低版本）。`workflow.search` **不返回**模式字段，**不要**为了判断模式额外调用命令，也**不要**自己拿版本号去比大小。

**模式怎么定**：一律以 `oaContext.smartGrouping` 为准——它是 CLI 按 OA 版本（基线 `10.0.9909.01`）算好的结论。**不要自己拿 `oaContext.version` 去比大小**（四段式逐段整数比较容易出错），`version` 只是背景信息；会话取不到版本时该值为 `false`，按低版本处理。

低版本模式的**探查/待阅接口异常时 CLI 直接失败返回**（`ok:false`），不会退化为「无超时/无紧急」——遇到这类失败按异常返回处理，**不要把它当作 0 条继续渲染**。

## 待办时间默认语义

**时间词的默认含义由"时间范围 + 动作词"共同决定**。下表组合都是**默认语义能唯一确定**的，照表传参即可，**不要反问用户**：

| 用户说法 | 默认条件 |
| --- | --- |
| "今天有哪些待办" | **不加时间条件**（今天＝当前全部待办） |
| "当前/所有/全部待办" | **不加时间条件** |
| 时间范围 + "待办"（"本周有哪些待办"） | `receiveTime`（该范围内**接收到**且当前仍待办） |
| 时间范围 + "接收/收到/到达/来的/提交到我待办的/指派给我的" | `receiveTime` |
| 时间范围 + "我发起/我提交/我创建/我提的" | `createTime` |
| 时间范围 + "已办/处理了/审批过/办理过" | `category:"done"` + `operateTime` |

- **时间范围限定的是"什么时候到我这边"时一律 `receiveTime`**，与问句里有没有"待办"二字无关——"本周接收的问题流程有哪些"＝`category:"todo"` + `receiveTime` + 工作流条件，**不要**因为"没出现待办二字"而放弃时间条件，也**不要**用 `createTime`（发起时间）去近似"接收到的"。
- 用户明确说"当前/所有待办"或"收到/到达"时，以显式说法为准。
- 相对时间词（本周/上周/今天/近 7 天/上月）**CLI 不做中文归一化**，自己换算成 `YYYY-MM-DD` 区间再传（换算规则见上文「时间条件」）；一周以**周一**为起点。

---

# 智能分组（仅待办查询，OA ≥ `10.0.9909.01`）

**适用前提**：本节仅在 **`oaContext.smartGrouping === true`**（OA ≥ `10.0.9909.01`）时生效。`smartGrouping === false`（低版本）的待办查询**不执行本节**——直接 `workflow.search`，其返回自带统计行与分组标题，原样渲染即可。

**模式来源**：`workflow.memoryPrompt` 返回的 `oaContext.smartGrouping`（智能分组流程第一步本就读取记忆，**直接看这个布尔值即可，不要自己比版本号**）。`oaContext` 为 `null` 或字段缺失时按 `false`（低版本）处理，不要自行调用 whoami 或其他命令补齐。

**身份信息**：`oaContext.user.position`（岗位）/`department`（所属部门）/`subcompany`（所属分部）同源——`subcompany` **可能为空，为空时忽略分部**，不要臆造分部信息。这些身份信息用于「七个维度」分析与 ⑤ 重点流程判定。

**意图 → 路径速查**（判定先于一切步骤）：

| 查询意图 | 必走路径 |
| --- | --- |
| 泛化待办查询（多工作流、未指明具体流程） | **按 `oaContext.smartGrouping` 分流**：`false`（低版本）→ 直接 `workflow.search`（category=todo，**不带 `planJson`/`subCategory`**），CLI 已直接输出分组统计与卡片，**原样渲染即结束**；`true`（智能分组）→ 调 `workflow.todoStat` 统计 → 按「参与身份 → 分组去向表」+ 汇报式分组骨架规划 → 打包为一次带 `planJson` 的 `workflow.search` 取数 |
| 查询**单个工作流**的数据（用户意图聚焦某个工作流；或 `countDetails` 归并后仅剩单工作流） | **必须先做字段分组判断**（见下「按重点字段组织分组」）：有可分层价值字段 → 按字段分组；确无价值字段 → 才可平铺 |
| `oaContext.smartGrouping === false`（低版本 OA） | 不执行本节后续步骤——直接 `workflow.search`，CLI 已直接输出分组统计与卡片，原样渲染返回 |

> 判定只看**查询意图是否聚焦单个工作流的数据**，与数据来自哪个组无关——折叠组、非折叠组都可能包含多个工作流的数据，均按上表以意图为准走对应路径；不得因"该组是折叠组/展开组"而直接取数平铺。

## 命令参数反思（调用前）

- 对照用户原话检查已生成的参数是否准确，不准确先调整再调用；`category` 先按「大分类判定」定好（句中出现"我/我的"或"提交/发起/创建"不等于 `mine`）；工作流多命中澄清后用 `"标准名称(ID)"` 格式回传，无澄清时传用户原词。
- **默认语义优先于反问**：上文「待办时间默认语义」表格能唯一确定的组合（含"本周接收的 X 流程"这类"时间范围 + 接收类说法"），**直接按表执行，不要反问**。不要因为用户没说"待办/已办"二字、或没说清是发起时间还是接收时间，就停下来反问——那正是上表要替你定下来的事。
- **反问只用于下列确实无法唯一确定的情况**（除此之外不许反问）：① 既没给分类（待办/已办/我发起/全部流程），也没有任何条件词，无从判断要查哪一批（有条件的按「大分类判定」用 `all`，不要反问）；② 原话存在**两种以上互斥解读**且无法用默认语义消解（如"本周的流程"——既可能是"我发起的""我收到的"，也可能是"我处理过的"）；③ 原话里的工作流名/字段名/人员名在当前环境**多命中或未匹配**（此时 CLI 已返回澄清信封与候选，直接按「澄清后回传」列候选，不要自行挑一个）。反问时用自然语言说明你的理解、列出可能的范围请用户选择，确认后再执行；**不要自行猜测一个范围硬查**。

## 执行流程

1. **先分流（看 `oaContext.smartGrouping`，不要探测、不要自己比版本号）**：泛化待办查询时——`smartGrouping === false`（低版本）→ **直接调 `workflow.search`（category=todo，不带 `planJson`/`subCategory`）**，CLI 已输出分组统计与卡片，**原样渲染即结束，不进入本节后续步骤**；`smartGrouping === true` → 先调用 `workflow.todoStat` 查询当前用户整体待办分组计数（按工作流 × 参与节点 × 参与身份三元组）再继续。**不要在 `smartGrouping === true` 之前先调 `workflow.todoStat`**——低版本会报 `todo_stat_requires_smart_mode`（错误 JSON 在 stderr、stdout 为空），纯属白费一次调用；如果查询意图是指向具体某个工作流的追问，可直接复用本对话之前 `workflow.todoStat` 结果中该工作流的工作流信息（`workflowId`/`workflowName`）与表单字段信息（`formFields`），不必重新调用；否则（泛化多工作流查询且已确认 smart 模式，或本对话尚无该工作流信息）必须先调用。
   `countDetails` **行完整性由 CLI 保证**（行全量返回不随输出大小截断，大输出仅移除行内 `formFields`）——**无需自校验求和、无需读 `resultFile` 核对行数、也无需对 CLI 输出做管道截断**；`resultFile` 仅在需要对某工作流做**字段分组判断**（取其 `formFields`）时才读。

2. **规划分组结构与查询边界（先于任何查询锁定；既定即不得事后重组）**：**先分流查询意图**——
   - **泛化待办查询**（多工作流、用户未指明具体流程）→ 走**汇报式分组骨架**：按「参与身份 → 分组去向表」把 `countDetails` 各行归入去向，划出固定特殊组（紧急/超时、转发给您）与业务域展开组、折叠组（≤3）；
   - **聚焦单个工作流**（用户意图聚焦某个工作流；或 `countDetails` 归并后仅剩单工作流）→ **必须先做字段分组判断**（见下「按重点字段组织分组」）；
   - **折叠分组只显示数量**——数量直接来自 `countDetails` 的 `totalCount`/`urgentCount`/`overtimeCount`/`forwardToSelfCount`/`managerForwardToSelfCount` 等字段，**不需要再走 `workflow.search` 查数量**。

### 按重点字段组织分组（仅聚焦单个工作流时）

用户意图是查询**具体某个工作流**的数据（如"查一下报销待办有哪些"），或 `countDetails` 归并后**仅剩单个工作流**时，**必须先**结合下方「常见业务重点字段与推荐分组维度」表中该流程类型的重点关注字段，判断该工作流是否有可组织分组的价值字段并据此组织分组；**除"确无价值字段"外不得平铺**。

字段名与组件类型以该分组 `countDetails` 元素附带的 `formFields`（该工作流表单字段清单）为准；按字段类型目前支持**数值、选项、时间**三类（文本、人员、关联类等字段不用于字段分组；**选项类判据：`formFields` 元素 `options` 非空**，组件名如 `Select`/`RadioBox` 仅作辅助语义参考）：

- **数值类**（金额、天数、次数等连续数值）→ 按值域切成**不超过 5 个**档位，每档在下一步对应一条**数值区间条件**的 `workflow.search`（如报销按"报销总金额"分 4 档：≤100 元、100-1000 元、1000-10000 元、>10000 元）；
- **选项类**（紧急程度、问题分类、费用类型等单选/枚举）→ 按选项值组织分组，每（组）选项对应一条 **eq 条件**的 `workflow.search`（`filterFields` 选项类 value 用 `选项名称(选项ID)`——选项 ID 取该字段 `options` 中对应选项的 `id`）；
- **时间类**（系统接收时间、表单日期字段如接收日期/到期日）→ 按时间窗组织分组（如今天/本周/更早），每个时间窗对应一条**时间条件**的 `workflow.search`；
- **确无价值字段才允许平铺（唯一例外）**：该分组 `formFields` 中无**数值/选项/时间**三类可分层字段、或字段均无业务分层意义（如选项全为废弃/无意义）时，才可平铺——正常查询数据，不分段；平铺前须基于 `formFields` 作出该判断，不得以平铺为默认。

构造各档的 `filterFields` 时：**有 `formFields` 就优先用它的 ID**——`fieldName` 用 `字段名(字段ID)`（字段 ID 取该字段 `fieldId`）、选项类 value 用 `选项名称(选项ID)`（选项 ID 取 `options` 中对应选项的 `id`）；`formFields` 已提供精确 ID 时**不要退回纯名称试探**（纯名称在存在重名字段/选项时会触发多候选澄清，多花一轮）。

**低版本模式（OA < `10.0.9909.01`，无 `formFields` 来源）**：直接传纯字段名即可——CLI 会读该工作流的表单字段元数据做解析，不需要模型事先拿到字段 ID；解析不出会报错并列出候选（见「表单字段筛选」）。**禁止凭记忆拼字段名或改用系统条件硬凑**：这类条件会被丢弃，返回的是未筛选的全量数据。

各档/组各对应一条查询计划（与骨架一致，走同一次 `planJson` 或单条并行），分档应保证每档有实际数据（数量均衡、避免空档）。

3. **查询计划——把分组计划打包为一次 `workflow.search`（带 `planJson`）调用**：
   - **泛化待办查询（按骨架划好组后）→ 构造 plan**（结构见「planJson 批量编排」）：把特殊组（紧急/超时、转发给您）、业务域展开组、折叠组（≤3）整体写入 `planJson.groups`，一次传入。**CLI 内部自动完成**：特殊组有货探测（读最近一次 `workflow.todoStat` 落盘快照）→ 有货则 `pageSize=100` 分页取全并收集 `requestId` 排除集 → 展开组并行取数并**自动注入排除集**（`condition.exRequestIds` 由 CLI 维护，模型不再手工维护）→ 折叠组按 `countDetails` 代码统计（**不发明细查询**）。返回 `type=workflowSearchPlan`：每个特殊组（含槽位）/展开组给 `total + hasMore + finalMarkdown`，折叠组给 `total + byWorkflow`。**展开组取数由 CLI 取全并自动识别草稿构成**：纯草稿组 `finalMarkdown` 为空、给 `pureDraft=true`；混合/非草稿组 `finalMarkdown` **只含非草稿卡片**（草稿卡片由 CLI 剔除、数量见 `draftCount`）。
     **分页条数（统一窗口）**：分组**不支持各组单独设置分页/条数**——各组统一由顶层 `pageSize` 控制分页与展示大小；**可不传 `pageSize`，不传时每组默认按 10 条分页**。用户/记忆有每页条数要求时按其值传（本次用户明确指定 > 记忆偏好，如"每组显示 20 条"→ 传 20，上限 100）；无任何要求则不传按默认。
   - **聚焦单工作流的字段分组取数**同样走这一次 `planJson`（把各档作为展开组 `condition.filterFields`；`filterFields` 只能用于**单工作流成员**的组）。仅以下场景才用**单条 `workflow.search`**：① plan 中 `status=error` 的组（名称没对上的先按候选与用户确认，改用 `名称(ID)` 后单独补查）；② 某组需看更多**非草稿**明细（`hasMore=true`）时，按该组条件用单条查询**分页查看（每页条数同展示窗口，按需 `current` 翻页），不得一次全量拉取贴屏**；③ 澄清/排障等单条场景。

4. **统一汇总**：`workflowSearchPlan` 返回后——各段卡片来自对应组/槽的 `finalMarkdown` **整段原样粘贴**（红线见「渲染红线」：禁止跨查询拆散重排卡片）；折叠组用 `total`/`byWorkflow` 数量；分组标题（含紧急/超时计数，见「汇总渲染规则」）与标题下一行汇总摘要由模型书写。`status=error` 的组按错误提示修正后单条补查，不阻塞其它组渲染。

## planJson 批量编排

**定位**：把「执行流程」步骤 3 的**多路查询执行**折叠为**一次调用**——模型的分组决策（骨架、业务域归纳、组名、折叠取舍）**完全不变**，变的只是"执行"下沉到 CLI：特殊组取全与排除集、展开组并行取数、折叠组统计均由 CLI 确定性完成，**稳定性更高（去重/ID 构造/翻页从"模型纪律"变为"CLI 保证"）、工具调用从 2N+1 次降为 todoStat + plan 共 2 次**。

**约束（plan 规划上限）**：`planJson.groups` 展开组 + 折叠组**总数 ≤ 8**——超出时该次 plan 调用失败并返回错误。规划时需把同业务域展开组合并，**不可按"组数量不限"字面意思拆分过细**。

**前置**：必须已执行过 `workflow.todoStat`（CLI 读其落盘快照做特殊组有货探测与折叠组统计——与模型规划用的是同一份口径）。

**planJson 结构**：

```json
{
  "category": "todo",
  "specialGroups": ["urgentOvertime", "forwardToSelf"],
  "groups": [
    { "groupName": "报销审批", "condition": { "workflow": ["总部费用报销(100003460000000060)", "分支机构费用报销(100003460000000060)"] } },
    { "groupName": "传阅与抄送", "collapsed": true, "condition": { "workflow": ["标准产品需求评审(100003460000000485)"] } }
  ]
}
```

| 字段 | 含义 |
| --- | --- |
| `category` | 固定 `todo` |
| `specialGroups` | 可选，要探测/取数的固定特殊组：`urgentOvertime`（紧急/超时）、`forwardToSelf`（转发给您）；**无货自动跳过（有货才出）**，CLI 据此维护排除集 |
| `groups[]` | 常规分组：`groupName`（组名，仅标注）、`collapsed`（`true`=折叠组：CLI 在 `countDetails` 上按成员∩折叠身份代码统计，**不走明细查询**，须带 `condition.workflow` 成员；缺省=false=展开组取明细）、`condition` |

**`condition` 支持的键**：

| 键 | 值 | 说明 |
| --- | --- | --- |
| `workflow` | `["名称(ID)", ...]` | 组内工作流成员（=or）。**必须用 `名称(ID)` 或纯数字 ID**——ID 取 `countDetails.workflowId`；纯名称直接判该组 `error`（plan 一律 `名称(ID)`，不走名称多候选澄清） |
| `subCategory` | 小分类名称或 tabid | 可选，一般展开组不传（默认全部 tabid=0） |
| `requestLevel` | `"紧急"`/`"紧急(ID)"`/纯 ID | 可选，紧急程度（当前枚举：紧急=2）；纯名称由 CLI 匹配 `requestLevelList`，多命中判 error |
| `receiveTime` | `"开始 结束"`（YYYY-MM-DD，单边空串） | 可选，接收时间窗（"这周收到的"→ 传换算好的日期区间） |
| `createTime` | `"开始 结束"`（YYYY-MM-DD，单边空串） | 可选，发起时间窗（语义同 `receiveTime`；只传一个日期即限到当天） |
| `requestIds` | `["ID", ...]` 或 `"ID,ID"` | 可选，**正向**只查这些流程（语义同 `requestId`） |
| `exRequestIds` | `["ID", ...]` 或 `"ID,ID"` | 可选，**排除**这些流程（语义同 `exRequestId`；与 CLI 自动收集的排除集合并去重） |
| `filterFields` | `[{"fieldName","term","value"}, ...]` | 可选，表单字段筛选；字段名→字段 ID 解析取最近一次待办统计快照里该工作流的 `formFields`，故**只能用于聚焦单个工作流的分组**（`workflow` 只传 1 个成员） |
| `creator` | `"郭杰"` / `"郭杰(ID)"` / `["郭杰","张三"]` | 可选，发起人。纯名称由 CLI 名称转 ID，**0 命中或多命中判该组 `error`**（plan 内不做澄清，多命中请改用 `名称(ID)`）；支持 `"我的"` 等自称词（=当前用户，跳过名称匹配） |
| `workflowType` | `"行政类"` / `"行政类(ID)"` | 可选，所属工作流类型，解析规则同 `creator`（不支持自称词） |

> **折叠组（`collapsed:true`）只支持 `workflow`**：其数量按最近一次待办统计快照统计，`receiveTime`/`createTime`/`requestLevel`/`filterFields`/`requestIds`/`exRequestIds`/`creator`/`workflowType` 一律不参与——带了这些键该组直接返回 `error`，需要该条件时请改为展开组。

**返回结构（`type=workflowSearchPlan`）**：

```json
{
  "type": "workflowSearchPlan",
  "specialGroups": [
    { "groupType": "urgentOvertime", "displayName": "紧急/超时", "excludeCount": 3,
      "slots": [
        { "slotType": "urgent", "total": 1, "hasMore": false, "finalMarkdown": "…纯卡片…" },
        { "slotType": "overtime", "total": 2, "hasMore": false, "finalMarkdown": "…纯卡片…" }
      ] },
    { "groupType": "forwardToSelf", "displayName": "转发给您", "excludeCount": 1,
      "slots": [ { "slotType": "forward", "total": 1, "hasMore": false, "finalMarkdown": "…纯卡片…" } ] }
  ],
  "groups": [
    { "groupName": "报销审批", "status": "ok", "total": 3, "hasMore": false, "pureDraft": false, "draftCount": 0, "nonDraftCount": 3, "finalMarkdown": "…非草稿卡片…" },
    { "groupName": "留言与通知", "status": "ok", "total": 20, "hasMore": false, "pureDraft": false, "draftCount": 19, "nonDraftCount": 1, "finalMarkdown": "…仅该组 1 张非草稿卡…" },
    { "groupName": "待提交草稿组", "status": "ok", "total": 7, "hasMore": false, "pureDraft": true, "draftCount": 7, "nonDraftCount": 0, "finalMarkdown": "" },
    { "groupName": "传阅与抄送", "status": "ok", "collapsed": true, "total": 20,
      "byWorkflow": [ { "workflowName": "标准产品需求评审", "count": 20 } ] },
    { "groupName": "…", "status": "error", "error": "工作流「XX」未匹配到任何对象…（plan 内不做澄清：请把候选原样交给用户确认，再用「名称(ID)」重跑该组）", "clarificationType": "workflow", "clarificationKeyword": "XX", "candidates": [] }
  ],
  "excludeRequestIdCount": 4,
  "displayRules": [ "…" ]
}
```

**渲染要点（对模型）**：

- **分组标题计数**：紧急/超时组 `## 紧急/超时（N 条｜紧急 M 条｜超时 K 条）`——N=该组各槽 `total` 之和、M=urgent 槽 `total`、K=overtime 槽 `total`（0 项省略）；转发给您/展开组 N=对应 `total`；折叠组 N=其 `total`。标题与标题下一行汇总摘要由模型书写，卡片段 `finalMarkdown` **整段原样粘贴**（槽位/组各自成段，组内多段之间用 `---` 分隔）。
- **`status=error` 组**：未取数，不阻塞其它组渲染。**先看它有没有 `clarificationType`/`candidates`**：
  - 带 `clarificationType`（名称没对上）→ **plan 内不做澄清**：把 `candidates` 按「名称(ID)」摆给用户确认，拿到确认后把该组条件改成 `名称(ID)` 重跑该组；**不要**把它当作"该组 0 条"渲染，也不要自行挑一个候选。
  - 不带（`condition` 键不支持、折叠组带了非法条件等）→ 按 `error` 提示修正后，将该组作为**单条 `workflow.search`** 单独补查。
- **`hasMore=true`**：该组的**非草稿**卡片超过展示窗口（窗口大小 = 构造 plan 时传入的 `pageSize`，不传默认 10——CLI 取全判定后只把前 N 张非草稿卡渲染进 `finalMarkdown`），需看更多非草稿明细时按该组条件用**单条查询分页查看（每页条数同展示窗口，按需 `current` 翻页），不得一次全量拉取贴屏**；不要重跑整份 plan。草稿卡片本就不在 `finalMarkdown` 中（数量见 `draftCount`），无需、也不要为"确认草稿性"续查全量。
- **排除集已由 CLI 注入**展开组查询（`excludeRequestIdCount`>0 时），模型无需也不应再手工排除；折叠组数量与排除集不逐条扣减（口径见「组间去重」）。

## 汇报式分组骨架（泛化待办查询）

**定位**：把"秘书向领导汇报待办"的方法论固化为**固定骨架**，取代模型逐会话临场发明的分组体系——分组种类、固定顺序、特殊组是否出现、去重与折叠上限由骨架定死；模型保留的决策空间只有**业务域归纳**（哪些流程归入哪类业务域、如何命名）。骨架仅用于**泛化待办查询**（多工作流、未指明具体流程）；聚焦单个工作流走「执行流程」步骤 2 的字段分组判断，不套本骨架。

**分组结构（固定顺序，有货才出、无货不显示）**：

- **① 紧急/超时组（特殊组）**：`countDetails` 存在 `urgentCount>0` 或 `overtimeCount>0` 的行即有货（数据源为待处理范围内的统计）。**plan 模式：模型在 `planJson.specialGroups` 声明 `"urgentOvertime"` 即可，取数（超时=todo 小分类超时(6)、紧急=`requestLevel`=2）由 CLI 执行**。标题计数按「汇总渲染规则」追加（`## 紧急/超时（N 条｜紧急 M 条｜超时 K 条）`）。
- **② 转发给您组（特殊组）**：存在转发类参与身份（转发接收人、转发接收人(委托)、转发接收人不需反馈、转发接收人不需反馈(委托)，见「参与身份 → 分组去向表」）即有货。**不再单列"上级/领导发起"组**——上级转发与其他人的转发都在本组展示明细；汇总行注明"其中上级转发 N 条"（N 取 `countDetails` 中对应行 `managerForwardToSelfCount` 的归并合计，取不到不编造）；有转发意见时在汇总/摘要体现（取不到不编造）。**plan 模式：声明 `"forwardToSelf"` 即可，取数由 CLI 执行**。
- **③ 业务域展开组（常规组，默认展示明细）**：去向为「业务域展开组」的参与身份对应流程（需亲自处理/重点关注的流程）——**默认按业务域聚合成组**：同一业务域的工作流归并为一组展示明细（组内可含多个工作流，如"报销审批"组=总部费用报销+分支机构费用报销；"合同审核"组=新客户合同审核+老客户增值合同审核）。**仅当**某业务域内待办量过大需分开展示、或同一业务域横跨多个互不相关流程群时，才按工作流/参与节点细分为多个展开组——**默认不得按工作流逐条拆组（同一业务域不得拆成多个可合并的重复组）**。**组名要让人一眼看出组内是什么事**——至少含组内工作流/节点名里的动作词（如"报销审批""合同审核"），不要用"处理""相关事项""综合"之类不传递信息的笼统词收尾。
  **组名硬约束（避免"看不懂"的组名）**：
  - **组内只有一个工作流时，组名直接用该工作流名称**（可去掉"流程/通知/管理"之类冗余尾字）。用户对自己 OA 里的工作流名是熟悉的，**照抄最省事也最易懂**；只有在工作流名过于笼统时才补一个节点名里的实词。
  - **组内有多个工作流时**，才按它们的**共有语义**归纳，且**只能使用组内工作流名/节点名里出现过的实词**。
  - **禁止生造工作流名与节点名里都没有的概念词**（如"阅读""自查""核对""办理""跟踪""相关事项""综合处理"）——这类词不传递任何信息，读者看不出组里到底是什么流程。**判据：把组名里的实词逐个对回工作流名/节点名，对不上的就是生造。**
  - 正反例：工作流「公司重要通知」（节点「查看留言」）→ 组名应为**「公司重要通知」**（✓）；写成**「通知阅读与自查」**（✗，"阅读""自查"既不在工作流名里也不在节点名里）。工作流「流程hotfix-jar测试情况确认」→「流程测试确认」（✓，实词均取自工作流名）。
- **④ 折叠组（常规组，最多 3 个，只显示数量）**：去向为「折叠组」的参与身份对应流程（知会类），同样按业务域归并折叠，**不超过 3 个**，只显示数量与一句汇总，不展开明细。
- **⑤ 需重点关注的流程单独提出（仅针对存在 `requestInfos`、去向为业务域展开组且非纯草稿的分组行）**：`countDetails` 中部分分组行会额外返回组内流程信息 `requestInfos`。对这类行，**结合当前用户岗位/部门/分部身份**逐条看组内流程的标题与字段值，判断是否存在**可能需要用户重点关注**的流程。
  **候选范围 = 同时满足两条的行：① 去向为业务域展开组；② 该行确实带 `requestInfos`**。**没有 `requestInfos` 的行一律不在候选内，整行直接跳过**：`requestInfos` **不是恒在字段**——接口只对**配置了关注字段**的工作流返回，未带的行即没有（这是正常的，**不是数据丢失、也不是"字段值为空"**）；**不要改用标题去判这类行、更不要为它另发查询取 ID**。此外——**去向为折叠组的行（知会类）一律不纳入**：抄送/传阅的语义就是"知会、无需处理"，若内容确需本人行动，发起人会以"转发"送达（那时会进「转发给您」特殊组，明细可见）；**纯草稿行（该行 `draftCount` == `totalCount`，实际去向为「待提交草稿」折叠）也不纳入**——本人尚未提交的草稿不属于"需要重点关注"。
  但不因"该行已在展开组、卡片本就会展示"而跳过（卡片展示只保证"看得到"，不等于"被标为重点"），个别流程仍可能对用户重要：
  - **判定粒度与取值要求**：对候选行的**每一条 `requestInfos`（每个 `requestId`）独立判定**，**禁止用"该行/该工作流整体是什么性质"替代逐条判定**（同一分组行、同一工作流内可同时存在"需本人动作"与"只需他岗动作"的条目，整体贴标签必然误判）；**判定必须依据 `formFieldValues` 的实际取值，不能只看标题**——受众（通知对象）、执行要求等关键信息通常在字段值正文里，标题往往看不出。stdout 里超长字段值会被截到正文开头（条目带 `formFieldValuesTruncated` 标记），**受众/动作信息都在开头，用前缀判定即可**；只有开头确实看不出受众与动作时，才从 `resultFile` 取该 `requestId` 的全文复核，**不要逐条去读全文**。
  - **「`formFieldValues` 为空」≠「没有 `requestInfos`」（两件事，不要混）**：本条指**该行确实带了 `requestInfos`、只是条目里的 `formFieldValues` 为 `null`**（该工作流未配置关注字段值），此时**只依据标题 `requestNameTitle` 判断**，**不得因"没有字段值"跳过该条目**。而**整行没有 `requestInfos`** 是另一回事——它**根本不在候选内**（见上一条），**不要拿它的标题去补判**。
  - **判定依据（只看两件事：动作落在谁身上、这个动作在不在本人岗位职责内）**：**看"该流程要求谁产生什么动作"，而不是"标题主题是否涉及本公司产品/本人的技术领域"**。
    - **决定项（满足才算重点）**：动作落在**本人自身**，且属于**本人当前岗位职责内的通用个人动作**——升级本人客户端、签收本人公文、自查本人账号/设备、确认/反馈本人信息。
    - **排除项（命中即不纳入，无论抬头写得多广）**：① 动作的宾语/接收方是**他人或外部业务角色**（提醒代理商/伙伴/渠道、通知客户、推动客户升级）；② 动作虽写"全员"，但实质是**特定业务岗**的职责（销售/渠道管代理商与伙伴、商务管投标与合同、服务/交付岗管客户补丁推进、HR 管任命、财务管报销制度）——**本人不是那个岗，就不纳入**。
    - **受众措辞只作线索、不作定论**：写"相关同事 / 服务同事 / 销售 / 项目 / 客服 / 商务部 / 各 BU"＝明确不含本人，可快速排除；写"全体员工 / 各位同仁 / 所有同事"**只表示这份函件知会面广（公司群发普遍如此），不等于本人有行动项**，仍须回到上面两项判断。
    - **辅助项（都不能单独定论）**：① 强提示词（如"重要/紧急/尽快/安全/漏洞/截止"）——群发通知几乎全带，**既不能因它纳入、也不能因它排除**；② 与本人岗位/部门/模块相关；④ 长时间滞留未处理。
    **速判表（按序走一遍，命中即定论）**：

    | 步骤 | 看标题/字段值里的什么 | 定论 |
    | --- | --- | --- |
    | 1 | **动作落点**：通知要求**谁**做什么？动作的宾语/接收方是**他人或外部业务角色**（提醒代理商/伙伴/渠道、通知客户、推动客户升级），或"由某部门统一管理/办理" | 落在他人/外部角色 → **不纳入**，本条目到此结束 |
    | 2 | **岗位匹配**：动作宾语是**本人自身**时，再问一句"这件事在我当前岗位/部门真的会发生吗"——若属销售/商务/渠道/服务/HR/财务等**特定业务岗**职责 | 非本人岗位职责 → **不纳入**，本条目到此结束 |
    | 3 | 动作是**通用个人动作**（任何岗位的本人都会做：升级自己的客户端、签收本人公文、自查本人账号/设备） | → **纳入** |
    | 4 | 1~3 都判断不了（正文开头既无动作也无受众信息） | **不纳入**（宁缺勿滥）；确有必要再从 `resultFile` 取该条全文复核**一次** |

    > **抬头写"各位同仁 / 全体员工"不等于本人有行动项**——判据落在"**这个动作能不能由本人这个岗位完成**"，不落在抬头措辞上；也不要因为"我也收到了这条通知"就认定"我也要行动"。① 强提示词与 ② 岗位/模块相关都只作辅助：既不单独构成纳入理由，也不构成排除理由。
    >
    > **判例（对齐用）**：
    > - 「有关《禁止私刻公章、串标围标行为》的通知」——抬头"各位同仁"，但动作是"**提醒代理商和所有伙伴**"，属**销售/渠道岗**职责 → 研发职能岗**不纳入**（✗ 最常见误判：把"我也收到了"当成"我也要行动"）。
    > - 「关于尽快升级微信 APP 的安全通知」——动作是"**升级自己的微信**"，任何岗位的本人都会做 → **纳入**。
    > - 「《电子投标平台注册及使用》商务统一管理通知」——动作"由**商务部**统一管理" → **不纳入**。

    **判定纪律（省时关键）**：**判定是查表不是论证**——每条只写一行结论 + 命中的 `requestId`，**不要为每条写一段分析、不要复述正文**；**同一 `requestId` 不重复辩论**，不要出现"但它是安全通知…""不过我是研发岗…"这类反复自我推翻；条目多时快速过表。
    **宁缺勿滥**——只提真正相关的，不要把带 `requestInfos` 的流程全部提出；但**不等于一条都不提**——若确有条目命中速判表第 3 步（**本人自身 + 本人岗位的通用个人动作**）却整组全部不提，即为漏判。
  - **存在** → 把这些流程**单独提出来**展示：建一个独立展开组承载（`condition.requestIds` 正向列出这些流程 ID，组名如「需要您重点关注的流程」），并让**其原所属分组排除这些流程**（该组 `condition.exRequestIds`），避免同一流程跨组重复展示。**判定与取 ID 在同一步完成**：`requestInfos[].requestId` 就在你用来判定的那条数据里，逐条判定时把它一并记下即可，**不要为取 ID 再跑一次脚本、或再读一次输出**。**`requestInfos[].requestId` 是该流程 ID 的唯一来源——任何情况下都不得为了取 ID 再发起一次 `workflow.search`**（那会白白多出整整一轮工具往返，实测 +10s 以上）；若某个流程拿不到 ID（即该行没有 `requestInfos`），**就按上一条规则不纳入候选**，它在自己的业务域展开组里照常展示，不要为它单独取数。
  - **不存在** → 忽略本条，按常规骨架继续，不要为此额外取数；**判为"不纳入"的流程（含全部不纳入与个别不纳入）一律不得在分组摘要里附加"建议单独查看/建议关注/建议核实"之类主观提示**——排除即彻底排除，这类提示与"不纳入"的结论自相矛盾，只会让读者怀疑是否漏判。
  - **已在特殊组（转发给您组/紧急/超时组）的流程**：明细卡片已在特殊组展示，**不重复单独提出**（特殊组流程本就被 CLI 注入排除集，单独提出也取不到）；但这类流程若带 `requestInfos`，其**分组汇总摘要要引用关键内容**——即 `requestInfos[].formFieldValues` 里的字段名:值（**字段名随工作流不同**），挑最能说明"要关注什么"的项。**这是硬要求**：只要该行存在 `requestInfos` 且 `formFieldValues` 有值，摘要里就**必须出现至少一项 `字段名:值`**；只复述标题、或只描述"已停留 X 天/需查看/待反馈"之类状态，**均视为未完成引用**。仅当该行没有 `requestInfos`、或字段值全为空时才退化为按标题简述。

**规划纪律（省时关键，避免在建 plan 时反复权衡）**：

- **一次成型**：按骨架把 `planJson` 一次写完，**不列备选方案、不自我辩论、不为同一组算两遍**——实测建 plan 那一轮的模型推理占了该轮耗时的绝大部分。
- **一个业务域 = 一个展开组**：同一业务域内的多个工作流**一次性列进同一组的 `condition.workflow`**（如「待提交草稿」组直接列 3 个纯草稿工作流），**不要拆成多个组**，也不要为"拆还是合"来回权衡。
- **纯草稿行不单独建组**：草稿性直接由 `countDetails` 行的 `draftCount` 判定（该组覆盖的 stat 行 `draftCount` 合计 == `totalCount` 合计即为纯草稿），数量用 `draftCount` 相加即可；**不要为了验证草稿性再扩大取数或另建探测组**。
- **组数上限：展开组 ≤ 6、折叠组 ≤ 3**。超出时按骨架顺序保留靠前的组，把知会类进一步归并；**不要因为"组数多了"而反复重排**。
- **`specialGroups` 照常全声明**（`["urgentOvertime","forwardToSelf"]`）——无货 CLI 会自动跳过，**不必先探测再决定要不要声明**。

**组间去重（硬约束）**：**任一流程只出现在一个分组**。**plan 模式由 CLI 保证**——CLI 先取全特殊组并把其 `requestId` 排除集自动注入各展开组查询，模型无需手工排除（仅需把特殊组声明进 `planJson.specialGroups`、展开组条件按业务域一次划清，不把同一工作流拆到多个展开组；**唯一例外是 ⑤ 单独提出的重点流程**——其 ID 由模型写进原所属分组的 `condition.exRequestIds`）。特殊组之间天然不重叠（转发流程不含超时/紧急统计，紧急/超时统计只覆盖待处理数据，无需互相排除）。折叠组只显数量，数量口径=对应身份 `countDetails` 归并值（多组归并时按归并口径汇总，无需与特殊/展开组逐条核对扣减）。

## 七个维度（辅助判断，不决定分组结构）

**七个维度不是七个固定分组，也不决定"分几组、展开还是折叠"**——分组结构与去向由「汇报式分组骨架」与「参与身份 → 分组去向表」确定。七个维度仅作骨架内的**辅助判断**：帮助模型做业务域归纳（哪些流程归并成一个业务域组）、组内/组间排序与摘要措辞。对 `countDetails` 每一行（工作流 × 节点 × 参与身份三元组）与明细卡片**综合**参考：

| 维度 | 分析要点 |
| --- | --- |
| 1. 用户身份 | 结合当前用户岗位、部门、分部（分部可能为空则忽略）推断其管理范围和所属业务域，辅助业务域归纳与排序：职责强相关（如总经理看经营决策、部门负责人看本部门事务、项目负责人看项目交付）的流程优先 |
| 2. 参与身份 | 当前节点上用户的参与身份——**归类直接查「参与身份 → 分组去向表」**，不再自行权衡"操作者优先于知会类"（该决策已表格化）；身份语义清单见「参与身份说明」 |
| 3. 时效风险 | 紧急/超时已由特殊组机制承载；骨架内用于组内排序与摘要强调（如同组内先排停留更久的） |
| 4. 低关注识别 | 抄送、传阅等知会类流程归折叠组候选（去向表已划走），用于决定折叠组按业务域归并与写汇总，不展开明细 |
| 5. 转发 | 转发类流程固定进"转发给您"特殊组展示并呈现转发意见（去向表已划走）；本维度不再单独成组 |
| 6. 组织关系 | 来源为本人上级的流程：上级**转发**在转发组汇总行说明条数（骨架②）；非转发类的上级发起仅作排序/摘要提示，**不再单独成组** |
| 7. 阻断程度 | 评估当前节点不处理的影响：对人员安排、项目交付、客户服务或资金业务的影响，影响大的在组内排序靠前并在摘要强调 |

## 参与身份说明

**`isRemark` 码位 ↔ 参与身份**（`workflow.search` 的 `cards[].isRemarkName` 与 `workflow.todoStat` 的 `countDetails[].isRemarkName` 都是这套身份；`todoStat` 的 `isRemarkName` 由服务端直接下发，列表侧的 `isRemarkName` 按本表由数字码位映射得出）：

| 码位 | 参与身份 | 行为口径 |
| --- | --- | --- |
| `0` / `1` | 节点操作者 / 节点操作者(委托) | 正常待处理，可提交/退回/转办 |
| `10` / `11` | 意见征询接收人 / (委托) | 征询反馈 |
| `20` / `21` | 传阅接收人 / (委托) | 传阅需批示 |
| `30` / `31` | 抄送接收人 / (委托) | 抄送需提交 |
| `40` / `41` | 转发接收人 / (委托) | 转发需批注 |
| `60` / `61` | 传阅接收人不需反馈 / (委托) | 查看即已办（不需批示） |
| `70` / `71` | 抄送接收人不需反馈 / (委托) | 查看即已办（不需提交） |
| `80` / `81` | 转发接收人不需反馈 / (委托) | 查看即已办（不需批注） |
| `100` | —（不可操作） | 已处理完，`canSubmitRejectTransfer=false` |

- **尾位 `+1` 一律是「(委托)」变体**；上表**只覆盖有据可查的码位**——「超时指定干预人」「异常处理指定干预人」两族的码位尚未确证，**遇到未列出的码位不要推断身份**（列表侧返回空串）。
- 判身份一律看 `isRemarkName` **或查本表**，不要按节点名/流程名猜；`isRemark < 100` 才可操作，`100` 不可操作。

- **节点操作者**：需要审批流程的身份，拥有当前节点的审批操作权限，可对流程进行同意、驳回等处理。
- **节点操作者(委托)**：节点操作者的代理人，代为行使原审批人的全部审批权限，可代替本人完成节点审批操作。
- **超时指定干预人**：流程到达超时条件后，被指定介入处理流程的人员，有权限干预超时待办、推进流程流转。
- **超时指定干预人(委托)**：超时指定干预人的代理人，可代替原干预人执行超时流程的干预处理操作。
- **异常处理指定干预人**：流程发生异常（报错、卡住等）后，被指定介入排查、处理该异常流程的人员。
- **异常处理指定干预人(委托)**：异常处理指定干预人的代理人，可代替本人完成异常流程的介入处理工作。
- **意见征询接收人**：流程发起意见征询时的接收对象，需要查看征询内容，并提交反馈意见。
- **意见征询接收人(委托)**：意见征询接收人的代理人，可代为查看征询信息、提交反馈意见。
- **传阅接收人**：由流程参与人手动传阅给自己，自己可以在任意时间查看流程，查看后需要提交阅读意见。
- **传阅接收人(委托)**：传阅接收人的代理人，代替本人查看传阅流程并提交阅读意见。
- **抄送接收人**：流程到达指定节点时抄送给自己，自己可以在任意时间查看，并在提交时需要填写签字意见。
- **抄送接收人(委托)**：抄送接收人的代理人，代替本人查看抄送流程、填写签字反馈意见。
- **转发接收人**：由流程参与人手动转发给自己，可随时查看流程内容，并在提交时需要填写反馈意见。
- **转发接收人(委托)**：转发接收人的代理人，代替本人查看转发流程并提交反馈意见。
- **传阅接收人不需反馈**：流程到达指定节点时传阅给自己，自己可以在任意时间查看流程，查看后就会变为已办，不需要提交阅读意见。
- **传阅接收人不需反馈(委托)**：传阅接收人不需反馈的代理人，代替本人查看传阅流程，查看后流程标记为已办，无需反馈意见。
- **抄送接收人不需反馈**：流程到达指定节点时抄送给自己，自己可以在任意时间查看，查看后就会变为已办，无需反馈意见。
- **抄送接收人不需反馈(委托)**：抄送接收人不需反馈的代理人，代替本人查看抄送流程，查看后流程标记为已办，无需填写签字意见。
- **转发接收人不需反馈**：由流程参与人手动转发给自己，自己可以在任意时间查看流程，查看后即变为已办，无需提交反馈意见。
- **转发接收人不需反馈(委托)**：转发接收人不需反馈的代理人，代替本人查看转发流程，查看后标记已办，不需要反馈意见。

## 参与身份 → 分组去向表

汇报式分组中参与身份的**确定性归类**（查表即得，覆盖上方 20 条身份；不要自行理解身份业务含义后再自由归类）。特殊组流程由 CLI（`planJson` 批量编排）按排除集从常规组剔除：

| 去向 | 参与身份 | 规则 |
| --- | --- | --- |
| 紧急/超时组（特殊） | 不限身份，按该行 `urgentCount>0` / `overtimeCount>0` 判定 | 有货才出、最先展示；进入排除集 |
| 转发给您组（特殊） | 转发接收人、转发接收人(委托)、转发接收人不需反馈、转发接收人不需反馈(委托) | 全部转发流程在此展示明细；汇总行注明上级转发数（取 `managerForwardToSelfCount`）；进入排除集；**不再单列"上级/领导发起"组** |
| 业务域展开组（模型归纳） | 节点操作者、节点操作者(委托)、超时指定干预人、超时指定干预人(委托)、异常处理指定干预人、异常处理指定干预人(委托)、意见征询接收人、意见征询接收人(委托) | 需亲自处理/重点关注的流程，按业务域/工作流/节点归纳为多个展开组 |
| 折叠组 ≤3（模型归纳） | 传阅接收人、传阅接收人(委托)、传阅接收人不需反馈、传阅接收人不需反馈(委托)、抄送接收人、抄送接收人(委托)、抄送接收人不需反馈、抄送接收人不需反馈(委托) | 知会类按业务域归并折叠，只显示数量 + 一句汇总 |

> 参与身份行与紧急/超时、转发的判定相互独立：同一行即使 `urgentCount/overtimeCount>0` 且身份是转发接收人，也按"特殊组优先"展示（紧急/超时统计只覆盖待处理数据、转发流程不含超时/紧急统计，故实际极少重叠；如重叠，按特殊组优先并从常规组剔除）。

**分组决策纪律（一次划组，不回头复查）**：

- **只按 `countDetails` 的身份/数量字段 + 上表划组**（`isRemarkName`/`isRemark` 代码 → 去向，查表即得），划完即走，**不要反复自我确认**（"这行到底展开还是折叠"只查一次上表，同一决策不重查第二遍）；
- **禁止按流程名/节点名猜测业务语义**来决定分组：如看到节点"填写留言/提交报销单/请假人请假"不要去猜"这是不是草稿/是否要退回"，看到工作流名"公司重要通知/人事任命公文"不要猜"这是不是知会类"——**参与身份已由 `isRemarkName` 给出、去向已由表定死**，节点名只用于业务域归并与组内排序，不影响去留；
- **草稿与否不影响分组去向**：某行明细可能是"本人发起的草稿/待提交"（卡片带 `` `草稿` `` 徽标），但它在待办里出现就按 `isRemarkName` 正常归类——是否折叠见「汇总渲染规则」的草稿折叠条目，分组规划阶段不因"可能是草稿"而改变去向。

## 常见业务重点字段与推荐分组维度

模型在做智能分组时，对待办所属的工作流类型识别后，可参考下表判断该类流程的"重点关注字段"与"建议分组维度"，用于做**字段分组判断**（聚焦单个工作流时）与**业务域归纳、摘要措辞**（泛化待办走汇报式骨架时）；下表不决定分组结构本身：

| 流程类型 | 重点关注字段 | 建议分组维度 |
| --- | --- | --- |
| 报销 | 金额、费用类型、发票、部门、项目、预算余额 | 金额区间、费用类型、部门、项目、是否超标 |
| 请假 | 请假类型、时长、日期、部门、剩余假期 | 请假类型、时长、部门、是否同组多人请假 |
| 采购 | 品类、金额、供应商、预算、比价情况、交付日期 | 品类、金额区间、供应商、是否预算内、紧急程度 |
| 合同 | 金额、到期日、主体、付款节点、条款、风险等级 | 合同金额、到期日、我方/对方主体、风险等级 |
| 用印 | 印章类型、文件类型、用印次数、授权范围、涉密等级 | 印章类型、文件类型、是否涉密、授权范围 |
| 人事 | 类型（入转调离）、部门、生效日期、薪资/职级、编制 | 类型、部门、生效日期、是否涉及薪资调整 |
| IT 权限 | 系统、权限等级、数据敏感度、离职/转岗关联 | 系统、权限等级、是否敏感数据、岗位变动 |
| 售后工单 | 紧急程度、客户价值、受理时间 | 紧急程度、客户价值、受理时间 |

> 上表**只是"看到这类业务可以往哪些角度看"的举例，不是保留字、不是可选枚举、也不代表你的环境里存在同名工作流**。流程类型一律按当前环境里该工作流的**真实名称与真实表单字段**判断：表里没列的业务照同一方法自行归纳，表里列了的若环境里没有就忽略。**禁止拿表里的类型名去匹配、筛选或改写用户说的工作流名**——用户口中的"问题流程""报销流程"等，指的都是他环境里的具体工作流，必须照原话走工作流名解析（多命中就澄清），不要往本表上套。

## 汇总渲染规则

- **汇报分组顺序（固定）**：紧急/超时组 → 转发给您组 → 「需要您重点关注的流程」组（⑤ 单独提出的重点流程，有货才出）→ 业务域展开组 → 待提交草稿 → 知会类折叠组（≤3）。有货才输出、无货不显示，全部为空的分组不出现；**任一流程只出现在一个分组，不得跨组重复展示**。
- **草稿/待提交类展开组 → 折叠为一组**：草稿判定由 **CLI 在 plan 取数阶段完成**（取全该组明细、逐条按状态识别本人待提交草稿），模型**直接以返回的 `pureDraft`/`draftCount` 为准，不要再看卡片猜、也不要为判定草稿性而续查全量**：
  - **规划层草稿/退回识别（stat 行计数字段）**：`countDetails` 行带 `draftCount`/`pendingCount`/`beRejectCount`/`nodeTypeName`。划组时若某候选展开组覆盖的 stat 行 `draftCount` 合计 == `totalCount` 合计 → 该组即**纯草稿组**，直接把该组划入「待提交草稿」折叠（不放进展开组明细）；**不要为此扩大取数去验证**。组内 stat 行 `beRejectCount` 合计 >0 → 汇报摘要注明"含 N 条被退回（需重新提交）"。分组标题主计数仍用 `totalCount`，`pendingCount` 仅作汇报口径参考、不据此改写标题（`totalCount` 与三字段非严格相等）。
  - **`pureDraft=true`**（该组全部为草稿，`finalMarkdown` 为空）：该组**不出现标题也不逐条渲染**，全部并入折叠组 `## 待提交草稿（N 条）`（N=各 `pureDraft` 组 `draftCount` 之和），置于业务域展开组之后、知会折叠组之前，组下写一句汇总（列出并入的各工作流与数量、停留节点——停留节点取该组 `countDetails` 行 `nodeName`，不要臆造）；需要看明细时按该组条件用单条 `workflow.search` 分页查看。
  - **`pureDraft=false`**：该组 `finalMarkdown` 已由 CLI**只含非草稿卡片**（草稿卡片被剔除、数量见 `draftCount`），直接整段原样粘贴渲染；分组标题计数用返回 `total`，标题下一行汇总可注明"其中 N 条为您起草的草稿、已并入「待提交草稿」"。混有草稿与真待办时**不再例外展开草稿卡**。
  - 本折叠只写数量与汇总、不粘贴任何卡片，故不与「原样粘贴边界」冲突（该红线约束的是"要粘贴卡片时必须整段粘贴、不拆散重排"，而非强制每组必须贴卡）。
- **顶部汇总行（可选）**：所有分组之前，可先输出一行整体汇总；**首要数字用「需您亲自处理」口径**（`workflow.todoStat` 返回的 `pendingTotal` 归并合计）——整体待办常含大量知会类（抄送/传阅可占九成以上），不要用含知会类的总数开头造成"待办很多"的错觉；**「需您亲自处理」已含 ⑤ 单列的重点流程，不要再单独相加**（避免读起来像重复计数）。**不要为了"凑齐栏目"去提某类为空的数据**——见「渲染红线」的空组约束。
- **`workflow.search`/plan 的 `finalMarkdown` 不输出统计行**，只有纯流程卡片列表——**分组名称由模型输出**，不要期待 CLI 给分组标题。
- 每个分组标题下需要生成一行对该分组流程内容的汇总摘要。**摘要只写能从返回数据核实的内容**——`字段名:值`、数量、停留时长、节点名都可以写；**不要写"最新 N 条""最早一条""这批里最重要的"这类没有依据的排序性/评价性断言**（卡片顺序不等于时间顺序，凭感觉下结论即为臆造）。
- 全部为 0 的分组不展示。
- **分组标题数量**：`## 分组名（N 条）`；该分组存在紧急或超时流程时，在条数后继续追加对应计数——`## 分组名（N 条｜紧急 M 条）`、`## 分组名（N 条｜超时 K 条）` 或 `## 分组名（N 条｜紧急 M 条｜超时 K 条）`，M/K 为 0 的项省略不写。计数口径：紧急/超时组 N=其 `slots` 各槽 `total` 之和、M=urgent 槽 total、K=overtime 槽 total；其余展开组 N=该组返回 `total`；折叠组 N=其 `total`。
- **卡片超时/状态徽标由 CLI 生成**：卡片标题后的 `` `草稿` ``/`` `已超时` ``/`` `已结束` `` 等徽标是 `finalMarkdown` 自带内容，渲染时**原样保留、不要删除，也不要自行给卡片补加"紧急/超时"等文字标记**——超时/紧急信息由分组标题计数表达。**徽标规则（CLI 已按此生成，不要质疑或改写）**：审批中不显示徽标；`已超时` 仅在流程未结束时出现（`已结束` 的卡片不得有超时效果）。
- **分组标题**：用 Markdown 二级标题 `## `，独占一行。
- **不要在分组标题前加序号**（如①②③ / 1.2.3.），分组顺序按用户最可能关注的顺序展示。
- **分组之间明显分隔**：上一分组的最后一张卡片与下一分组标题之间留空行（建议再补一行 `---` 让分组边界更清晰）。
- **禁止（仅限本节的分组卡片渲染）**：不要把卡片输出成 Markdown 表格、也不要压成连续文本编号列表——卡片一律原样粘贴 CLI 生成的 `finalMarkdown`；不要自行重算或改写各组数量。**本条只约束分组卡片渲染，不适用于其它场景**：发起/修改流程的表单预览与明细表按 [`workflow-create.md`](workflow-create.md) 的规则展示（明细表**必须**用表格列展示），批量操作结果按 [`workflow-batch.md`](workflow-batch.md) 用表格展示。

**渲染纪律（省时关键）**：分组顺序、标题计数口径、顶部汇总行口径、卡片粘贴边界都已在本节与「渲染红线」给定——**照做即可，不要重新推导、不要反复确认**（避免"这个组该不该排前面""汇总行要不要含草稿"这类来回权衡）。进入渲染阶段后只做三件事：按固定顺序拼接各组已取到的内容、写分组标题、为每组写一行汇总。**结尾不写说明句**——不写"依据您的历史偏好…"这类，也**不得附带任何 0 计数、类别清单，或"某某类别为空/未列出/不涉及"之类表述**（口径见「渲染红线」空组约束）。

## 渲染红线

`finalMarkdown` 是 CLI 最终交付的渲染内容，**必须一字不改原样输出**——禁止重排、压缩、改写成单行、添加标题/emoji、替换占位文案；**不得把分组标题/卡片转写成自己的话后加壳重述**。卡片间 `---` 分隔。如需在 `finalMarkdown` 前后添加自然语言引导，仅限引导句本身，不得改动内部任何内容。

**原样粘贴边界（跨多次查询）**：一个分组下的卡片必须来自该组对应的那一次查询的 `finalMarkdown` 整段粘贴；禁止从多次查询结果中拆散单张卡片手工归并、重排或改写（含标题链接格式 `[标题](url)` 与加粗、`` `草稿` `` 徽标、分隔线）。多次查询各自的结果只能以各自的 `finalMarkdown` 分段呈现。

**分组边界先于查询确定（规划期约束）**：哪些内容归入哪个分组、每组对应哪条查询，在生成查询计划时即锁定（一个展开分组对应且仅对应一次查询，见「执行流程」步骤 3）；查询完成后**禁止再按内容语义临时跨查询归并卡片**。

**用户对已展示结果的更正：只改呈现、不重跑取数**：用户对**上一轮已给出的汇报**做补充或纠错时（如"重点组第一条其实是转发给我的，意见是请知悉""这条应该归到 X 组"），先分清是哪一类——

- **新数据需求**（要求查别的范围、换条件、看更多）→ 正常走查询流程，与本条无关。
- **展示层更正**（指出某条的性质/归属不对，或补充一条信息）→ **不要重跑 `workflowSearchPlan`、不要重新取数**：数据没有变化，变的只是呈现。按下面三档处理，**取成本最低的一档**：
  1. **只标注（默认档）**：分组与卡片都不动，在**受影响分组的汇总摘要里补一句**用户提供的信息（如"其中 1 条经他人转发给您，转发意见：请知悉"）。
  2. **移出**：用户明确说"不要放在这一组"时，回复里把该条从该组去掉——该组标题计数按剩余条数写、该张卡片不贴，**其余卡片仍照原 `finalMarkdown` 整段粘贴**（"用户指令驱动的删减"不属于跨查询拆散归并，不违反上面的渲染红线）。
  3. **换组重出**：**仅当用户明确要求**"重新出一份 / 把它挪到 X 组并重出"时，才重跑 plan，且**必须复用上一轮那次的 `planJson`、只改动受影响的分组**（不重新 `todoStat`、不重新读文档）。

> **代价对照**：重跑一次 `workflowSearchPlan` ≈ **1 轮工具往返 + 30~50s**（实测一次更正重跑耗时 51.0s，其中大半是"到底要不要重跑"的自我辩论）；而 ①② 两档是**零工具调用**的。**用户没有明确要求重出报告时，一律不要重跑**。用户表达是陈述句、看不出想要"改措辞"还是"重出报告"时，**用一句话问清再动手**（如"要我把这条移到转发区，还是只在摘要里标注？"）。

**特殊组不接受用户口述注入（机制边界，遇到就地标注）**：`specialGroups`（`forwardToSelf` / `urgentOvertime`）的成员**只能由 `countDetails` 的参与身份行决定**，CLI 按此取数——**用户口述的条目无法注入这些特殊组**（例如某条在 `countDetails` 里的身份是"节点操作者"，用户说它"是转发给我的"，系统口径上它**不会**出现在「转发给您」组）。遇到这类口径冲突：**在摘要里如实标注用户提供的信息即可，不要为此重建分组、更不要自造计划外分组**（如自造一个「转发给您的通知」）——**分组归属一律以 `countDetails` 的参与身份为准**。

**空组/空数据一律不出现（硬约束）**：**紧急、超时、转发给您、上级转发**这四类数据不存在或计数为 0 时，回复里**任何位置都不得出现**——不写空分组标题（如 `## 紧急/超时（0 条）`）、不写说明句（如"没有紧急、超时以及上级转发的待办"）、**更不得在回复末尾追加一句此类总结**。**有则按骨架展示，无则整类静默省略**。同类附加计数（如"其中草稿 M 条 / 被退回 K 条"）M/K 为 0 时同样直接不写。

**"任何位置"的口径（最容易漏的地方，逐条对照）**——为 0 的类别要**只字不提**，**连"为什么没列"也不许解释**：

- ❌ 结尾说明句里夹带：`说明：本次分组依据您的历史偏好（每页 5 条）；紧急/超时这一类当前计数为 0，故未列出。`——**夹带 0 计数不允许**；回复里也**不再出现"依据了记忆 / 历史偏好"这类说明**，这样的结尾说明句整句都不写。
- ❌ 其它分组的汇总摘要里带一句：`……动作对象指向客户或商务部等业务角色，无紧急、超时。`
- ❌ 顶部汇总行里写 `紧急 0 条 / 超时 0 条`。
- ❌ 换任何说法的否定式提及：`本次不涉及紧急/超时`、`暂无紧急事项`、`未列出的类别为空`、`其余类别无数据`。
- ✅ 正确做法：**把这一类当成根本不存在**，一个字都不写；读者只会看到有内容的分组。

**卡片形态由 CLI 生成，模型不得改造**：卡片第一行是标题（`[标题](url)` 链接 + 可选 `` `草稿` ``/`` `已超时` `` 徽标），其后是辅助信息行——**待办＝发起人/当前节点/停留时长；已办、全部＝发起人/当前节点/发起时间；我发起＝当前节点/发起时间**（由 CLI 按 `category` 生成）。模型**不得改写、不得增删辅助信息行**；卡片内与自写的汇总摘要里**都不得出现** `requestId`、`isRemark`、`canSubmitRejectTransfer`、紧急程度等技术/内部字段。**标题必须独占一行并保持正文默认黑色**——不要把整张卡片放进 blockquote（宿主会把标题渲染成灰色），也不要把多张卡片连成一个连续 blockquote；辅助信息之间用适当空格分隔，**不用点号 `·`**。

## 智能分组示例

> 以下示例适用于智能分组模式（OA ≥ `10.0.9909.01`），为**示意**（角色与流程为演示，非真实数据）。示例 1-3 为泛化待办查询，统一按**汇报式分组骨架**推演（统计 → 按去向表划组 → **构造 planJson 一次调用取数** → 按固定顺序渲染）；示例 4 为聚焦单个工作流的字段分组样板（独立路径，不套骨架）。要点：分组标题与标题下汇总摘要由模型书写；卡片来自各组 `finalMarkdown` **原样粘贴**；展开组 N 取该组 `total`、折叠组 N 取 `total`/`byWorkflow`；卡片自带徽标保留原样，模型**不要**再给卡片补加"紧急/超时"等文字。

**示例 1：总经理问"今天有哪些待办需要我处理？"**（完整骨架：特殊组 + 业务域展开 + 折叠）

- 用户身份（oaContext）：岗位=总经理，部门=公司管理层，分部为空（忽略）
- 统计要点（countDetails 示意）：借款申请 1（操作者，超时 1）；项目付款说明书盖章 1（操作者，紧急 1）；总部费用报销 1、分支机构费用报销 1（操作者）；渠道协议用印申请 1（转发接收人，上级转发 1）；传阅 12、抄送 8（知会）
- 划组（按去向表）：① 紧急/超时组有货（借款超时 + 盖章紧急）→ 特殊组；② 转发给您组有货（渠道协议用印，上级转发）→ 特殊组；③ 操作者流程按业务域归纳 →「费用报销审批」展开组（总部+分支 2 个工作流并一组）；④ 知会类 →「传阅与抄送」折叠组
- plan 构造（示意）：`planJson` 一次传入——`specialGroups:["urgentOvertime","forwardToSelf"]`；`groups` 含展开组「费用报销审批」（workflow=总部+分支两个 `名称(ID)` 成员）与折叠组「传阅与抄送」（`collapsed:true`，workflow=知会类成员）。CLI 自动：探测到紧急/超时与转发有货 → 分别取全（收集 3 条 requestId 排除集）→ 展开组并行取数并自动注入排除集 → 折叠组统计数量。返回 `workflowSearchPlan` 后按固定顺序渲染：

```markdown
## 紧急/超时（2 条｜紧急 1 条｜超时 1 条）
> 借款申请 1 条已超时、付款说明书盖章 1 条紧急（需实体用印），建议优先处理。

**1. [借款申请-程启明-2026-08-21](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)** `已超时`  
发起人：程启明　　当前节点：总经理审批　　停留时长：6小时5分钟

---

**2. [项目付款说明书盖章-恒越智能](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：陈志远　　当前节点：总经理审批　　停留时长：2小时10分钟

---

## 转发给您（1 条）
> 其中上级转发 1 条：分管副总转发渠道协议用印审批，意见"请尽快用印"，建议优先。

**1. [渠道协议用印申请-2026-08-20](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：行政部　　当前节点：总经理审批　　停留时长：3小时10分钟

---

## 费用报销审批（2 条）
> 总部费用报销 1 条、分支机构费用报销 1 条。

**1. [总部费用报销-2026-08-22](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：李明远　　当前节点：总经理审批　　停留时长：5小时

---

**2. [分支机构费用报销-2026-08-23](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：周敏　　当前节点：总经理审批　　停留时长：1小时

---

## 传阅与抄送（20 条）
> 传阅 12 条、抄送 8 条，无需处理，可稍后查看。
```

**示例 2：普通员工问"我这周收到哪些待办？"**（无特殊组时骨架退化，只剩展开 + 折叠 + 待提交草稿）

- 用户身份（oaContext）：岗位=模块负责人，部门=流程引擎研发部，分部=产品研发中心
- 统计要点（countDetails 示意）：Jar包&前端NPM发版流程 1、E10客户问题支持解决流程 1（操作者，无紧急/超时）；某流程 3（操作者，`draftCount`=3=totalCount → 纯草稿）；标准产品需求评审抄送接收人 2（知会）
- 划组（按去向表）：① 紧急/超时组、② 转发给您组均**无货不出现**；③ 操作者流程按业务域归纳 →「研发处理」展开组（2 个工作流并一组）；纯草稿行 → 「待提交草稿」折叠；④ 抄送类 →「抄送与传阅」折叠组
- plan 构造（示意）：`specialGroups` 不声明；`groups` 含「研发处理」展开组（workflow=2 个工作流成员，`condition.receiveTime:"2026-08-24 2026-08-28"`）、纯草稿展开组（`pureDraft=true`，不渲染）、「抄送与传阅」折叠组（`collapsed:true`）。CLI 自动跳过特殊组（无排除集）、展开组并行取数、折叠统计。

```markdown
## 研发处理（2 条）
> Jar 包发版确认 1 条、E10 客户问题跟进 1 条。

**1. [Jar包&前端NPM发版流程-2026-08-26](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：李明远　　当前节点：发布确认　　停留时长：1小时30分钟

---

**2. [E10客户问题支持解决流程-2026-08-27](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：陈志远　　当前节点：开发人员自动接收任务　　停留时长：40分钟

---

## 待提交草稿（3 条）
> 某流程 3 条为您起草、停留于"填写留言"节点，尚未提交。

---

## 抄送与传阅（2 条）
> 标准产品需求评审抄送接收人 2 条，无紧急/超时，可稍后处理。
```

**示例 3：部门经理问"我的费用报销待办有哪些？"**（意图聚焦单个工作流 → 字段分组样板，独立场景）

- 用户身份（oaContext）：岗位=部门经理，部门=流程引擎研发部，分部=产品研发中心
- 意图判定：聚焦单个工作流（总部费用报销）→ **必须先做字段分组判断**；`countDetails` 中该工作流待办 8 条（>5）→ 需按字段分组，不得平铺
- formFields 核对（示意）：`报销总金额`（数值）、`费用类型`（Select：差旅费/招待费/办公费/交通费）、`发票张数`（数值）、`费用归属部门`（关联）、`备注`（文本）——结合「常见业务重点字段」报销行（金额、费用类型…），存在数值/选项可分层字段 → 按**费用类型**（选项类）组织分组
- 查询计划（示意）：差旅费组 `condition:{"workflow":["总部费用报销(100003460000000060)"],"filterFields":[{"fieldName":"费用类型(费用类型字段的fieldId)","term":"eq","value":["差旅费(差旅费选项的id)"]}]}`（fieldName/选项 value 均带 ID：字段 ID 取该分组 `formFields` 中费用类型字段的 `fieldId`、选项 ID 取 `options` 中差旅费的 `id`，此处为示意占位）；招待费/办公费/交通费组同理各对应一个展开组，4 组同一次 plan 并行取数，各组返回 `total` 即该组条数

```markdown
## 差旅费报销（2 条）
> 差旅报销 2 条，其中北京出差高铁 1 条已超时，建议优先处理。

**1. [总部费用报销-北京出差高铁-2026-08-22](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)** `已超时`  
发起人：李明远　　当前节点：部门经理审批　　停留时长：1天2小时

---

**2. [总部费用报销-上海驻场住宿-2026-08-23](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：陈志远　　当前节点：部门经理审批　　停留时长：3小时

---

## 招待费报销（2 条）
> 客户招待报销 2 条，涉及渠道合作洽谈，金额均在预算内。

**1. [总部费用报销-渠道客户晚宴-2026-08-21](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：周敏　　当前节点：部门经理审批　　停留时长：1天

---

**2. [总部费用报销-产品发布答谢宴-2026-08-19](https://oa/sp/workflow/flowpage/view/xxx?secondEmpId=yyy&requestId=xxx)**  
发起人：许知行　　当前节点：部门经理审批　　停留时长：2天
```

---

# 异常返回处理

**先看 CLI 的真实返回形态**：成功 = 退出码 0 + stdout 的 JSON 信封 `ok:true`（数据在 `data`）；失败 = 非 0 退出码 + **stderr** 的 JSON 信封 `ok:false` + `error.type`/`error.subtype`/`error.message`/`error.retryable`。**没有** `success`/`stopReason`/`userMessage` 这类字段，不要去找。

| 情况 | 处理 |
| --- | --- |
| 退出码 0 且 `ok:true`、`finalMarkdown` 非空 | 直接按规则渲染，**不要二次验证查询结果**——`total`/`finalMarkdown`/`cards` 是 CLI 最终交付，不要去猜测"filterFields 是否真的生效""卡片是否真的过滤对了"等（CLI 内部责任）。**筛选条件解析不出时 CLI 返回的是澄清信封（`status=NEEDS_CLARIFICATION`）而不是数据**，所以拿到 `ok:true` 且带 `total`/`finalMarkdown` 就等于条件已生效；`total=0` 就是真的没有匹配数据 |
| `ok:true` 且 `data.status='NEEDS_CLARIFICATION'` | **名称类条件没对上的澄清，不是失败、也不是"查无数据"**：本次查询**没有执行**（`data.note` 已写明）。把 `data.clarificationQuestion` 与 `data.candidates` **原样**交给用户确认，拿到确认后用 `名称(ID)` 格式重发同一条命令（见「澄清后回传」）；**禁止**把它转述成"没有匹配的流程""查询结果为 0 条"，也**禁止**自行挑一个候选继续查 |
| `error.type=validation` 且 subtype 属于**用法/能力类**（`field_require_workflow`/`field_require_single_workflow`/`field_term_unsupported`/`field_type_unsupported`/`field_meta_empty`/`field_meta_unavailable`/`requestlevel_unavailable`/`time_invalid`） | 按 `error.message` 修正入参后重试（如先与用户确认工作流再带 `filterFields`；把 term 换成该字段类型支持的操作符；时间取值换成 YYYY-MM-DD）。这类错误是给模型的修正指令，**不要原样转述给用户**当结论 |
| `error.type=validation` 且 subtype 为**探查类**（如 `todo_probe_invalid`/`input_invalid`） | 按 `error.message` 处理；**不得当成"无超时/无紧急待办"继续渲染** |
| `error.subtype=locate_required` 等入参类错误 | 按 `error.message` 补齐参数后重试一次 |
| `error.type=authentication`（未登录/会话失效） | 停止业务调用，按共享规则读取 `weaver-e10-shared` 的 `references/e10-auth-and-session.md` 引导用户完成登录，登录后重放原查询（读操作可重放） |
| 查询结果为空（`total=0`） | 直接展示"无匹配流程"，不自行放宽条件重查 |
| 用户明确说"重试/再查一次" | = 新请求，可用同 operation 同条件重跑一次；**不得连续自动重试**，同一操作连续 2 次失败必须停止 |
| 其它失败（`error.type` 为 `network`/`api`/`internal` 等） | `error.retryable=true` 时最多重试一次；否则原样转述 `error.message` 并停止，不换接口、不绕过 |

### 澄清后回传

名称类条件**解析不出唯一对象**时不会静默放行：返回澄清信封（`ok:true` + `status:NEEDS_CLARIFICATION` + `data.candidates`），**不返回任何业务数据**。收到澄清就按下面的流程把候选原样交给用户；**不要**自行挑一个候选继续，也**不要**换词重发试探。

**澄清时一律不向用户索取 ID**：只问该对象的**完整名称**，或**其它可用于检索的关键词**——候选确认后的回传格式（`名称(ID)`）由你按 `candidates[].display` 自行拼好，**不要让用户提供 ID**。

返回形态分两类（澄清信封 / 硬失败），**不要混为一谈**：

| 情形 | 返回 | 处理 |
| --- | --- | --- |
| 工作流 多命中（或 0 命中） | **澄清信封**（`ok:true` + `data.type='workflowClarification'` + `data.status='NEEDS_CLARIFICATION'` + `data.clarificationQuestion` + `data.candidates` + `data.note`） | 见下文流程 |
| 工作流类型 / 发起人 / 发起人部门 / 发起人分部 / 紧急程度 **多命中** | **澄清信封**（`clarificationType=system_relate_name2id_<字段>`） | 见下文流程 |
| 表单字段名 0 命中 / 多命中 | **澄清信封**（`clarificationType=field`） | 见下文流程 |
| 选项/人员/浏览类字段的取值不能唯一解析 | **澄清信封**（`clarificationType=fieldOption`） | 见下文流程 |
| 表单字段元数据读不到 / 空清单 | **澄清信封**（`clarificationType=field_meta`，**无候选**） | 按 `clarificationQuestion` 如实告知用户或改不带 `filterFields` 查询 |
| 工作流类型 / 发起人 / 发起人部门 / 发起人分部 / 紧急程度 **0 命中** | **`ok:false` + `error.subtype=<字段>_not_found`**（V11.3 是硬失败） | 按上表「异常返回处理」的 `*_not_found` 行处理，**不是**澄清 |

**候选就用服务端返回的这一批（最多 10 条），不要指望 CLI 帮你扩召回**：CLI 按用户原词直接问服务端，返回几条就是几条——这是刻意的，名称类模糊匹配在大租户下可能命中成千上万条，取全既慢又没意义。所以：① 把这批候选**原样**给用户看；② **这批里都不匹配时，请用户给出该对象的完整名称（或其它可用于检索的关键词）**，不要自行换相近词反复试探、也不要要求 CLI 取更多候选；③ 用户给了更准的词就重发一次，仍不匹配就如实告知。

`data.candidates` 为空（`candidateCount=0`）说明该名称在当前环境**根本没有对应对象**（多半是错别字/漏字），请用户给准确全名后重发，**不要**当作"没有匹配的流程"答复。

处理方式：

**澄清顺序——一轮只推进一级**：先工作流（`clarificationType=workflow`）→ 用户确认后再表单字段（`clarificationType=field`）→ 再选项值（`clarificationType=fieldOption`）。每一级都要**先把候选原样给用户确认**，拿到确认后再发下一次查询。

**不得跳过澄清自行合并范围**：候选工作流**不能**自动拼成一个 `workflow: [...]` 一起查——字段条件只对单个工作流生效（`field_require_single_workflow`），且用户说的"XX流程"通常只指其中一个。确属"所有 XX 类流程"的范围型意图，也要先说明将要合并哪些工作流、经用户确认后再查（且此时不要带 `filterFields`）。

1. 原样把候选展示给用户，请其确认；
2. 用户确认后**必须回传带 ID 的格式**（`candidates[].display` 就是该格式），避免名称重匹配二次澄清：

| 条件 | 回传方式 |
| --- | --- |
| 工作流 | `workflow: ["标准名称(ID)"]` |
| 工作流类型 | `workflowType: "类型名(ID)"` |
| 发起人 | `creator: "姓名(ID)"` |
| 发起人部门 | `creatorDept: "部门名(ID)"` |
| 发起人分部 | `creatorSubcom: "分部名(ID)"` |
| 紧急程度 | `requestLevel: "紧急程度名称(ID)"` |
| 表单字段 | `filterFields` 里 **`fieldName` 用候选的 `名称(ID)` 格式**（如 `任务总负责人(100003720000107057)`），同时带 `term` 与 `value` |
| 表单字段选项 | `filterFields` 里 **`value` 用 `选项名(选项ID)` 格式**（如 `缺陷(123456)`） |

示例（字段确认回传）：

```bash
weaver-work-cli --json workflow run workflow.search --input-json '{"category":"all","workflow":["标准产品需求评审(100003460000000485)"],"filterFields":[{"fieldName":"任务总负责人(100003720000107057)","term":"eq","value":["李明远"]}]}'
```

## 示例

> 以下示例为 macOS/Linux（bash/zsh）形态；Windows PowerShell 与之一一对应、命令完全相同，仅按 shell 引用规则书写同一段 JSON 字符串即可（复杂 JSON 建议写 UTF-8 文件后用 `--input` 传入）。

### 当前待办（智能分组模式）

```bash
weaver-work-cli --json workflow run workflow.search --input-json '{"category":"todo","pageSize":10}'
```

### 我本月发起的报销流程（每页 5 条）

```bash
weaver-work-cli --json workflow run workflow.search --input-json '{"category":"mine","workflow":["报销"],"createTime":"2026-08-01 2026-08-31","pageSize":5}'
```

### 排除某工作流（notin）

```bash
weaver-work-cli --json workflow run workflow.search --input-json '{"category":"todo","workflow":["工作流名称"],"workflowTerm":"notin"}'
```

### 批量置已读数据查询（配合批量置已读）

```bash
weaver-work-cli --json workflow run workflow.search --input-json '{"category":"todo","batchType":"read","pageSize":100}'
```

### 批量操作第一步查数量

```bash
weaver-work-cli --json workflow run workflow.search --input-json '{"category":"todo","batchType":"submit","totalOnly":true}'
```

### todoStat 基础统计（必带 category:todo）

```bash
weaver-work-cli --json workflow run workflow.todoStat --input-json '{"category":"todo"}'
```

**一次执行、一次读取（硬要求）**：

- **不要对输出做管道截断**（`| head`、`| tail` 等）——截断会破坏 JSON，并直接导致同一条命令被重复执行。
- **一律直读 stdout，不要重定向、不要写解析脚本**：本命令输出约 20 KB 且是**多行 pretty JSON**（数百行、每行都不长，完全不触发行长截断），最多执行 1 次、一次读完完全可控；`countDetails` 各行（含 `requestInfos` 的 `requestId`、标题、字段值前缀）都在 stdout 里，**直接读，判定与取 ID 同一步完成**。**禁止** `> /tmp/stat.json` 重定向后再写脚本回读解析——它不会带来任何新信息，只会白白多花一次工具往返（实测多一轮约 +7s）。
- **唯一例外**：stdout 被宿主截断、且结果里没有 `resultFile`（CLI 侧落盘也不可用）时，才允许重定向落盘并**一次性**读回；不得为本来就能直读的输出这么做。
- 被省略的大字段（某工作流的 `formFields`、通知正文全文）从结果**最前面**给出的 `resultFile` 定点取，**不要重新跑命令**。

### todoStat 带筛选条件

```bash
weaver-work-cli --json workflow run workflow.todoStat --input-json '{"category":"todo","workflow":["总部费用报销(100003460000000060)"],"requestLevel":"重要"}'
```

### plan 批量编排（一次取数，内联传入）

把 plan 作为 `--input-json` **内联**传入（plan 通常只有几百字符，**不要写 JSON 文件再 `--input`**）：

```bash
weaver-work-cli --json workflow run workflow.search --input-json '{"category":"todo","pageSize":5,"planJson":{"category":"todo","specialGroups":["urgentOvertime","forwardToSelf"],"groups":[{"groupName":"报销审批","condition":{"workflow":["总部费用报销(100003460000000060)"]}},{"groupName":"传阅与抄送","collapsed":true,"condition":{"workflow":["标准产品需求评审(100003460000000485)"]}}]}}'
```

展开后的结构（**仅为便于阅读，实际必须压成一行内联**）：

```json
{
  "category": "todo",
  "planJson": {
    "category": "todo",
    "specialGroups": ["urgentOvertime", "forwardToSelf"],
    "groups": [
      { "groupName": "报销审批", "condition": { "workflow": ["总部费用报销(100003460000000060)"] } },
      { "groupName": "传阅与抄送", "collapsed": true, "condition": { "workflow": ["标准产品需求评审(100003460000000485)"] } }
    ]
  }
}
```

> 组名、工作流名里不要出现单引号（会破坏 shell 单引号包裹）；确实含单引号时改用 `--input` 文件方式。

## 返回

`workflow.search` 关键字段（批量编排模式 `type=workflowSearchPlan`，不套用下表，见「planJson 批量编排」）：

| 字段 | 含义 |
| --- | --- |
| `type` | `workflowSearch`（单条）或 `workflowSearchPlan`（批量编排） |
| `total` | 命中总条数（用于翻页/批量循环） |
| `finalMarkdown` | **最终用户可见的渲染文本，直接原样输出**（卡片已含标题链接、状态徽标与「标签：值」元信息行）。本 operation **不再返回 `renderMarkdown`**（它与 `finalMarkdown` 内容重复，已被移除）；`workflow.detail` 反过来只有 `renderMarkdown`、没有 `finalMarkdown`，两者不要混用 |
| `hasMore` / `current` / `pageSize` | 本页是否有更多 / 当前页 / 每页条数 |
| `cards` | 结构化条目数组（本 operation 的**唯一**结构化形态）。每条只含必要字段：`index`（序号定位）/ `requestId`（操作与详情）/ `requestMark`（用户可见编号）/ `flowName`（标题）/ `workflowId` + `workflowName`（工作流标识）/ `canSubmitRejectTransfer` + `isRemark` + **`isRemarkName`** + `finished` + `overdue`（可操作性判断）。**渲染一律用 `finalMarkdown`**；渲染字段（`cardMeta`/`badgeObjects`/`badges`/`flowStatus`/`currentNode`/`creatorName`/`stayDuration`/`timeoutLabel` 等）与内部字段（`userMasterId`/`nodeid`）**已不再回显**——它们的内容都在 `finalMarkdown` 里渲染过了。**不存在 `cardItems`**（历史别名，已移除） |
| `cards[].isRemarkName` | **当前用户在这条流程当前节点上的参与身份**（如 `节点操作者` / `抄送接收人` / `转发接收人不需反馈` / `传阅接收人(委托)`）。**这是判定"这条到底是不是抄送/传阅/转发给我的"的唯一可读依据**——用户问"抄送给我的有哪些""转发给我的是哪几条"时直接查本字段，**不要靠节点名、流程名或 `finalMarkdown` 的文字去猜**，也不要因为"卡片上看不出身份"就怀疑筛选没生效（`total` 与 `finalMarkdown` 是 CLI 最终交付，见「异常返回处理」）。⚠️ 列表接口的原始响应里**没有**这个字段（只有数字 `isRemark`），本字段**由码位映射得出**；未覆盖的码位返回**空串**（此时以 `workflow.todoStat` 的 `isRemarkName` 为准，不要臆断）。码位 ↔ 身份对照见「参与身份说明」 |
| `todoSummary` / `todoGroups` | **仅低版本模式的分组查询**返回：`todoSummary` 为各口径计数（`total` 之外含 `personalTotal`/`sharedTotal`/`overdueTotal`/`urgentTotal`/`forwardTotal`/`ccTotal`/`circulateTotal`），`todoGroups` 为实际输出的分组清单（`kind`/`label`/`total`/`current`/`displayed`） |
| `queryId` / `sessionMap` | 本次查询的序号映射标识（`index` 定位基于最近一次查询结果） |
| `resultFile` / `resultMdFile` / `largeOutputNotice` | **仅当输出超过 24 KB（美化口径）** 时出现（摆在结果**最前面**）：完整结果已落盘。stdout **仍保留全量 `finalMarkdown`** ⇒ 渲染直接用 `finalMarkdown`、**不需要读文件**；只有需要逐条结构化明细（如逐条 `requestId`）时才从 `resultFile` 按需提取，并一次读完（不要 `\| head`/`\| tail`）。**出现这些字段时不要重跑命令**（结果一样，白烧一轮） |

> 名称类条件解析不出唯一对象时**不在这里返回**——CLI 返回**澄清信封**（`ok:true` + `data.type='workflowClarification'` + `data.status='NEEDS_CLARIFICATION'` + `data.clarificationQuestion` + `data.candidates`），此时**没有** `total`/`finalMarkdown`/`cards`（查询未执行）；而工作流类型/发起人系/紧急程度 **0 命中**则走 `ok:false` + `*_not_found`。两者处理见「异常返回处理 · 澄清后回传」。

> **要工作流 ID（`workflowId`）只能从 `cards[]` 取**：`finalMarkdown` 按契约不渲染工作流名，更不含 ID。所以「用户澄清时只给了工作流名称 → 按名称重查成功」这种情况下，`workflowId` **只在这里出现**——保存「业务别名 → 工作流」记忆前必须回看本字段（口径见 `workflow-memory.md`），**不要只记名称**。

`workflow.todoStat` 返回：

| 字段 | 含义 |
| --- | --- |
| `type` | `workflowTodoStat` |
| `query` | 本次统计的查询条件（供构造 plan 分组条件参考，无分页） |
| `total` | `countDetails` 中 `totalCount` 累加（所有分组合计） |
| `draftTotal` / `pendingTotal` / `beRejectTotal` | `countDetails` 各行 `draftCount`/`pendingCount`/`beRejectCount` 的累加；用于汇报"其中草稿 M 条 / 被退回 K 条"与顶部汇总行的「需您亲自处理」口径，**不替代 `total` 作主计数** |
| `countDetails[]` | 按工作流 × 节点 × 参与身份分组的计数明细（字段见下）；每行含 `totalCount`/`pendingCount`/`draftCount`/`beRejectCount`/`forwardToSelfCount`/`urgentCount`/`overtimeCount`/`managerForwardToSelfCount`/`nodeTypeName`；**部分行**另带 `formFields`/`requestIds`/`requestInfos`（出现条件见下，**非恒在字段**） |
| `countDetailsTruncated` | 仅极端情况（紧凑版仍超安全线）为 `true`，表示 `countDetails` 已整体移除、全量仅在 `resultFile` 中 |
| `resultFile` / `largeOutputNotice` | 输出较大（超约 50KB 安全线）时出现：完整结果写入 `state/last_stat.json`，stdout 的 `countDetails` 行完整、仅去掉行内 `formFields` |
| `outputBytes` | **落盘文件的完整 JSON 字节数（与 stdout 无关）**，与 `resultFile` 同现；stdout 已是精简版（数 KB～数十 KB），**不要据此判断 stdout 很大**——看到 `outputBytes` 几十 KB 仍应直读 stdout，不要因此回退落盘或写脚本解析 |
| `displayRules` | 分组规划规则提示 |

`countDetails` **行完整性由 CLI 保证（契约，无需任何验证）**：行按"工作流 × 节点 × 参与身份"分组**全量返回、不随输出大小截断**；`countDetailsTruncated` 缺省即未截断。常规分组规划**直接用 stdout 的 `countDetails` 数量字段即可，不要读 `resultFile` 核对行数/求和对账、也不要做管道截断**；仅当需要对某工作流做**字段分组判断**（把 `filterFields` 的字段名换成 `字段名(字段ID)`、选项换成 `选项名称(选项ID)`）时，才从 `resultFile` 中该工作流元素的 `formFields` **针对性提取**（文件较大，不要把全量内容搬入上下文）。`resultFile` 不存在或读取失败时，直接用 stdout 的 `countDetails` 正常规划。

`requestIds` / `requestInfos` 的**出现条件**：**仅部分分组行返回**——接口只对**配置了关注字段**的工作流、其对应分组行返回这两个字段；**未带的行即没有，不是数据缺失、不是被截断**（同一份 `countDetails` 里有的行带、有的行不带，属正常）。`requestIds` 为该组组内流程的 ID 集合（逗号分隔字符串），`requestInfos` 为组内流程信息数组（元素含 `requestId` / `requestNameTitle` / `createDateTime` / `formFieldValues`，其中 `formFieldValues` 是**关注字段的「字段名 → 值」映射**，键为字段显示名、直接读值即可）。**按实际返回内容处理，不要把这两个字段当恒在字段用**——需要逐条判定或取 ID 时，**只处理带 `requestInfos` 的行**（详见「汇报式分组骨架」⑤）。

`countDetails` **不是分页结果**——返回多少行就是多少个分组，恰好 10 行只是当前分组数为 10，不代表"只返回第一页/默认每页 10 条"（`workflow.search` 的分页心智不适用于本 operation）。

## 注意

- **禁止编造字段**：所有字段名必须与 `weaver-work-cli workflow schema` 完全一致（camelCase）。`workflow.search` 与 `workflow.todoStat` 都支持 `workflowType`（工作流类型筛选）。
- **schema 中不存在的字段不要用**：例如发起人关系词（`creatorTerm` 之类）与节点名称列表（`nodeNames` 之类）在 schema 中没有对应字段。按发起人筛选用 `creator`/`creatorDept`/`creatorSubcom`；按参与节点筛选用 `nodeId` + `nodeIdTerm`。
- **OA 版本分支**：`workflow.todoStat` 仅 OA ≥ `10.0.9909.01` 支持；低版本待办查询直接用 `workflow.search`，不要调用 `todoStat`。智能分组仅 OA ≥ `10.0.9909.01` 生效。
- **最终回复以 `finalMarkdown` 为准**：它已按 OA 版本自动渲染好，整段原样输出即可，不要自行裁剪、改写或重新拼装卡片。智能分组模式返回纯卡片列表、无顶部统计行；低版本模式自带顶部行（分组汇总/总条数）与探查提示。
- **低版本模式不要自行分组**：该模式的分组、计数与分组标题**全部由 CLI 输出**（`finalMarkdown` 已含），不要再调 `todoStat`、不要自己按工作流/身份归类。用户未明确小分类时即走分组输出；要按小分类查（转发/抄送/待阅等）时显式传 `subCategory`，此时为普通列表输出。
- **低版本模式分页只留在分组标题里**：分组标题 `### 组名（共 N 条，第 X 页显示 M 条）` 已含分页信息，顶部汇总只说总量与构成；**不要自行补页码行、不要重复当前页**。用户要"下一页/全部/更多"时用 `workflow.search` 传 `current N` 续查后**原样渲染新返回**（不重跑已渲染过的页、不自行拼接多页卡片）。
- **待处理为空时 CLI 自动改查全部**：低版本模式下**未指定子分类**的待办查询，若待处理无数据，CLI 会自动改查「全部待办」（转发/抄送/传阅类同样算有效待办，避免只剩汇总而没有任何可看列表）。此时 `finalMarkdown` 顶部行会是「暂无需您亲自处理的流程，以下展示全部待办。……」、分组只有「全部流程」一个，`todoGroups[].label` 即 `全部流程`——**原样渲染即可**，不要因为"问的是待办却大多是抄送"而自行改口径、补查或另作解释。
- **禁止事项**：不要把系统条件塞进 `filterFields`；不要为看全貌剥离用户筛选条件；不要对 `todoStat`/`search` 输出做管道截断（`| head`/`| tail` 会破坏 JSON，并直接导致同一条命令被重复执行）；`planJson.groups` 展开+折叠总数不要超过 8；不要重复传同一个纯名称试探（多命中/0 命中必须改用 `名称(ID)`）。
- **输出体积与截断**：本 operation 的条目已收窄到必要字段（泛化待办查询 `category=todo`、`pageSize=10` 实测约 **14 KB**，此前 70 KB 会超宿主单次直读线后被截成一小段预览，而 `finalMarkdown` 排在后面会整段看不见）。**不要靠加大 `pageSize` 一次拉全**：泛化待办按要求走 `planJson` 分组（各组各 10 条）、要看更多用 `current` 分页续查。输出超过 **24 KB（美化口径）** 时 CLI 自动落盘并在结果**最前面**给出 `resultFile`（结构化）+ `resultMdFile`（纯 `finalMarkdown`），同时 **stdout 仍保留全量 `finalMarkdown`** ⇒ 渲染直接用它、不需要读文件。真被宿主截断时**不要重跑同一条命令**（结果一样、白烧一轮），也不要读宿主提示的 `tool-results/**` 落盘文件（无读权限）——改用更小页或分组重取。
- **命令不重复执行**：`workflow.todoStat` 每轮最多执行 **1 次**；输出里已给出 `resultFile` 时，被省略的大字段（`formFields`、通知正文全文）从 `resultFile` 定点取，**不要重跑命令**。
- **未登录/登录失效**：按 `weaver-e10-shared` 的 `references/e10-auth-and-session.md` 引导用户登录，登录后重放原查询（读操作可重放）。
- **凭据禁止**：业务输入里禁止传入 Cookie、ETEAMSID、Token、`header.operator`，这些由 CLI 托管。
