# S01 New Booking Skill

## 1. Skill Identity

- catalog_code: `S01`
- skill_id: `new_booking_skill`
- skill_name: `New Booking Skill`
- task_type: `New Booking`

## 2. Purpose

本 Skill 用于判断一条来自 `body_current` 的当前邮件事件，是否可以生成 New Booking 任务。

第一版判断保持简单：

- 可以安全创建 New Booking 任务：输出 `normal_task`
- 不能安全自动处理：输出 `manual_review`

本 Skill 不直接写数据库或外部系统，不写 Opera，不确认 Payment，不生成 Receipt。

New Booking 可以携带 Fix Charge / 固定费用附加执行项。Fix Charge 不改变主任务类型；主任务仍是 New Booking，附加收费信息写入 `extracted_fields.fix_charge_items` 和 `additional_operations`，供信息系统在订单创建成功后继续处理。

如果本 Skill 输出 `ai_task_result` 且通过统一输出校验，AI 运行时 / Main Agent / Skill Orchestrator 后续可调用信息系统提供的统一受控 Tool / API 创建普通任务卡、人工复核 / 人工处理任务卡或信息系统可展示记录。真实 TaskCard ID、任务状态机、幂等控制、并发保护和执行前硬校验仍由信息系统负责。

## 3. Scope

本 Skill 覆盖以下新建预订对象：

- FIT Reservation
- Group Block
- Allotment / Control Block 类新建控房订单
- LianTai / 旅行社语境中的配合房、取配、父团拆子团创建；即使 current 文本写作 `AMEND + FINAL BOOKING`，只要实质是在给多个新子 `group_code` 分配房量，在酒店系统中按 New Booking / Allotment creation 处理

对象类型判断参考：

- 房间数小于 5 间，通常按 FIT Reservation 理解。
- 房间数 5 间及以上，通常按 Group Block 理解。
- 邮件明确出现 allotment、allocation、control block、控房、配额等语义时，按 Allotment / Control Block 类新建对象理解。
- 邮件当前正文若列出父 group code，并在 `AMEND TO`、`AMED TO`、取配、配合房、allocation 等语义后列出多个子 group code、日期、晚数、房型和房量，按 Allotment / Control Block 类新建对象理解；父 group code 只作为 `parent_group_code` / `allocation_parent_group_code` evidence。

Extra bed / 加床 / `เตียงเสริม` 属于 Trace / Guest Request，不属于房型或房量：

- 不计入 `room_quantity`。
- 不影响 FIT / Group 判断。
- 不作为独立房型映射。
- 不单独决定 Rate Code。
- 如果与 New Booking 同一事件或同一表格行出现，仍由本 Skill 处理 New Booking 主任务，同时生成 S07 Trace / Reservation Notes linked task；先处理 S01，再处理 S07。

Fix Charge / 固定费用属于 New Booking 的附加收费能力，不属于独立任务类型：

- 不因为 `TWN` / `DBL` / 普通房型本身触发 Fix Charge。
- 不因为普通价格如 `2000THB`、`1800THB` 本身触发 Fix Charge。
- 只有当 current 事件或 LianTai 表格酒店说明价格区出现可拆分的复合单价结构，例如 `2000THB+500`、`1800THB+500`、`2000THB*2` 换行后 `+附加500*2`，才识别 Fix Charge。
- `+` 前的房费单价组件用于 Rate Code 判断；`+` 后的附加费用单价组件写入 `extracted_fields.fix_charge_items`。
- AI 不负责从该表达计算数量或总额。

本 Skill 的房型映射与 Rate Code 判断规则不直接写在主文档正文中，而是作为 bundled references 维护：

- `S01_new_booking_skill/references/room_type_mapping_rules.md`
- `S01_new_booking_skill/references/rate_code_rules.md`

当 current 邮件涉及房型、房型代码、Rate Code、结算价格、渠道、市场类别、早餐或用餐餐厅时，应按需读取对应 reference。

## 4. When To Use

当 `body_current` 中明确提出创建新的预订对象时，Main Agent 可以调用本 Skill。

典型语义包括：

- 新建 FIT 预订。
- 新建 Group Block。
- 新建控房 / 配额 / Control Block。
- 新建配合房 / 取配 / Allotment，或 `AMEND + FINAL BOOKING` 实质为父团拆成多个子 group 的房量分配。
- 邮件当前内容包含新订单所需的基本信息，或通过附件提供新订单信息。

## 5. Must Not Use When

以下情况不得使用本 Skill 生成 `normal_task`：

- 当前邮件是在修改既有订单。
- 当前邮件是在取消订单。
- 当前邮件是在取消控房 / 配额 / Control Block。
- 当前邮件只是提交 Rooming List / Name List。
- 当前邮件只是收到 Voucher、Credit Voucher、payment slip 或 payment confirmation。
- 当前邮件只是添加 Trace、Reservation Notes 或 Guest Request。
- 当前邮件只是为既有订单添加、修改或取消 extra bed / 加床 / `เตียงเสริม`，且没有新的创建动作。
- 当前邮件只是修改 Group Code、Block Code、Block Name 或 Group Name。
- 新建预订动作只出现在 `body_thread`，不在 `body_current`。
- 当前邮件只是 thank you、FYI、acknowledgement、noted、received、confirmed receipt、确认收到、转发说明、仅同步信息或无新业务动作。
- 邮件只是追问、确认、转发历史信息，没有新的创建动作。

如果邮件语义无法安全区分 New Booking 与 Update Booking，应结合 `routing_context` 判断；仍无法判断时输出 `manual_review` 或交由 `exception_detection_skill` 处理。

## 6. Allowed Result Types

第一版只允许：

- `normal_task`
- `manual_review`

第一版不输出：

- `exception_task`
- `no_action`
- `informational_message`

原因：New Booking 的第一版判断只区分“可以安全创建”与“需要人工确认”，不做复杂异常分类；明确轻量消息通知由 `message_notification_skill` 处理。

## 7. Key Context Needed

Main Agent 应尽量提供以下上下文：

- `source_message_id`
- `source_event_index`
- 当前邮件事件文本，只能来自 `body_current`
- 当前邮件相关附件摘要
- `group_code`
- `confirmation_number`
- 房间数
- 入住 / 离店日期
- 客人姓名、团队名称或 block 名称
- supplier / sender 线索
- 房型原文、床型、人数、是否套房、是否家庭房等可用于房型映射的线索
- 渠道 / 市场类别、备注价格、是否含早餐、用餐餐厅、实际结算价格等可用于 Rate Code 判断的线索
- extra bed / 加床 / `เตียงเสริม` 等 Trace / Guest Request 线索
- LianTai 复合单价、附加费、Fix Charge 原文线索
- `routing_context`

`routing_context` 至少应覆盖：

- 同 key 是否已有已完成 / 已写入的 FIT Reservation
- 同 key 是否已有已完成 / 已写入的 Group Block
- 同 key 是否已有已完成 / 已写入的 Allotment / Control Block 或其他有效订单记录
- 同 key 是否已有 pending / open task
- 同 key 是否已有 active workflow
- 同 key 是否已有 terminated record

`body_thread` 只能作为 evidence context，不得作为生成 New Booking `normal_task` 的来源。

## 8. Input Requirements Summary

本 Skill 输入应包含：

- 当前事件摘要
- 当前邮件原文片段
- 附件摘要
- 已提取的核心 key
- 路由级查询结果
- 与新建判断直接相关的基础业务字段
- 能帮助房型映射、Rate Code 判断或手工结算价格维护的上下文线索
- 能帮助识别 Fix Charge / 固定费用的复合单价、附加费、酒店说明列原文
- 与新建任务同一事件出现的 Trace / Guest Request 线索，例如 extra bed / 加床 / `เตียงเสริม`

本 Skill 不要求 Main Agent 在输入阶段固定完整 `extracted_fields` schema。

具体字段抽取、字段标准化、必填字段、附件解析规则，应放在本 Skill 后续详细字段章节、bundled references 或统一输出契约中维护。

### 8.1 Bundled / Shared References

本 Skill 可按需读取以下 references：

- `references/room_type_mapping_rules.md`
  - 当 current 邮件涉及房型、房型代码、套房、家庭房、`Q10`、`U-DBL`、`U-TWN`、`U-TRP`、`HNM` 等房型语义时读取。
  - 用于将邮件原始房型映射到 Opera 房型代码。

- `references/rate_code_rules.md`
  - 当 current 邮件涉及 Rate Code、结算价格、渠道 / 市场类别、supplier、备注价格、早餐、用餐餐厅或手工价格维护时读取。
  - 用于判断可选 Rate Code、是否需要手工录入具体结算价格，以及需要哪些人工确认字段。
  - 当 current 事件是新建控房 / 配额 / Allotment / Control Block，且邮件没有明示 Rate Code 时，也必须读取；若房型命中控房默认补全规则，应自动补全房型代码和结算价格。
  - 当 current 事件或 LianTai 表格酒店说明价格区出现 `2000THB+500`、`1800THB+500`、`2000THB*2` 换行后 `+附加500*2` 等复合单价表达时必须读取；用于拆分房费单价组件和 Fix Charge 单价组件。

- `../references/qbd_liantai_email_table_rules.md`
  - When the current message, attachment, sender, subject, or extracted evidence indicates QBD or LianTai Excel/table workflow, read this shared reference.
  - 触发条件包括：QBD / LianTai 发件人或渠道、QBD / LianTai 表头、Excel / table 附件、`BOOKING UPDATE`、`NEW BOOKING`、`AMEND`、`AMD ALLOTMENT`、`CXL`、`CFM`、黄色 / 高亮行、红字、划线、`โรงแรม` 或酒店状态列等线索。
  - 用于判断表格行是否代表当前 New Booking 请求、黄色 / 高亮行如何拆成独立 current events、新建对象是 FIT / Group Block / Allotment Control Block，以及总房量如何影响 FIT / Group 路径。

Reference 使用原则：

- 只有 reference 中规则唯一命中时，才可将映射结果写入 `extracted_fields`。
- `pms_room_type_code` 必须来自 `references/room_type_mapping_rules.md` 的唯一命中；`references/rate_code_rules.md` 可以引用房型代码，但不得作为房型映射唯一来源。
- `ST+K:2卧1厅=1200` + `FAMILY 1` 是跨 QBD / LianTai 渠道可识别的房型表达，房型映射可命中 `SU3`；Rate Code 必须继续按渠道判断。
- 如果 QBD / LianTai reference 识别出多个当前有效黄色 / 高亮 `NEW BOOKING` 行，必须按行拆分：一行一个 `source_event_index`，一行一个 `ai_task_result`，一行一个下游 task card 候选；不得跨行合并。
- 如果 QBD / LianTai reference 识别出 parent-to-child `AMEND + FINAL BOOKING` 配合房 / Allotment 创建文本，必须按子 group code 拆分：一个子 group code 一个 `source_event_index`、一个 S01 `ai_task_result`、一个下游 task card 候选；不得用父 group code 的单个 S02 Update 结果代替。
- parent-to-child 配合房场景中，`parent_group_code` 不作为本任务的 `case_keys.group_code`；`case_keys.group_code` 必须是该子行 / 子事件自己的 child group code。
- 这种场景不要求建立 S02 意义上的 before / after。父团原房量、父团日期和父团号应保留在 `extracted_fields.parent_allocation_context`，供后台展示和硬校验。
- 即使多行共享同一 `group_code`、`confirmation_number`、日期、酒店、批次、supplier、主题或附件，也不得合并为一个 New Booking task。
- 不得用单个结果里的 `source_event_count`、数组型 `case_keys.group_code`、汇总型 `highlighted_rows` 或跨行 `room_items` 代替多个逐行 `ai_task_results`。
- 如果一行内包含多个房型 / 房量 / 价格明细，可放入该行自己的 `extracted_fields.room_items` 或等价结构；不同表格行之间不得合并。
- 如果某一行信息不完整或不能安全处理，只让该行输出结构化 `manual_review`，不得阻塞其他可正常处理的行。
- Extra bed / 加床 / `เตียงเสริม` 是 Trace / Guest Request，不得计入 `room_quantity`，不得影响 FIT / Group 判断，不得作为独立房型映射，不得单独决定 Rate Code。
- 如果 extra bed 与 New Booking 同一表格行出现，主任务仍是 New Booking；同时生成 S07 linked task，并在后台 payload 保留 extra bed 数量和原文。
- 示例：`Sup 高级房TWN 4 + extra bed 2` 中 `room_quantity = 4`，`extra_bed_quantity = 2`，extra bed 生成 S07 linked task。
- 房型映射不得覆盖原始房型关键线索。即使 `U-TWN` 与 `Sup 高级房TWN` 都映射到 `RM3`，或 `U-DBL` 与 `Sup 高级房DBL` 都映射到 `RM2`，Rate Code 仍必须按原始 `U-` / `Sup` / `高级房` 线索判断。
- 如果 reference 明确要求手工录入或修改价格，且实际价格可可靠提取，可以输出 `normal_task`，并在 `extracted_fields` 中标记手工价格维护要求。
- 如果 LianTai 复合单价表达与 New Booking 同一事件或同一表格行出现，主任务仍是 New Booking；将房费单价组件写入 `rate_code_result`，将附加费用单价组件写入 `fix_charge_items`。
- 没有复合单价或附加费组件时，继续按既有房型 / Rate Code 规则处理，不因缺少 Fix Charge 输出 `manual_review`。
- 对于新建控房 / 配额 / Allotment / Control Block，如果邮件没有明示 Rate Code，但 `references/rate_code_rules.md` 的控房默认补全规则可按房型唯一命中，不得仅因缺少 Rate Code 输出 `manual_review`；应在 `extracted_fields` 中记录自动补全结果。
- 如果房型、渠道、市场类别、早餐、餐厅、价格或上下文不足以唯一命中规则，输出结构化 `manual_review`。
- 如果 reference 没有覆盖当前表达，不得靠常识猜测房型代码或 Rate Code。
- If any trigger signal is present but the table/highlight/row evidence is unavailable, unreadable, or ambiguous, do not guess. Output structured manual_review and include the missing table evidence in manual_review.evidence_to_check.
- `context_used` 应记录使用了哪个 reference 以及命中的规则摘要。

## 9. Decision Rules

1. 先确认 New Booking 动作是否出现在 `body_current`。
2. 如果 New Booking 动作只出现在 `body_thread`，不得输出 `normal_task`。
3. 判断当前事件是否确实是创建新对象，而不是修改、取消、名单、Voucher、Trace 或改 Group Code。
   - 如果 current 文本含 `AMEND + FINAL BOOKING` / `AMEND TO` / `AMED TO`，但业务形态是父团拆为多个子 `group_code` 并给出各子 code 的房量分配，按新建配合房 / Allotment 创建处理，不因 `AMEND` 字样改走 S02。
4. 如果能提取到 `group_code` 或 `confirmation_number`，必须使用对应 `routing_context`。
5. 如果 routing context 显示同 key 已存在已完成 / 已写入的有效订单记录，不得输出 `normal_task`。
6. 如果 routing context 显示同 key 已存在 pending / open task 或 active workflow，第一版不得输出 `normal_task`。
7. 如果涉及房型映射，应读取 `references/room_type_mapping_rules.md`；只有唯一命中时，才可填入 Opera 房型代码。
8. 如果涉及 Rate Code 或结算价格，应读取 `references/rate_code_rules.md`；只有唯一命中、满足 reference 中“手工价格仍可 normal_task 的条件”，或新建控房 / 配额 / Allotment / Control Block 缺 Rate Code 但命中控房默认补全规则时，才可继续创建任务。
9. 如果 current 邮件、附件、发件人、主题或抽取证据显示 QBD / LianTai Excel/table workflow，应读取 `../references/qbd_liantai_email_table_rules.md`；只有当前表格行、高亮 / 黄色行、行证据和对象类型可靠时，才可基于表格输出 `normal_task`。
10. 对 QBD / LianTai 表格中的多个当前有效黄色 / 高亮 `NEW BOOKING` 行，必须按行拆分；每一行生成独立 `source_event_index` 和独立 `ai_task_result`，不得跨行合并，不得用 `source_event_count` 或数组型 `case_keys.group_code` 代替。
10a. 对 QBD / LianTai / 旅行社 current 文本中的 parent-to-child `AMEND + FINAL BOOKING` 配合房创建，必须按每个 child group code 拆分；当 child code、stay dates、nights、room_items 和对象类型可读时，输出 S01 `normal_task`，并在 `extracted_fields` 保留 `booking_object_type="Allotment / Control Block"`、`parent_group_code`、`allocation_split_from_parent=true`、`allocation_child_group_code`、`parent_allocation_context`。
    - 如果 child line 中包含通用 `SUITE` 且未给出 `TWN SUITE` / `DBL SUITE` / 明确床型，保留该 room item 的 `raw_room_type="SUITE"`、`pms_room_type_code=null`、`room_type_mapping_status="requires_downstream_room_type_validation"`；在 parent-to-child Allotment 测试口径下，不因此把整封或其他 child line 合并为 `manual_review`，但必须标记 `requires_downstream_hard_validation=true`。如果信息系统要求创建任务前必须有最终 PMS suite code，只该 child line 输出结构化 `manual_review`，不得阻塞其他 child lines。
11. 如果 extra bed / 加床 / `เตียงเสริม` 与 New Booking 同一事件出现，主任务仍是 New Booking，同时生成 S07 linked task；不得把 extra bed 数量计入 `room_quantity`，不得用于 FIT / Group 判断。
12. 如果 current 邮件只是为既有订单添加、修改或取消 extra bed / 加床 / `เตียงเสริม`，不得路由为 New Booking；应路由到 Trace / Reservation Notes Skill。
13. 如果 LianTai 复合单价表达出现，应按 `references/rate_code_rules.md` 拆分房费单价和 Fix Charge 单价；不得把 `2000+500` 合并为 `2500` 判断 Rate Code。
14. 如果 key 缺失、对象身份不清、邮件语义混杂、current/history 边界不清、房型映射无法唯一确认、Rate Code 无法唯一确认、结算价格无法可靠确认，或 QBD / LianTai 表格高亮 / 行证据不可读或不明确，输出 `manual_review`。
15. 如果当前邮件是感谢、确认、FYI、noted、received、confirmed receipt、转发说明等轻量信息，但需要用户可见记录，不应路由到本 Skill，应由 `message_notification_skill` 输出 `informational_message`。
16. 只有当前事件明确是 New Booking，routing context 未发现阻断自动创建的既有记录、pending/open task、active workflow 或终止冲突，且房型 / Rate Code / Fix Charge / QBD-LianTai 表格相关规则已可靠处理时，才能输出 `normal_task`。

## 10. Normal Task Output

仅当可以安全创建 New Booking 任务时，输出：

```json
{
  "result_type": "normal_task",
  "task_type": "New Booking",
  "current_or_history": "current"
}
```

完整输出必须符合统一输出契约。

关键要求：

- `source_message_id` 必须原样带回。
- `source_event_index` 必须原样带回。
- `case_keys.group_code` 和 `case_keys.confirmation_number` 按实际提取结果填写。
- `visible_reason` 应说明为什么这是当前邮件中的 New Booking 请求。
- `relevant_message_excerpt` 必须来自 `body_current`。
- `attachments` 只包含当前事件相关附件。
- `context_used` 应记录用于判断的 routing context 摘要。
- `extracted_fields` 应填入可可靠抽取的新建预订字段。
- 如果涉及房型映射，应在 `extracted_fields` 中保留原始房型、归一化房型、命中规则和 Opera 房型代码。
- 如果涉及 Rate Code，应在 `extracted_fields` 中保留渠道 / 市场类别、备注价格、结算价格、命中规则、Rate Code 或手工价格维护要求。
- 如果使用手工结算价格维护，必须在 `extracted_fields.rate_code_result` 中写入 `rate_code=null`、`settlement_price`、`manual_settlement_price_required=true`、`manual_price_reason_code` 和 `price_evidence`。
- 如果涉及 LianTai 复合单价，应在 `extracted_fields.rate_code_result` 中保留 `raw_price_expression`、`composite_unit_price_detected`、`base_room_price_component`、`additional_charge_component`、`settlement_price`、`rate_code` 和命中规则摘要。
- 如果涉及 Fix Charge，应在 `extracted_fields.fix_charge_required`、`extracted_fields.fix_charge_items` 和 `extracted_fields.additional_operations` 中保留附加费用单价、币种、原文证据和后续 Tool 占位；没有 Fix Charge 时可填 `fix_charge_required=false`、`fix_charge_items=[]`。
- `extracted_fields.fix_charge_items[]` 建议包含 `charge_type`、`amount`、`currency`、`pricing_mode`、`unit_basis`、`quantity=null`、`total_amount=null`、`raw_text`、`evidence_source`、`requires_followup_tool=true`、`followup_tool_name=create_fix_charge / TBD`。
- `extracted_fields.additional_operations[]` 建议包含 `operation_type=create_fix_charge` 和 `status=pending_booking_id`；如果后续系统使用其他状态枚举，以信息系统契约为准。
- 如果是新建控房 / 配额 / Allotment / Control Block 且邮件未明示 Rate Code，但按控房默认补全规则命中，应在 `extracted_fields.rate_code_result` 中记录 `auto_completed_from_control_block_room_type_default`、原始房型、归一化房型、`pms_room_type_code`、结算价格和 `rate_code_missing_in_email=true`。
- 如果是 parent-to-child 配合房 / Allotment 创建，应在 `extracted_fields` 中记录 `allocation_split_from_parent=true`、`parent_group_code`、`allocation_child_group_code`、`parent_original_room_summary`、`child_room_items`、`allocation_context_source="body_current"`；父团原房量不作为本子任务的 `room_quantity`。
- 如果来自 QBD / LianTai 表格行，应在 `extracted_fields` 中保留该行的附件名、sheet 名、行号或行标签、高亮状态、动作 / 状态单元格、原始日期、原始房型、原始房量和原始价格；一行内多个房型 / 房量 / 价格明细应放入该行自己的 `room_items` 或等价结构。
- 如果来自 QBD / LianTai 多行表格，单个 `ai_task_result` 只能代表一个当前有效行；`case_keys.group_code` 应只填该行 key。
- 如果同一事件包含 extra bed / 加床 / `เตียงเสริม`，应生成 S07 linked task；同时可在本任务后台 payload 中保留原文、数量和说明，`room_quantity` 必须排除 extra bed 数量。
- `context_used` 应记录使用的 reference 文件与命中规则摘要。
- `exception` 必须为 `null`。
- `no_action` 必须为 `null`。

## 11. Manual Review Output

当邮件看起来是 New Booking，但不能安全自动创建时，输出：

```json
{
  "result_type": "manual_review",
  "task_type": "New Booking",
  "current_or_history": "current"
}
```

典型原因包括：

- 同 key 已有有效订单记录。
- 同 key 已有 pending / open New Booking task。
- 同 key 已有 active workflow。
- 邮件可能其实是在修改既有订单，但表达成了新建。
- 缺少关键 key，无法确认对象身份。
- current/history 边界不清。
- 一个 current 事件混合多个新建对象，且无法安全拆分。
- QBD / LianTai 表格触发信号存在，但表格、黄色 / 高亮行、行号、划线或当前行证据不可读、缺失或不明确。
- 房型映射 reference 未覆盖当前表达，或存在多个候选。
- Rate Code reference 无法根据渠道、市场、房型、早餐、餐厅或备注价格唯一匹配。
- 新建控房 / 配额 / Allotment / Control Block 缺 Rate Code，但房型无法命中控房默认补全规则，或 `U-TRP` / `FAM` / `6+4` 关系无法可靠确认。
- reference 要求手工录入价格，但实际结算价格无法可靠提取。
- 手工价格维护条件未全部满足，例如房型未唯一映射、价格不来自 `body_current` / 当前表格行、价格不可读、核心日期 / 房量 / 对象类型不可靠，或 routing context 存在阻断。
- 出现复合单价或附加费用线索，但无法判断哪一段是房费单价、哪一段是附加费用单价。
- Fix Charge 金额无法可靠提取，或同一行多个价格组件无法归属。

`manual_review` 不能只是“人工看一下”。它必须带结构化信息，方便信息系统创建人工复核 / 人工处理任务卡。

即使输出 `manual_review`，也要尽力结构化抽取：

- 能确定的 `case_keys` 必须填入。
- 能确定的 `candidate_object_type` 应填入 `extracted_fields`，例如 `FIT Reservation`、`Group Block`、`Allotment / Control Block`。
- 能确定的新建预订字段应填入 `extracted_fields`，例如 `arrival_date`、`departure_date`、`room_quantity`、`room_type`、`guest_name`、`group_code`、`confirmation_number`、`supplier`。
- 能确定的原始房型、归一化房型、候选 Opera 房型代码、候选 Rate Code、候选结算价格，应尽量填入 `extracted_fields`。
- 能确定的复合单价拆分结果和 Fix Charge 单价，应尽量填入 `extracted_fields.rate_code_result` 与 `extracted_fields.fix_charge_items`。
- 不能可靠确认的字段不要猜，填 `null`、空字符串或空数组。
- 不能唯一确认的房型映射或 Rate Code，不要猜，填 `null` 或候选数组。
- 不确定原因必须写入 `manual_review.reason_code`。
- 缺失字段写入 `manual_review.missing_fields`。
- 阻塞点写入 `manual_review.blocking_points`。
- 冲突点写入 `manual_review.conflicting_points`。
- 建议人工处理动作写入 `manual_review.suggested_human_actions`。
- 建议人工查看的证据写入 `manual_review.evidence_to_check`。
- 如房型或 Rate Code 无法自动确认，`manual_review.evidence_to_check` 应包含相关 reference 文件名以及需要人工核对的邮件片段、附件或系统上下文。
- 人工复核记录类型写入 `manual_review.review_record_type`。

当同 key 已有有效订单记录时，`visible_reason` 应明确提示：

```text
该 key 疑似已存在有效订单记录，不能继续自动创建 New Booking，需要人工业务确认并中止或改派当前自动处理流程。
```

建议结构：

```json
{
  "manual_review": {
    "reason_code": "",
    "visible_reason": "",
    "review_record_type": "",
    "blocking_points": [],
    "missing_fields": [],
    "conflicting_points": [],
    "suggested_human_actions": [],
    "evidence_to_check": []
  }
}
```

`review_record_type` 第一版建议使用：

- `manual_review_required`
- `manual_processing_required`

示例语义：

```json
{
  "case_keys": {
    "group_code": "LLT260727FA",
    "confirmation_number": null
  },
  "extracted_fields": {
    "candidate_object_type": "Group Block",
    "arrival_date": "2026-07-27",
    "departure_date": null,
    "room_quantity": 10,
    "room_type": "Deluxe Twin",
    "guest_name": null,
    "group_code": "LLT260727FA",
    "confirmation_number": null,
    "supplier": "TBD"
  },
  "manual_review": {
    "reason_code": "EXISTING_ORDER_RECORD_FOUND",
    "visible_reason": "该 Group Code 疑似已存在有效订单记录，不能继续自动创建 New Booking。",
    "review_record_type": "manual_review_required",
    "blocking_points": ["routing context 显示同 key 已存在有效订单记录"],
    "missing_fields": ["departure_date"],
    "conflicting_points": [],
    "suggested_human_actions": ["核对既有订单记录，确认当前邮件是重复新建、修改请求还是需中止处理"],
    "evidence_to_check": ["body_current", "routing_context.matched_order_records"]
  }
}
```

房型 / Rate Code 无法唯一确认时的典型 reason_code 可使用：

- `ROOM_TYPE_MAPPING_UNCONFIRMED`
- `ROOM_TYPE_MAPPING_MULTIPLE_CANDIDATES`
- `RATE_CODE_UNCONFIRMED`
- `SETTLEMENT_PRICE_REQUIRED`
- `MANUAL_PRICE_UNCONFIRMED`
- `RATE_CODE_RULE_NOT_COVERED`
- `COMPOSITE_UNIT_PRICE_UNCONFIRMED`
- `FIX_CHARGE_UNCONFIRMED`

## 12. Tool Invocation Placeholder

当前创建任务卡 / 可见记录的具体 Tool / API 尚未实现，本节只预留对接位置和语义契约，不定义最终 endpoint、鉴权方式或完整返回结构。

- tool_status: `TBD`
- suggested_tool_name: `create_task_card` / `TBD`
- tool_purpose: 根据信息系统统一任务卡创建接口，创建普通任务卡、人工复核 / 人工处理任务卡或信息系统可展示记录。
- followup_tool_name: `create_fix_charge` / `TBD`
- followup_tool_purpose: 当 New Booking 创建成功并取得 reservation / confirmation / PMS booking id 后，为对应订单添加 Fix Charge / 固定费用。
- tool_owner: 信息系统。
- caller: AI Runtime / Main Agent / Skill Orchestrator，最终由系统架构确认。
- invocation_timing: Skill 输出 `ai_task_result` 并通过 Unified Output Contract 校验后。
- followup_invocation_timing: 仅在 `create_task_card` 或后续信息系统流程确认 New Booking 已成功创建并取得订单 ID 后；如果订单 ID 尚未生成，只保留 `additional_operations`，不得编造 Tool 调用结果。
- payload_rule: Skill 能抽取出的字段照实填入；任务卡需要但无法抽取的字段填 `null` / empty，并在 `manual_review.missing_fields` 或 `manual_review.blocking_points` 中说明。
- mapping_payload_rule: 如果涉及房型映射或 Rate Code 判断，应将原始值、归一化值、命中 reference、命中规则摘要、最终代码或候选项写入 `extracted_fields`；不得只写最终结果而丢失依据。
- fix_charge_payload_rule: 如果涉及 Fix Charge，应将 `fix_charge_required`、`fix_charge_items`、`additional_operations`、原文证据、金额、币种、pricing mode 和后续 Tool 占位写入 `extracted_fields`；AI 不计算数量或总额。
- must_not_call_when:
  - Skill 输出不符合统一契约
  - current 事件完全不应进入 AI 工作台记录
  - 输出内容缺少任务卡 / 可见记录创建所需的最低溯源字段
- followup_must_not_call_when:
  - New Booking 尚未创建成功或缺少 reservation / confirmation / PMS booking id
  - Fix Charge 金额无法可靠提取
  - 复合单价无法可靠拆分
  - 输出内容不符合统一契约
- minimum_payload_should_include:
  - `source_message_id`
  - `source_event_index`
  - `catalog_code`
  - `skill_id`
  - `result_type`
  - `task_type`
  - `case_keys`
  - `visible_reason`
  - `relevant_message_excerpt`
  - `attachments`
  - `context_used`
  - `extracted_fields`
  - `manual_review`
  - `additional_operations`
  - `idempotency_key` / `TBD`
- expected_tool_result: `TBD`

Tool 设计原则：

- New Booking Skill 只调用一个统一任务卡创建 Tool：`create_task_card`。
- `create_fix_charge / TBD` 是后续执行 Tool，不替代 `create_task_card`，也不改变主任务类型。
- AI 不直接写数据库，只调用信息系统暴露的受控 Tool / API。
- 信息系统负责生成真实任务卡 ID、人工复核任务卡 ID 或可见记录 ID。
- 信息系统负责幂等、并发、状态机和最终落库。
- 信息系统在创建任务卡或执行前仍需做硬校验，不能只依赖 AI 判断。
- 如果 Tool 尚不可用，本 Skill 仍应输出合格的 `ai_task_result`；不得编造 Tool 调用结果。

## 13. Conflict Or Fallback Rule

- 如果当前事件同时像 New Booking 和 Update Booking，应优先查看 routing context。
- 如果 routing context 显示已有有效订单，第一版输出 `manual_review`，不继续创建 New Booking。
- 如果 routing context 显示已有 pending / open task 或 active workflow，第一版输出 `manual_review`。
- 如果房型映射或 Rate Code 判断无法唯一命中 reference，不由 Main Agent 自行猜测，由本 Skill 输出结构化 `manual_review` 或创建明确的手工价格维护任务。
- 如果仍无法判断是 New Booking、Update Booking 或其他任务类型，交由 `exception_detection_skill` 或输出 `manual_review`。
- Main Agent 不应自行把 New Booking 改判为 duplicate、exception 或 no_action。

## 14. Must Not Do

- 不得从 `body_thread` 生成 New Booking `normal_task`。
- 不得在同 key 已有有效订单记录时继续输出 `normal_task`。
- 第一版不得输出 `exception_task`。
- 第一版不得输出 `no_action`。
- 不得输出 `informational_message`；明确轻量消息通知应路由到 `message_notification_skill`。
- 不得在 Main Agent 中修补本 Skill 输出。
- 不得把 `manual_review` 输出成空泛的“人工看一下”。
- 不得在无法可靠确认字段时猜测字段值。
- 不得在 reference 未覆盖或无法唯一命中时猜测 Opera 房型代码。
- 不得在 reference 未覆盖或无法唯一命中时猜测 Rate Code。
- 不得忽略 reference 中“手工录入具体结算价格”的要求。
- 不得因为看到 `TWN` / `DBL` 或普通价格就触发 Fix Charge。
- 不得把 `2000+500` 合并为 `2500` 判断 Rate Code。
- 不得从复合单价表达计算 Fix Charge 数量或总额。
- 不得编造尚未实现的 Tool endpoint、鉴权、返回结构或调用结果。
- 不得绕过信息系统 Tool / API 直接创建真实 TaskCard。
- 不得写 Opera。
- 不得确认 Payment。
- 不得生成 Receipt。
- 不得修改数据库。
