# S02 Update Booking / Amendment Skill

## 1. Skill Identity

- catalog_code: `S02`
- skill_id: `update_booking_amendment_skill`
- skill_name: `Update Booking / Amendment Skill`
- task_type: `Update Booking`

## 2. Purpose

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

第一版判断保持简单：

- 可以明确且安全创建修改任务：输出 `normal_task`
- 不能安全自动处理、需要人工判断或人工处理：输出 `manual_review`

本 Skill 第一版不输出 `exception_task`，也不输出 `no_action`。

进入 AI 工作台的 current 邮件事件，都应生成某种用户可见记录。对于感谢、确认、FYI、noted、received、confirmed receipt、无业务动作但需要展示的信息，不应路由到本 Skill；明确轻量消息应由 `message_notification_skill` 输出 `informational_message`。

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

Update Booking 可以携带 Fix Charge / 固定费用维护项。Fix Charge 不改变主任务类型；主任务仍是 Update 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
- 既有控房 / 配额对象

本 Skill 的内部 subtype 只用于识别修改内容、测试覆盖、任务卡展示和 payload 结构化，不拆分为多个 Tool。

支持的 subtype：

- `update_stay_dates`
- `update_nights`
- `update_room_type_or_quantity`
- `update_guest_count`
- `update_trace_or_guest_request`
- `update_group_block_linkage`
- `update_allotment_control_block`
- `manual_rate_code_or_settlement_price`
- `update_fix_charge`

`update_group_block_linkage` 不覆盖旧 Group Code 改为新 Group Code 的 `AMEND GROUP CODE` 事件；这类事件由 `amend_group_code_skill` 处理。

`update_trace_or_guest_request` 只用于标记 Trace / Guest Request 与其他核心 Update 同一 current 事件出现时的后台线索；独立 Trace / Reservation Notes / Guest Request 任务应走 S07。

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

- 不计入 `room_quantity`。
- 不影响 FIT / Group 判断。
- 不作为独立房型映射。
- 不单独决定 Rate Code。
- 如果与其他 Update Booking 修改同一事件或同一表格行出现，仍由本 Skill 处理 Update Booking 主任务，同时生成 S07 Trace / Reservation Notes linked task；先处理 S02，再处理 S07。
- 如果 current 邮件仅要求为既有订单添加、修改或取消 extra bed / 加床 / `เตียงเสริม`，应走 Trace / Reservation Notes Skill，不得当作普通房量修改。

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

- 不因为 `TWN` / `DBL` / 普通房型本身触发 Fix Charge。
- 不因为普通价格如 `2000THB`、`1800THB` 本身触发 Fix Charge。
- 当 current 事件或 LianTai 表格酒店说明价格区出现可拆分的复合单价结构，例如 `2000THB+500`、`1800THB+500`、`2000THB*2` 换行后 `+附加500*2`，可标记 `update_fix_charge`。
- `+` 前的房费单价组件用于 Rate Code 判断；`+` 后的附加费用单价组件写入 `extracted_fields.fix_charge_items`。
- 如果 current 邮件只要求为既有订单添加、修改或取消 Fix Charge，且目标订单和动作明确，可由本 Skill 处理；如果目标订单或动作不清，输出 structured `manual_review`。
- AI 不负责从该表达计算数量或总额。

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

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

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

## 4. When To Use

当 `body_current` 中要求修改既有订单、既有 Group Block、既有控房 / 配额 / Control Block 时，Main Agent 可以调用本 Skill。

典型修改包括：

- 修改入住 / 离店日期
- 修改晚数
- 修改房型 / 房量
- 修改人数
- 与上述核心修改同一事件出现的备注 / Trace / Guest Request；该类内容还应生成 S07 linked task
- 修改 confirmation / group / block 关联，但不包括旧 Group Code 改为新 Group Code 的 Amend Group Code 事件
- 维护既有控房 / 配额 / Control Block 的日期、房型、房量
- 手工维护 Rate Code / 实际结算价格
- 新增、修改或取消既有订单的 Fix Charge / 固定费用

## 5. Must Not Use When

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

- 当前邮件是在全新创建预订，应走 `new_booking_skill`。
- 当前邮件虽然包含 `AMEND` / `AMEND + FINAL BOOKING` / `AMEND TO` 字样，但实质是在把父团拆成多个子 `group_code` 并为每个子 code 创建配合房 / Allotment / Control Block；应走 `new_booking_skill`，不是 S02 before-after 修改。
- 当前邮件是在取消 FIT / Group Block / Allotment / Control Block，应走 `cancel_booking_skill`。
- 当前邮件只是提交 Rooming List / Name List。
- 当前邮件只是收到 Voucher / Credit Voucher / payment slip / payment confirmation。
- 当前事件明确包含旧 Group Code 改为新 Group Code 的 Amend Group Code 动作；若该动作与日期、晚数、房型、房量、人数、价格等修改属于同一不可拆分事件，主任务应走 `amend_group_code_skill`，其他修改只作为后台关联信息保留。
- 当前邮件只是添加、修改或取消 Trace / Reservation Notes / Guest Request，且没有其他日期、晚数、房型、房量、人数、价格或控房修改；应走 `trace_reservation_notes_skill`。
- 当前邮件只是为既有订单添加、修改或取消 extra bed / 加床 / `เตียงเสริม`，且没有其他日期、晚数、房型、房量、人数、价格或控房修改；应走 `trace_reservation_notes_skill`。
- 修改动作只出现在 `body_thread`，不在 `body_current`。

如果当前邮件没有明确修改动作，但属于感谢、确认、FYI、noted、received、confirmed receipt、转发说明等需要前端展示的信息提醒，不应路由到本 Skill，应由 `message_notification_skill` 输出 `informational_message`。

## 6. Allowed Result Types

第一版只允许：

- `normal_task`
- `manual_review`

第一版不输出：

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

原因：前三个核心 Skill 第一版先不做复杂异常任务分类，也不使用 no_action。无法安全自动处理的 current 邮件事件，统一生成结构化 `manual_review`，供信息系统创建用户可见记录；明确轻量消息通知由 `message_notification_skill` 处理。

## 7. Key Context Needed

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

- `source_message_id`
- `source_event_index`
- 当前邮件事件文本，只能来自 `body_current`
- 当前邮件相关附件摘要
- `group_code`
- `confirmation_number`
- `routing_context`
- 既有 FIT / Group Block / Allotment / Control Block 上下文
- pending / open task 上下文
- active workflow 上下文
- terminated record 上下文
- before / after 所需的上下文摘要
- 可用历史证据上下文
- 房型原文、床型、人数、是否套房、是否家庭房等可用于房型映射的线索
- 渠道 / 市场类别、supplier、备注价格、是否含早餐、用餐餐厅、实际结算价格等可用于 Rate Code 判断的线索
- extra bed / 加床 / `เตียงเสริม` 等 Trace / Guest Request 线索
- LianTai 复合单价、附加费、Fix Charge 原文线索

`routing_context` 至少应覆盖：

- 同 key 是否已有有效订单记录
- 同 key 是否已有 pending / open task
- 同 key 是否已有 active workflow
- 同 key 是否已有 terminated record
- 当前对象状态是否支持继续创建修改任务

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

## 8. Input Requirements Summary

本 Skill 输入应包含：

- 当前修改请求摘要
- `body_current` 中的相关原文片段
- 附件摘要
- 已提取的核心 key
- routing context
- 可用历史证据上下文
- 能帮助建立 before / after 的系统上下文或历史证据
- 能帮助识别 Fix Charge / 固定费用的复合单价、附加费、酒店说明列原文
- 与修改任务同一事件出现的 Trace / Guest Request 线索，例如 extra bed / 加床 / `เตียงเสริม`

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

具体字段抽取、字段标准化、房型映射、Rate Code 判断、价格规则、before / after 详细结构，应放在本 Skill 后续详细字段章节或统一输出契约中维护。

### 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 事件或 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`、`AMEND BOOKING`、`AMD`、`AMEND GROUP CODE`、`AMD ALLOTMENT`、`CXL`、`CFM`、黄色 / 高亮行、红字、划线、`โรงแรม` 或酒店状态列等线索。
  - 用于判断 Excel highlighted / yellow rows、QBD current-row selection、黄色 / 高亮行如何拆成独立 current events、LianTai hotel column date parsing、strikethrough before/after、AMD/CXL/CFM status evidence、以及 FIT vs Group decision by total room quantity。

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 识别出多个当前有效黄色 / 高亮修改行，必须按行拆分：一行一个 `source_event_index`，一行一个 `ai_task_result`，一行一个下游 task card 候选；不得跨行合并。
- 即使多行共享同一 `group_code`、`confirmation_number`、日期、酒店、批次、supplier、主题或附件，也不得合并为一个 Update Booking task。
- 不得用单个结果里的 `source_event_count`、数组型 `case_keys.group_code`、汇总型 `highlighted_rows` 或跨行 `before_after` / `room_items` 代替多个逐行 `ai_task_results`。
- 如果一行内包含多个房型 / 房量 / 价格 / before-after 明细，可放入该行自己的 `extracted_fields.room_items`、`extracted_fields.before_after` 或等价结构；不同表格行之间不得合并。
- 如果某一行信息不完整或不能安全处理，只让该行输出结构化 `manual_review`，不得阻塞其他可正常处理的行。
- Extra bed / 加床 / `เตียงเสริม` 是 Trace / Guest Request，不得计入 `room_quantity`，不得影响 FIT / Group 判断，不得作为独立房型映射，不得单独决定 Rate Code。
- 如果 extra bed 与 Update Booking 同一表格行出现，主任务仍是 Update Booking；同时生成 S07 linked task，并在后台 payload 保留 extra bed 数量和原文。
- 除非邮件明确修改房数，否则不得把 extra bed 当作 `update_room_type_or_quantity`。
- 房型映射不得覆盖原始房型关键线索。即使 `U-TWN` 与 `Sup 高级房TWN` 都映射到 `RM3`，或 `U-DBL` 与 `Sup 高级房DBL` 都映射到 `RM2`，Rate Code 仍必须按原始 `U-` / `Sup` / `高级房` 线索判断。
- 如果 reference 明确要求手工录入或修改价格，且实际价格可可靠提取，可以输出 `normal_task`，并在 `extracted_fields` 中标记手工价格维护要求。
- 如果 LianTai 复合单价表达与 Update Booking 同一事件或同一表格行出现，主任务仍是 Update Booking；将房费单价组件写入 `rate_code_result`，将附加费用单价组件写入 `fix_charge_items`，并可标记 `update_fix_charge`。
- 没有复合单价或附加费组件时，继续按既有房型 / Rate Code 规则处理，不因缺少 Fix Charge 输出 `manual_review`。
- 如果房型、渠道、市场类别、早餐、餐厅、价格或上下文不足以唯一命中规则，输出结构化 `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. 先确认修改动作是否出现在 `body_current`。
2. 如果修改动作只出现在 `body_thread`，不得输出 `normal_task`。
3. 判断当前事件是否确实是修改既有对象，而不是新建、取消、名单、Voucher 或 Amend Group Code。
   - 如果 `body_current` 是 parent-to-child 配合房 / Allotment 创建，即父 group code 后列出多个新 child group code、日期、房型和房量，按 S01 New Booking 处理；不要因为标题或正文含 `AMEND` 而要求建立 S02 的 before / after。
4. 如果能提取到 `group_code` 或 `confirmation_number`，必须使用对应 `routing_context`。
5. 如果涉及房型映射，应读取 `references/room_type_mapping_rules.md`；只有唯一命中时，才可填入 Opera 房型代码。
6. 如果涉及 Rate Code 或结算价格，应读取 `references/rate_code_rules.md`；只有唯一命中或满足 reference 中“手工价格仍可 normal_task 的条件”时，才可继续创建任务。
7. 如果 current 邮件、附件、发件人、主题或抽取证据显示 QBD / LianTai Excel/table workflow，应读取 `../references/qbd_liantai_email_table_rules.md`；只有当前表格行、高亮 / 黄色行、before / after、状态证据和对象类型可靠时，才可基于表格输出 `normal_task`。
8. 对 QBD / LianTai 表格中的多个当前有效黄色 / 高亮修改行，必须按行拆分；每一行生成独立 `source_event_index` 和独立 `ai_task_result`，不得跨行合并，不得用 `source_event_count` 或数组型 `case_keys.group_code` 代替。
9. 如果 extra bed / 加床 / `เตียงเสริม` 与 Update Booking 同一事件出现，主任务仍是 Update Booking，同时生成 S07 linked task；不得把 extra bed 数量计入 `room_quantity`，不得用于 FIT / Group 判断，不得单独触发 `update_room_type_or_quantity`。
10. 如果 current 邮件只是为既有订单添加、修改或取消 extra bed / 加床 / `เตียงเสริม`，不得路由为普通 Update Booking；应路由到 Trace / Reservation Notes Skill。
11. 如果 LianTai 复合单价表达出现，应按 `references/rate_code_rules.md` 拆分房费单价和 Fix Charge 单价；不得把 `2000+500` 合并为 `2500` 判断 Rate Code。
12. 如果 current 邮件只要求为既有订单添加、修改或取消 Fix Charge，必须能确认目标订单和动作类型；否则输出结构化 `manual_review`。
13. 如果当前事件明确是修改既有对象，并且 routing context 支持继续处理，且房型 / Rate Code / Fix Charge / QBD-LianTai 表格相关规则已可靠处理，输出 `normal_task`。
14. 如果不能安全自动处理，输出结构化 `manual_review`。
15. 如果当前邮件是感谢、确认、FYI、noted、received、confirmed receipt、转发说明等轻量信息，但需要用户可见记录，不应路由到本 Skill，应由 `message_notification_skill` 输出 `informational_message`。

以下情况第一版统一输出 `manual_review`：

- 找不到原订单。
- 前置任务未完成。
- 目标对象不明确。
- 邮件内容冲突。
- 关键信息缺失。
- 状态不允许修改。
- 房型无法确认。
- 房型映射 reference 未覆盖当前表达。
- 房型映射存在多个候选或需要床型 / 人数等补充信息。
- Rate Code 或结算价格无法确认。
- Rate Code reference 无法根据渠道、市场、房型、早餐、餐厅或备注价格唯一匹配。
- reference 要求手工录入价格，但实际结算价格无法可靠提取。
- 手工价格维护条件未全部满足，例如目标订单不存在或状态不允许修改、房型未唯一映射、价格不来自 `body_current` / 当前表格行、价格不可读、before / after 不可靠，或 routing context 不支持继续处理。
- 出现复合单价或附加费用线索，但无法判断哪一段是房费单价、哪一段是附加费用单价。
- Fix Charge 金额无法可靠提取，同一行多个价格组件无法归属，或无法确认是新增、修改还是取消 Fix Charge。
- before / after 无法可靠建立。
- 例外：parent-to-child 配合房 / Allotment 创建不属于 S02 修改，不因缺少 S02 before / after 输出本 Skill 的 `manual_review`；应重新路由到 S01。
- 当前邮件只有 extra bed / 加床 / `เตียงเสริม` 维护请求，但无法安全绑定目标对象或备注内容不可读。
- QBD / LianTai 表格触发信号存在，但表格、黄色 / 高亮行、行号、划线、before / after 或当前行证据不可读、缺失或不明确。
- 当前邮件像修改，但也可能是新建、取消或改 Group Code。
- 修改可能已经处理过。
- 重复提交。
- 当前邮件没有新的有效修改动作，但与既有订单上下文相关，且无法安全判断是否需要人工处理。

## 10. Normal Task Output

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

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

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

关键要求：

- `source_message_id` 必须原样带回。
- `source_event_index` 必须原样带回。
- `case_keys.group_code` 和 `case_keys.confirmation_number` 按实际提取结果填写。
- `extracted_fields.update_subtypes` 必须填入识别到的 subtype。
- `extracted_fields.before_after` 应填入可可靠建立的修改前 / 修改后字段。
- 如果涉及房型映射，应在 `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_target_order_id`；如果后续系统使用其他状态枚举，以信息系统契约为准。
- 如果来自 QBD / LianTai 表格行，应在 `extracted_fields` 中保留该行的附件名、sheet 名、行号或行标签、高亮状态、动作 / 状态单元格、原始日期、原始房型、原始房量、原始价格和 before / after 证据；一行内多个房型 / 房量 / 价格明细应放入该行自己的 `room_items`、`before_after` 或等价结构。
- 如果来自 QBD / LianTai 多行表格，单个 `ai_task_result` 只能代表一个当前有效行；`case_keys.group_code` 应只填该行 key。
- 如果同一事件包含 extra bed / 加床 / `เตียงเสริม`，应生成 S07 linked task；同时可在本任务后台 payload 中保留原文、数量和说明，`room_quantity` 必须排除 extra bed 数量。
- `visible_reason` 应说明为什么这是当前邮件中的可创建修改任务。
- `relevant_message_excerpt` 必须来自 `body_current`。
- `attachments` 只包含当前事件相关附件。
- `context_used` 应记录用于判断的 routing context 摘要。
- `context_used` 应记录使用的 reference 文件与命中规则摘要。

## 11. Manual Review Output

当邮件看起来与 Update Booking / Amendment 相关，但不能安全自动创建修改任务时，输出：

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

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

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

- 能确定的 `case_keys` 必须填入。
- 能确定的 `update_subtypes` 必须填入 `extracted_fields`。
- 能可靠建立的 before / after 字段，应填入 `extracted_fields.before_after`。
- 能确定的原始房型、归一化房型、候选 Opera 房型代码、候选 Rate Code、候选结算价格，应尽量填入 `extracted_fields`。
- 能确定的复合单价拆分结果和 Fix Charge 单价，应尽量填入 `extracted_fields.rate_code_result` 与 `extracted_fields.fix_charge_items`。
- 不能可靠建立 before / after 的字段，不要猜，填 `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 文件名以及需要人工核对的邮件片段、附件或系统上下文。

建议结构：

```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": {
    "update_subtypes": ["update_room_type_or_quantity"],
    "before_after": {
      "room_type": {
        "before": null,
        "after": "Deluxe Twin"
      },
      "room_quantity": {
        "before": 10,
        "after": 12
      }
    }
  },
  "manual_review": {
    "reason_code": "BEFORE_VALUE_UNCONFIRMED",
    "visible_reason": "无法自动创建修改任务：修改前房型无法可靠确认。",
    "review_record_type": "manual_review_required",
    "blocking_points": ["无法可靠确认修改前房型"],
    "missing_fields": ["before_room_type"],
    "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: 当目标订单已确认并取得 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` 或后续信息系统流程确认目标订单 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 工作台记录
  - 修改动作不在 `body_current`
  - 输出内容缺少任务卡 / 可见记录创建所需的最低溯源字段
- followup_must_not_call_when:
  - 目标订单缺少 reservation / confirmation / PMS booking id
  - Fix Charge 金额无法可靠提取
  - 复合单价无法可靠拆分
  - 无法确认是新增、修改还是取消 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 设计原则：

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

## 13. Conflict Or Fallback Rule

- 如果当前事件同时像 Update Booking 和 New Booking，应优先查看 routing context。
- 如果当前事件的 `AMEND + FINAL BOOKING` 表达实际是在创建子 group 配合房 / Allotment，优先交给 S01；父团号只作为 parent evidence，不作为 S02 修改目标。
- 如果 routing context 显示已有有效订单且当前邮件表达为修改，优先按 Update Booking 判断。
- 如果当前事件同时包含改 Group Code 和日期、房型、房量等修改，能拆分为独立 current 事件时分别路由；如果属于同一不可拆分事件，主任务走 `amend_group_code_skill`，本 Skill 不再为该事件另建任务卡。
- 如果无法确认原订单是否存在，不由 Main Agent 直接输出 `CASE_NOT_FOUND`，由本 Skill 输出结构化 `manual_review`。
- 如果房型映射或 Rate Code 判断无法唯一命中 reference，不由 Main Agent 自行猜测，由本 Skill 输出结构化 `manual_review` 或创建明确的手工价格维护任务。
- 如果多个 Skill 冲突且无法安全拆分，交由 `exception_detection_skill` 或输出结构化 `manual_review`。

## 14. Must Not Do

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