# 预约日程/会议、查询/搜索可用会议室的工作流

## CRITICAL 执行摘要（先按这个骨架执行，再看下方细则）

- **默认做智能助理，不做表单填写机。** 能根据上下文补全的默认值就直接补全，避免把用户带入表单式问答。
- **先补默认值，再判断时间是否明确。** 默认值包括标题、参会人、时长，以及在“完全无时间信息”时的默认时间范围。
- **只有三类场景才主动追问用户**：存在时间冲突、搜索结果无法唯一确定、时间语义本身有歧义。
- **明确时间**：若需要会议室，先 `+room-find`；再 `+freebusy` 判断参会人忙闲；有冲突时先说明冲突，再让用户决定继续当前时间还是改走 `+suggestion`。
- **模糊时间或无时间信息**：先 `+suggestion` 产出候选时间块；若需要会议室，再把这些时间块批量交给 `+room-find`，将“候选时间 + 对应可用会议室”一次性展示给用户选择。
- **BLOCKING REQUIREMENT: 只要面临时间方案（模糊时间/无时间）或会议室方案（需要会议室）的选择，必须先向用户展示选项并等待用户明确确认，绝对禁止在未获用户确认的情况下直接调用 `+create` 创建日程。**
- **用户选中了 `+suggestion` 返回的候选时间块后，不要再次调用 `+freebusy`。** 用户确认后直接进入 `+create`。
- **当用户说“查会议室”“找会议室”“搜可用会议室”时，默认意图是查会议室可用性，不是检索会议室资源名录。**
- **必须按顺序执行。** 不要跳过“补默认值”“判断时间明确性”这两个前置步骤。

> **💡 核心原则：做智能助理，充分利用默认值规则（如默认标题、时长、参与人等）自动补全信息。极力避免像“表单填写机”一样频繁打断并反问用户，仅在必须决策的冲突或无法唯一确定的场景下才发起询问。**

## 严禁行为

- **严禁在未读取对应子命令文档（如 `lark-calendar-room-find.md`、`lark-calendar-suggestion.md`）的情况下直接调用命令！** 必须先阅读文档掌握最新参数要求与规范。
- **严禁在用户仅要求“查会议室”但未提供明确时间时，直接调用 `+room-find`！** 必须先默认一个合理时间范围，调用 `+suggestion` 拿到候选时间块，再将时间块传给 `+room-find`。
- **不要在用户完全没给时间时，直接反问“你想约什么时候”。** 先补一个合理时间范围，再进入 `+suggestion`。
- **不要在“需要会议室 + 时间模糊”的场景下，先让用户只选时间。** 应先批量查出每个候选时间对应的可用会议室，再让用户一次性完成选择。
- **不要在用户已经选中 `+suggestion` 候选时间后，再重复调用 `+freebusy`。**
- **不要在用户未明确说出城市时，仅凭园区/办公室名自动补城市。**
- **严禁在面临时间方案或会议室方案的选择时（模糊时间、无时间或需要会议室），未经用户确认就擅自调用 `+create` 创建日程。**

## 适用场景

- “帮我约个会”
- “下周找时间和 XX 开会”
- “帮我订个会议室”
- “帮我找/搜索一个可用的会议室”
- “帮我推荐一个我以前常用的会议室”
- “查询明天下午可用的会议室”
- “明天下午3点约个日程/日历”

## 核心概念

- **会议室是日程的一种参与人（attendee / resource），不能脱离日程单独预定。** 
- **预定或查找会议室，均需先确定时间块。** 在推荐可用会议室后，应顺势引导用户完成最终的**预约日程**操作。

## CRITICAL 约束

- **在调用任何具体的 CLI 子命令（如 `+room-find`、`+suggestion`、`+freebusy`、`+create`）前，必须先读取其对应的 Markdown 文档。** 禁止仅凭记忆组装命令参数，以确保符合各命令最新的业务约束和格式规范。
- **当用户说“查会议室”“找会议室”“搜可用会议室”等，默认意图是查询会议室可用性，而不是检索会议室资源名录。**
- **必须严格按照下方【工作流】的步骤顺序完成任务。特别是单独查会议室时，若无明确时间，强制先走“模糊时间/无时间信息”分支调用 `+suggestion`。**

## 工作流

### 1. 智能推断默认值
以下信息智能推断，减少频繁询问用户：

- **标题**：根据上下文自动生成，例如“沟通对齐”“需求讨论”；如无法推断，默认为“会议”
- **参会人**：如未明确指定其他人，默认参会人仅为**用户自己**
- **时长**：基于会议类型和上下文动态推断；如无法推断，默认为 30 分钟
- **无任何时间信息**：默认推断一个合理区间（如“今天”或“近两天”），并进入时间推荐流程，禁止询问用户

当搜索特定参与人（人、群）出现多个结果无法唯一确定时，必须询问用户进行选择确认，并将该偏好记录为长期记忆，以便后续自动识别。

### 2. 判断时间是否明确

分两类处理：

- **明确时间**：如“明天下午3点”
- **模糊时间**：如“明天下午”“下周找个时间”

### 3. 明确时间

明确时间时，需先判断是否需要会议室，如果需要，提前查询会议室；然后判断是否有时间冲突。
详见 [`+room-find`](./lark-calendar-room-find.md) 与 [`+freebusy`](./lark-calendar-freebusy.md)。

```bash
# 1. 如果需要会议室，提前查询会议室
lark-cli calendar +room-find \
  --slot "<start>~<end>" \
  --attendee-ids "<ids>" \
  --city "<city>" \
  --building "<building>" \
  --floor "<F2>" \
  --room-name "<room_name>"

# 2. 查询当前用户及其他参会人忙闲
# （如果有多名参会人，需分别调用查询：--user-id "<ou_xxx>"）
lark-cli calendar +freebusy --start "<start>" --end "<end>"
```

规则：

- **参会人过多或包含群组时的处理**：
  - 如果参与人过多（例如超过 5 人），为避免高耗时，仅需查询**当前用户（自己）**及少数核心人员的忙闲状态即可。
  - 如果参与人中包含**群组**，无需展开群组成员查询其忙闲状态。
- **如果没有冲突**：直接让用户选择会议室（如需），然后调用 `calendar +create` 创建日程
- **如果有冲突**：必须先说明冲突情况，询问用户继续选择这个时间还是换个时间
  - **如果说换个时间**：放弃当前时间，转入【模糊时间】流程，调用 `+suggestion` 推荐多个可用时间块
  - **如果继续选择这个时间**：直接让用户选择会议室（如需），然后调用 `calendar +create` 创建日程
- 位置信息要优先拆到结构化字段：用户明确说了城市才提取 `--city`；`--building` 不要再重复携带城市前缀。
- 参数归类顺序应为：`city/building/floor` > `floor + room-name` 复合表达 > `room-name`。像 `2L`、`2F` 这类更像楼层或区域定位的短词，优先视为 `--floor`，不要默认当作 `--room-name`。像 `学清2层` 这种表达，通常拆为 `--building "学清"` 与 `--floor "F2"`。
- 会议室名要做轻量归一化：`木星会议室` -> `--room-name "木星"`；`会议室 02` / `02会议室` -> `--room-name "02"`。
- 对 `F3-05` / `F5-07` / `3楼-08` 这类复合表达，若能稳定识别楼层与会议室号，应优先提取为 `--floor + --room-name`，不要把整段直接退化成 `--room-name`。

### 4. 模糊时间或无时间信息

先调用：
详见 [`+suggestion`](./lark-calendar-suggestion.md)；若需要会议室，再结合 [`+room-find`](./lark-calendar-room-find.md)。

```bash
lark-cli calendar +suggestion \
  --start "<range_start>" \
  --end "<range_end>" \
  --attendee-ids "<ids>" \
  --duration-minutes <n> \
  --event-rrule "<rrule>"
```

规则：

- 若用户完全没有提供时间信息，应先默认一个合理区间后再调用 `+suggestion`
- **不需要会议室**：获取多个推荐时间块后，直接向用户展示候选时间，用户确认后创建日程。
- **需要会议室**：获取多个候选时间块后，**不要急于让用户选时间**。先将这些时间块一次性交给 `calendar +room-find` 批量查询可用会议室，然后将【候选时间】与【对应的可用会议室列表】结构化分行展示，让用户一次性完成选择。（**注意：即使用户最初只说“查会议室”，且未带时间，也必须强制走到这一步，先 suggestion 再 room-find**）。
- 用户一旦选择了 `+suggestion` 返回的时间块，**无需再次调用 `+freebusy`**

### 5. 模糊语义消解与长期记忆构建

针对用户专属的时间表达习惯或存在歧义的时间场景，严禁主观臆断。典型例子包括：

- “上班后”
- “下班前”
- 未明确上下午的 12 小时制时间表达

处理规则：

- 应主动澄清真实意图，而不是自行猜测
- 当用户给出澄清后，应将这类个性化定义沉淀为长期偏好，推动后续直接理解类似表达

### 6. 重复性日程

若当前会议为重复性日程，调用 `+room-find` 时需携带 `--event-rrule`。

必须检查返回中的：

- `reserve_until_time`

若候选会议室的可预约上限早于重复规则覆盖范围，**不要直接按原规则创建**。应：

- 向用户明确说明该会议室最长可约至何时。
- 若用户确认继续选用该会议室，你必须**自动将日程的重复规则结束时间缩短**至该 `reserve_until_time`，以防止会议室预约失败。

### 7. 创建日程

用户确认后调用：
详见 [`+create`](./lark-calendar-create.md)。

```bash
lark-cli calendar +create \
  --summary "..." \
  --start "<start>" \
  --end "<end>" \
  --attendee-ids "ou_xxx,oc_xxx,omm_xxx"
```

规则：
- 需要会议室时，将选中的 `room_id` 写入 `--attendee-ids`
- 展示会议室候选时，必须保留 CLI/API 返回的完整 `room_name` 原值；允许附加“推断说明”，但禁止用摘要名、楼层及会议室号、容量/视频标签重组后的名称替换原值

## 用户展示建议

当向用户展示多个时间块及对应的多个会议室时，**必须使用结构化清晰的格式排版**。**严禁将时间与会议室名称放在同一行展示**，必须分行并使用编号列表呈现可用会议室，严禁将所有信息揉成一团纯文本堆叠。

**推荐展示格式参考：**

```text
## 2026-03-27 周五

[选项 1] 14:00 - 15:00（参会人均空闲）
  可用会议室：
  1. 学清嘉创大厦B座-F2-02🎦(7人)
  2. 学清嘉创大厦B座-F2-05🎦(10人)

[选项 2] 16:00 - 17:00（参会人均空闲）
  可用会议室：
  1. 学清嘉创大厦B座-F3-01🎦(6人)
  2. 学清嘉创大厦B座-F3-06🎦(8人)

💡 请回复您倾向的选项编号以及对应的会议室序号，我来为您完成预定。
```

## 参考

- [lark-calendar-room-find.md](./lark-calendar-room-find.md)
- [lark-calendar-freebusy.md](./lark-calendar-freebusy.md)
- [lark-calendar-suggestion.md](./lark-calendar-suggestion.md)
- [lark-calendar-create.md](./lark-calendar-create.md)
- [lark-shared](../../lark-shared/SKILL.md)
- [lark-calendar](../SKILL.md)
