# 人工复核 ## 入口结果边界 Gateway 必须先校验 `source_message.source_message_id`。该值为 `null`、空字符串或纯空白时,形成并校验 `00-output-contract.md` 定义的 `infrastructure_input_error`;不得读取正文、附件、OCR、历史或系统上下文,也不得调用 `booking-desk-event` skill。冻结该 error 后必须执行一次 mandatory submit,再原样返回;如果 Gateway 在 Main Agent 前短路,Gateway 必须执行同一最终提交钩子。 source message identity 合法后,Main Agent 才完成支持范围分类: - 当前输入可理解,但没有匹配 active event 时,输出 `S10`。 - 当前输入不足,无法判断是否匹配 active event 时,输出 `S99`。 - `S10` 和 `S99` 都展示源邮件并由用户自行决定是否回复或进行其他处理。 - `S10` 和 `S99` 不由 `booking-desk-event` skill 输出。 Thank you、裸 FYI、acknowledgement、Noted、Received 等没有具体预订业务信息的文字,以及一般咨询和当前不支持的 Booking Confirmation Request,都不匹配 Trace。FYI 或单纯告知中包含与明确预订对象相关的具体补充信息时,匹配 `Trace`。正文只有 `see attached` 且附件无法取得、无法识别业务方向时走 `S99`。 需要酒店批准的价格、退款、减免、账期、付款政策或合同条件询问不是 Trace。此类具有当前业务意义但没有任务卡承接的内容必须保留在 `unknowns`:同邮件存在支持事件时输出到 `unhandled_current_intents`,整封邮件没有支持事件时走 S10。意图清楚但不受支持不等于业务判断不安全,不得仅因此输出业务人工复核。 ## 两种业务人工复核 ### 已知业务卡型的人工复核 只要业务 `event_type` 和 subtype 已经能够确定,就必须保留该业务事件,继续输出能够安全抽取的字段,并令该 event 的 `manual_review` 为完整 `business_event_review` 对象。不得仅因为房型、Rate Code、目标对象或某项证据存在歧义,就把事件改成 `Need Manual Review`。 常见情形包括: - target object 不明确或不唯一,但业务卡型已确定; - current/history 边界不明确,但业务卡型已确定; - 已确定业务卡型,但其附件、OCR、表格或必要证据不可读; - required room type、Rate Code、settlement price 或其他必需字段无法唯一确定; - QBD/LianTai row、highlight 或 current-row evidence 缺失或歧义; - system context 显示 duplicate、pending/open task、active workflow、lock 或 conflict。 - Parent Group 的 `group_code` 与 `block_code` 原始候选冲突,但 `New Booking + Allotment / Control Block` 或 `Cancel Allotment` 卡型已确定;此时两 key 均置空,保留候选证据并使用 `target_object_unclear`。 - 完整 Parent split 已确认,但 child list、关系 index 或 parent-child 对应不完整;保留 linked `Cancel Allotment` 并使用 `parent_child_split_evidence_unclear`。 例如,正文明确 `please update the booking as attached`,因此业务卡型已经确定为 Update;附件不可读时仍输出对应 Update event,把安全取得的订单号、客人名等保留下来,并附非空 `manual_review`。Adapter 据此派生 `manual_review + 原业务 task_type + 原业务 subtype`,而不是 Fallback。 ### 业务类型或 subtype 未知的 Fallback 只有业务 `event_type` 或 subtype 本身无法确定时,才输出 `event_type=Need Manual Review`。Adapter 将其派生为: ```text manual_review + Fallback + business_event_review ``` 例如,同一段 current action 同时可能表示 New Booking 或 Update,且没有足够证据裁决,业务类型无法确定,此时才走 Fallback。 不得为了满足 Main Agent 的 skill-call gate 而制造 `Need Manual Review`。如果 Main 给出的所有粗候选都被 skill 否定,skill 返回内部 `no_supported_event` disposition,由 Main 转成 S10。 ## 必要结构和字段类型 业务级 `manual_review` 必须完整包含九个字段: ```json { "reason_code": "room_type_mapping_multiple_candidates", "visible_reason": "房型原文可识别,但无法唯一映射到当前有效 PMS 房型代码。", "review_record_type": "business_event_review", "missing_fields": [ "/extracted_fields/room_items/0/pms_room_type_code" ], "blocking_points": [ "pms_room_type_code is required before Preflight" ], "conflicting_points": [], "suggested_human_actions": [ "select_room_type_from_active_pms_catalog" ], "evidence_to_check": [ "current_body", "current_attachments" ], "known_fields": { "room_type_raw": "SUITE" } } ``` 固定规则: - 九个字段必须全部存在。 - `reason_code` 和 `visible_reason` 必须是非空字符串。 - `review_record_type` 固定为 `business_event_review`。 - `missing_fields`、`blocking_points`、`conflicting_points`、`suggested_human_actions`、`evidence_to_check` 固定为字符串数组;无内容时使用空数组。 - `known_fields` 固定为对象;没有已知值时使用空对象。 - `missing_fields[]` 每一项必须是指向当前 event 的 RFC 6901 JSON Pointer,例如 `/extracted_fields/room_items/0/pms_room_type_code`。不得填写人类说明、点号路径或根邮件路径。 - 不新增 `required_user_inputs`;前端业务卡字段注册表负责将 pointer 映射到可编辑控件。 - pointer 无法映射到该业务卡的已知可编辑字段时,属于 adapter contract error,不能展示一个无法完成的复核卡。 ## 房型和其他必需字段 房型原文可以识别但映射不唯一时: - 保留 `room_type_raw`; - `pms_room_type_code=null`; - 在 `manual_review.missing_fields` 中登记对应的 JSON Pointer; - 用户只能从信息系统提供的当前有效 PMS 房型目录中选择,不得由 Agent 猜测,也不得允许用户自由填写 PMS code。 Rate Code、价格或其他业务必需字段遵循相同原则:保留安全抽取值,待用户确认的目标字段置为 `null` 并用 pointer 标记。`requires_downstream_hard_validation` 不能替代这些字段的人工确认;也不得写成“人工复核或 downstream validation 二选一”。 一个 event 进入人工复核时,不得清空同邮件中的 sibling events。每个 event 独立派生路由:确定且完整的 sibling 仍为 normal task,需要确认的 sibling 保留其业务 task type/subtype 并进入 manual-review mode。 ## 同卡解阻状态 Agent 输出只描述初始业务判断,保持不可变。信息系统在同一张业务卡上维护复核状态,初始为: ```json { "review_status": "pending", "review_resolution": null } ``` 用户确认后保存: ```json { "review_status": "resolved", "review_resolution": { "field_overrides": [ { "field_pointer": "/extracted_fields/room_items/0/pms_room_type_code", "value": "SU1" } ], "resolved_by": "", "resolved_at": "" } } ``` 固定规则: - 原 Agent payload 和初始 `result_type=manual_review` 不得改写;当前页面模式由 `review_status` 控制。 - `field_overrides[].field_pointer` 必须与待解决字段 pointer 对应,覆盖值和审计信息由信息系统持有。 - 只有所有缺失字段完成、目录值校验通过、依赖字段重新校验通过后,才允许进入现有 Preflight。 - 在 Preflight 完成前不得写 PMS。 - 不创建第二张 linked normal task;解决后仍是同一张业务卡。 - 业务字段可以按权限编辑;邮件原文、raw evidence、source ID 和审计字段只读。 ## 常见 Reason Code - `current_history_boundary_unclear` - `target_object_unclear` - `multiple_target_candidates` - `attachment_or_ocr_unreadable` - `event_type_conflict_unclear` - `subtype_unresolved` - `room_type_mapping_unconfirmed` - `room_type_mapping_multiple_candidates` - `rate_code_unconfirmed` - `rate_code_rule_not_covered` - `settlement_price_required` - `manual_price_unconfirmed` - `composite_unit_price_unconfirmed` - `fix_charge_unconfirmed` - `qbd_liantai_row_evidence_unreadable` - `parent_child_split_evidence_unclear` - `stay_date_inference_unclear` - `existing_order_record_found` - `pending_or_active_workflow_found`