Files
th-hotel-simple/docs/project/requirements/M002-order-task-workflow-v3.md

489 lines
38 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# M002 Order Task Workflow 订单任务主流程 V3
## 文档信息
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.4 |
| 日期 | 2026-07-18 |
| 状态 | 0712 P0.1 增量确认版;已补充 M002 V4 CP1 入站现状和 CP2 多卡模型设计入口 |
| 适用范围 | SourceMessage 之后的 SuperAgent 输出适配、任务路由、只读通知卡、人工复核同卡解阻、前后端协作边界 |
| 主要读者 | 产品、后端、前端、测试、SuperAgent 对接方、后续协作 agent |
## 1. 文档定位
本文是 `M002-order-task-workflow-v2.md` 的第三版修正。V2 记录了当前后端阶段实现:`ai_task_results[]``S000/S999` 文本结果、订单任务基础流转、任务草稿确认、OPERA 模拟骨架、SuperAgent 查询上下文接口和前端 P0 查询接口。
V3 记录 2026-07-11 导入的 SuperAgent P0 冻结基线、2026-07-12 导入的 P0.1 Parent Group 语义修订,以及本项目已经确认的产品决策。后续 M002 新开发应优先按本文和 `M002-v3-p0.1-parent-group-routing-update.md` 执行;当前代码中已经存在的 V2 行为,需要按 checkpoint 逐步兼容迁移,不能在未实现前对外宣称已经完成。
本文不替代 `docs/project/integrations/superagent-api-contract.md` 的线上联调接口说明。若要给 SuperAgent 联调方使用,必须在对应接口实现完成后同步更新该对外契约。
## 2. 权威输入资料
V3 以以下资料和决策为输入:
| 资料 | 用途 |
| --- | --- |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/README_交付说明.md` | 0711 P0 交付边界、可先实现范围、P1/P2 暂缓范围 |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/01_Adapter_Frontend/任务卡前端字段变更与路由说明_3.0_to_current.md` | Adapter / Frontend 的 P0 路由、人工复核、fail-closed 规则;其中 Parent split / 42 路由部分已被 0712 P0.1 覆盖 |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/01_Adapter_Frontend/任务卡前端字段变更说明_3.0_to_当前版_2026-07-10.xlsx` | P0 字段、三元组路由、旧枚举迁移、非法组合和验收用例 |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/02_AI_Runtime/main_agent_prompt.md` | 当前 Main Agent 运行提示词 |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/02_AI_Runtime/booking-desk-event.skill` | 当前 Skill 包 |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/02_AI_Runtime/核心契约_展开阅读/*.md` | 输出契约、事件路由、内容完整性、Main 到 Skill 输入、人工复核规则 |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/03_P0_Acceptance/` | P0 fixtures 和轻量 validator |
| `docs/import/20260711/开发交付_P0冻结基线_2026-07-11/04_Known_Issues_非契约/` | P1/P2 未闭合范围,只用于识别暂缓和 fail-closed不作为生产规则源 |
| `docs/import/20260712/开发交付_P0_to_P0.1_增量修订说明_给开发Codex_2026-07-11.md` | Parent Group / Allotment 语义修订、40 路由、当前 producer 禁止旧 Parent Cancel Booking |
| `docs/import/20260712/Agent 0711 1743/**` | P0.1 Main Agent prompt、booking-desk-event skill 和 references |
| `docs/import/20260712/前端字段控件修改说明_给信息系统小伙伴Codex_2026-07-12.md` | 前端字段控件、人工复核编辑、只读证据和验收用例输入;本项目落地口径见 `M002-task-field-control-contract-v1.md` |
| `docs/project/requirements/M002-v3-p0.1-parent-group-routing-update.md` | 本项目对 P0.1 增量的落地说明和验收清单 |
| `docs/project/requirements/M002-task-field-control-contract-v1.md` | 本项目任务卡字段控件契约 V1后端已扩展 `fields[]`,前端后续按该契约渲染字段和同卡复核输入 |
本项目确认的产品决策:
- M002 V3 正式采用 0711 P0 基线,并从 2026-07-12 起采用 P0.1 Parent Group / Allotment 增量修订。
- 旧数据 `S000/S999` 继续在任务列表可见;新数据迁移为 `S10/S99`
- M002 V3 / P0.1 阶段 `S10/S99` 继续复用隐藏技术订单 + 任务列表只读卡不进入订单列表和订单执行队列M002 V4 新模型已确认 S10/S99 改为来源通知模型,不再挂隐藏技术订单。
- 缺少 `source_message.source_message_id` 时,后端已按 `HTTP 400 + infrastructure_input_error + retryable=true` 的技术错误响应返回,不创建 SourceMessage、AI transition、订单、任务或通知卡。
- 内部任务模型采用“方案 C”完整保存 AI 三元组,系统处理分类和前端展示分类单独维护。
- type-known manual review 使用同一张业务卡复核解阻,不生成第二张 normal task。
- 第一版保存全部 40 条 P0.1 路由 / 枚举,先支持保存和列表展示。
- `Allotment / Control Block = Parent Group`;完整 Parent split 的父事件必须是 `Cancel Allotment + cancel_allotment_control_block`,不是普通 `Cancel Booking`
- P1/P2 未闭合范围命中时 fail closed不由本系统发明字段或业务规则。
- 普通任务切换订单继续后置P0 仅支持“复核场景下确认订单归属”。
## 3. 相对 V2 的核心变化
| 主题 | V2 | V3 |
| --- | --- | --- |
| SuperAgent 业务输出 | 顶层 `source_message_id + ai_task_results[]` | 顶层 `source_message + message_events[] + case_candidates[] + extraction_warnings[] + unhandled_current_intents[]` |
| 信息类 / 入口问题 | `text/plain``S000,source_message_id` / `S999,source_message_id` | 结构化 JSON`S10` / `S99``result_type=source_message_review_notification` |
| 任务路由 | 以 `result_type + task_type + task_subtype` 粗映射系统主任务 | 按每个 `message_events[i]` 派生 40 条 P0.1 三元组 |
| 人工复核 | Fallback / manual_review 可转换为业务任务 | type-known review 保留原业务卡;只有类型或 subtype 未知才走 Fallback |
| 复核解阻 | 偏“转换”思路 | 同卡 `review_status + review_resolution.field_overrides[]` 解阻 |
| Message Notification | 历史信息提醒任务 | 新入口统一使用 `S10/S99` 只读源邮件通知卡;历史数据兼容展示 |
| P1/P2 未闭合 | 部分规则可能由系统先做 | 明确 fail closed / adapter_contract_error不猜测 |
## 4. SourceMessage Identity 和入口错误
### 4.1 SourceMessage ID 口径
`source_message.source_message_id` 是 SuperAgent 从上游输入原样带回的外部来源消息 ID对应 AgentBus 邮件 payload 中的 `source.external_message_id`。它不是本系统内部 `platform_source_message_inbox.id`
后端处理时按以下路径反查:
```text
系统酒店 + source_message.source_message_id
→ platform_source_message_inbox.external_message_id
→ platform_source_message_inbox.id
→ workflow / task / transition 表内部 source_message_id 外键
```
V3 第一版继续使用单酒店阶段的系统默认酒店后续多酒店或权限收口时再扩展显式酒店上下文。SuperAgent 不需要传数据库层 provider/channel`source_message.source_channel=Email` 只是上游消息渠道语义;后端以 SourceMessage Inbox 的真实入库 provider/channel 为准。同一系统酒店下如果出现多条相同 `external_message_id`,后端返回 `SOURCE_MESSAGE_AMBIGUOUS`,不随机选择。
### 4.2 缺少 source_message_id
Gateway 必须在读取正文、附件、OCR、历史、系统上下文或调用 Skill 前校验 `source_message.source_message_id`
为空时,目标契约响应:
```json
{
"result_type": "infrastructure_input_error",
"error_code": "missing_source_message_id",
"retryable": true,
"missing_fields": [
"source_message.source_message_id"
]
}
```
当前 CP6 实现说明:后端已识别 V3 `source_message.source_message_id` 缺失,并返回上方 typed `infrastructure_input_error` 结构。
处理要求:
- HTTP 状态码第一版使用 `400`
- 不创建 SourceMessage、AI transition、订单、任务、通知卡或审计业务记录。
- 不把该错误当成 `S10/S99`、Fallback 或人工复核。
- 调用方可修正输入后重试。
## 5. SuperAgent 输出分流
V3 接收端按根结构分流:
```text
1. infrastructure_input_error
→ 返回技术错误,不建卡。
2. source_message_review_notification + route_code=S10/S99
→ 创建只读源邮件通知卡,任务列表可见,订单列表不可见。
3. 业务根 source_message + message_events[]
→ 按每个 message_events[i] 派生业务任务或复核任务。
4. unhandled_current_intents[]
→ 仅保存和展示为源邮件详情 / 任务详情中的未覆盖业务意图块,不自动创建业务任务卡。
```
`candidate_events[]` 是 Main 到 Skill 的内部输入,不属于最终入站结果。本系统不得把它当成最终任务卡或持久化业务事实。
## 6. S10 / S99 处理规则
### 6.1 新入口结果
`S10``S99` 均为结构化入口通知结果:
| route_code | result_type | 固定含义 | manual_review |
| --- | --- | --- | --- |
| `S10` | `source_message_review_notification` | 输入可理解,但没有匹配当前支持的 active 业务事件 | `null` |
| `S99` | `source_message_review_notification` | 输入不足,无法形成业务素材包或判断支持范围 | 完整 `main_agent_entry_review` |
两者都要求用户查看源邮件并自行决定是否回复或处理,不代表系统可以自动忽略邮件。
### 6.2 系统落地
新数据 `S10/S99` 的系统处理规则:
- 按外部 `source_message.source_message_id` 反查 SourceMessage Inbox。
- 创建隐藏技术订单,仅用于满足任务外键或列表聚合需要。
- 创建只读源邮件通知卡,任务列表可见。
- 订单列表不可见;订单详情不能作为普通订单页打开。
- 不参与订单任务执行队列,`queue_participation=false`
- 不阻塞任何订单任务,也不被任何订单任务阻塞。
- 不允许保存草稿、最终确认、复核转换、普通切换订单、执行 OPERA、重试 OPERA。
- 任务详情展示来源邮件、邮件会话、附件、SuperAgent 原始返回、`route_code` 和入口说明。
以上是 M002 V3 / P0.1 当前实现口径。M002 V4 新模型落地时S10/S99 改为来源通知模型:任务列表 / 工作台展示点击进入纯通知详情页只显示邮件展示卡和确认按钮不创建订单、不进订单列表、不参与订单阻塞也不支持编辑、复核、OPERA 或人工终止。
### 6.3 旧 S000 / S999 兼容
旧数据 `S000/S999` 已经在系统中以只读特殊任务展示。V3 不删除旧数据,也不要求历史回写。
兼容规则:
-`S000` 在前端和查询层按 `S10` 语义展示。
-`S999` 在前端和查询层按 `S99` 语义展示。
- 如果旧任务已经是 `SOURCE_MESSAGE_ONLY` 或等价只读类型,继续在任务列表可见。
- 新入站不再优先使用 `S000/S999` 文本格式;实现迁移前,对外契约应清楚标记当前代码支持范围。
## 7. Adapter 路由模型
### 7.1 40 条 P0.1 路由
V3 第一版必须保存并支持以下路由类别:
- 18 个业务 subtype每个 subtype 都有 normal 和 type-known manual review 两条路由,共 36 条。
- `S10``S99` 两条源邮件通知路由。
- 类型或 subtype 未知的 Fallback 路由:`manual_review + Fallback + business_event_review`
- `unhandled_current_intent + Unhandled Current Intent + requires_business_approval_or_unsupported_task_card` 展示路由。
第一版后端要求:
- 40 条路由全部进入枚举或稳定配置,不能只硬编码已实现的少数几条。
- `route_code` 是历史稳定码,不因 P0.1 总数从 42 调整为 40 而重编号;`R41_FALLBACK_BUSINESS_EVENT_REVIEW``R42_UNHANDLED_CURRENT_INTENT` 继续保留。
- 每条入站 event 都按自己的 `message_events[i]` 独立派生,不能在邮件根只生成一个任务。
- 同一封邮件多个任务按 SuperAgent 返回数组顺序和事件顺序生成执行顺序。
- `Note``Allotment Maintenance``update_allotment_control_block` 仅历史兼容,不允许新数据生成。
- 当前 producer 不允许再生成 `normal_task/manual_review + Cancel Booking + linked_parent_release_after_child_split`
- `relationship_type=linked_parent_release_after_child_split` 只用于 Parent / Child 关联和 Preflight不再决定 `task_subtype`
- 旧 V2 兼容 `ai_task_results[]` 若继续提交 `Cancel Booking + linked_parent_release_after_child_split`,按请求级 `ADAPTER_CONTRACT_ERROR` 拒绝,不创建业务任务,也不创建 AI transition。
- Parent 只提供 `group_code` 或只提供 `block_code`adapter 可以在派生副本中补齐另一边用于路由和落库;原始 payload 不回写。
- Parent 的 `group_code``block_code` 原始候选冲突时不猜测。若 SuperAgent 已输出 `manual_review.reason_code=target_object_unclear``context_used.parent_identity_candidates[]` 非空,创建同卡 type-known manual review否则写入 adapter contract error。
P0.1 Parent Group 路由规则:
| 场景 | 合法事件 / 三元组 | 系统处理 |
| --- | --- | --- |
| Child Group 创建 | `normal_task/manual_review + New Booking + new_group_block` | 创建 New Booking 业务任务 |
| Parent Group 完整释放 / 取消 | `normal_task/manual_review + Cancel Allotment + cancel_allotment_control_block` | 创建 Cancel Allotment 业务任务卡 |
| 旧 Parent split 新入站 | V3 `Cancel Booking + linked_parent_release_after_child_split` | 按 event 写入 `adapter_contract_error`,不创建业务任务 |
| 旧 Parent split V2 兼容入口 | V2 `ai_task_results[]` 中的 `Cancel Booking + linked_parent_release_after_child_split` | 请求级 `ADAPTER_CONTRACT_ERROR` 拒绝,不创建业务任务 / AI transition |
| 重复 Parent 候选 | 同一 Parent Group 再次输出合法 Parent 候选 | 第二个及后续 Parent 写入 `adapter_contract_error` |
| Parent key 单边缺失 | `group_code``block_code` 仅有一边 | 在派生副本中补齐另一边,继续创建 Cancel Allotment 业务任务卡 |
| Parent key 候选冲突 | 双 key 无法安全归一,且 `target_object_unclear + parent_identity_candidates[]` 完整 | 创建 Cancel Allotment 同卡人工复核任务 |
| 历史旧 payload 只读展示 | `Cancel Booking + linked_parent_release_after_child_split` | reader / adapter 展示层可归一为 Cancel Allotment不改写原 payload |
### 7.2 方案 CAI 三元组和系统处理分类分离
V3 内部模型采用方案 C避免把 SuperAgent 的任务三元组直接等同于本系统执行分类。
建议保存三层信息:
| 层级 | 字段示例 | 中文说明 |
| --- | --- | --- |
| AI 原始路由 | `ai_result_type``ai_task_type``ai_task_subtype``route_code` | 完整保存 SuperAgent 输出,不因系统处理而丢失 |
| 系统处理分类 | `system_process_category``system_task_type``queue_participation``readonly` | 决定是否进入订单队列、是否可编辑、是否可确认、是否可执行 |
| 前端展示分类 | `card_display_type``card_title_code``route_display_code` | 决定任务列表和详情如何展示 |
这样可以同时支持:
- `S10/S99` 有 AI 三元组,但不是业务执行任务。
- `unhandled_current_intent` 可展示,但不自动建业务任务卡。
- 新增业务卡可以先保存和列表展示,后续再逐步接校验和 OPERA adapter。
- type-known manual review 保留原业务 subtype不被强行改成 Fallback。
## 8. 业务任务和订单挂靠
### 8.1 业务任务
`normal_task` 业务事件可以按既有订单/任务模型生成业务任务;用户确认前不得执行 OPERA。
第一版应至少保留以下业务标识:
- `source_event_index`
- `array_index`
- `event_type`
- `ai_result_type`
- `ai_task_type`
- `ai_task_subtype`
- `route_code`
- `case_keys`
- `manual_review`
- `ai_payload_json`
- `review_status`
- `review_resolution`
### 8.2 订单归属
订单归属第一版规则:
- `New Booking` 无可靠业务号时创建临时订单。
-`group_code``confirmation_number` 等可定位字段时,优先挂靠或创建相应订单。
- 同一个 `hotel_id + GROUP_CODE` 只能有一个 `ACTIVE` 订单。
- 同一个 `hotel_id + CONFIRMATION_NUMBER` 只能有一个 `ACTIVE` 订单。
- M002 V3 / P0.1 当前实现中,`S10/S99` 使用隐藏技术订单不进入订单列表M002 V4 S10/S99 目标模型改为独立来源通知,不再挂订单。
P0 新增明确:复核场景下需要支持用户确认订单归属。它不是普通任务切换订单:
| 能力 | V3 范围 |
| --- | --- |
| 复核过程中确认 / 选择订单归属 | P0 需要支持 |
| type-known manual review 解决字段同时确认订单归属 | P0 需要支持 |
| Fallback 被用户判定为 New / Update / Cancel 并确定订单归属 | P0 需要支持 |
| 已创建普通任务任意切换到其他订单 | 继续后置,不在 P0 |
## 9. Type-known manual review 同卡解阻
### 9.1 路由原则
只要 SuperAgent 已能确定业务 `event_type` 和 subtype就必须保留原业务类型和 subtype。字段、目标对象、房型、Rate Code、证据或上下文不安全时使用同一业务卡的 manual-review mode。
只有业务类型或 subtype 本身无法确定时,才使用:
```text
manual_review + Fallback + business_event_review
```
### 9.2 状态模型
Agent payload 不可变。本系统在同一张卡上维护复核状态:
```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",
"field_path": "extracted_fields.room_items.0.pms_room_type_code",
"legacy_field_path": "extracted_fields.pms_room_type_code",
"value": "SU1"
}
],
"confirmed_order_id": "10001",
"resolved_by": "<user_id>",
"resolved_at": "2026-07-11T00:00:00Z"
}
}
```
要求:
- 不改写 `ai_payload_json`
- 不创建第二张 linked normal task。
- `missing_fields[]` 必须是 RFC 6901 JSON Pointer。
- 入站阶段 `missing_fields[]` 不完整或不是 RFC 6901 Pointer 时,按 `adapter_contract_error` fail closed不创建业务任务。
- 解阻接口提交的 Pointer 必须能映射到该业务卡当前可展示且可编辑字段,否则返回 `TASK_REVIEW_POINTER_INVALID`
- 解阻接口 `field_overrides[]` 支持提交 `field_pointer``field_path``field_pointer` 使用 RFC 6901 JSON Pointer`field_path` 支持 P0 主矩阵路径和旧扁平路径。两者同时提交时必须指向同一个字段,否则按非法字段处理。
- 同一次解阻请求中 `field_overrides[]` 不允许重复指向同一 `field_pointer` 或同一矩阵 `field_path`,否则返回 `TASK_REVIEW_POINTER_DUPLICATE`
- 订单归属确认可作为复核解阻的一部分保存;当前第一版只允许确认当前任务所属订单,不开放普通任务随意切换订单能力。
- 全部缺失字段、订单归属、目录值和依赖校验通过后,才进入 Preflight / READY。
当前字段矩阵迁移第一版说明0711 P0 fixtures 中 `room_items[]` 已作为房型字段主结构。后端已将 New Booking 卡的房量、房型原文、PMS 房型代码主路径迁移为:
| 语义 | 主 `field_path` | 主 `field_pointer` | 旧兼容 key |
| --- | --- | --- | --- |
| 房量 | `extracted_fields.room_items.0.room_quantity` | `/extracted_fields/room_items/0/room_quantity` | `extracted_fields.room_quantity` |
| 房型原文 | `extracted_fields.room_items.0.room_type_raw` | `/extracted_fields/room_items/0/room_type_raw` | `extracted_fields.room_type` |
| PMS 房型代码 | `extracted_fields.room_items.0.pms_room_type_code` | `/extracted_fields/room_items/0/pms_room_type_code` | `extracted_fields.pms_room_type_code` |
入站 `ai_payload_json` 保留 SuperAgent 原始结构不回写用户修正。V3 `message_events[]` 归一化为任务卡时,会把 `relevant_message_excerpt` 同步到任务 item 根路径,便于旧字段矩阵读取证据字段。任务详情 `fields[]``field_path``field_pointer` 以 P0 主结构为准,`legacy_field_path` 仅用于前端过渡展示。草稿保存、最终确认的 `field_values` 可继续提交旧扁平 key同卡复核解阻可提交 `field_pointer``field_path`,其中 `field_path` 可为 P0 主路径或旧扁平路径。后端会归一化到 P0 主 `field_path`;响应中的 `field_values` 使用主路径,`legacy_field_values` 提供旧扁平回显兼容,`effective_payload` 提供嵌套结构供后续 OPERA 参数组装使用。当前第一版只支持 `room_items[0]`,非 0 下标或不存在路径按 `TASK_REVIEW_POINTER_INVALID` / 字段校验错误处理,不自动映射。
Parent / Allotment 的 `block_code` 是 SuperAgent 输入侧同义 key本系统订单和任务卡第一版统一落到 `case_keys.group_code`。因此 Parent key 冲突进入 `target_object_unclear` 复核时,即使 `manual_review.missing_fields[]` 同时包含 `/case_keys/group_code``/case_keys/block_code`,任务详情只要求用户填写 `case_keys.group_code`;后端复核解阻会把 `/case_keys/block_code` 视为 `case_keys.group_code` 的别名进行缺失字段校验。`Cancel Allotment / cancel_allotment_control_block` 第一版复用旧 `Cancel Booking` 字段矩阵,后端确认和复核解阻时会派生 `extracted_fields.cancel_object_type=allotment_control_block`,并允许 P0.1 的 `extracted_fields.cancel_scope=entire_allotment_control_block`
### 9.3 后端第一版接口
```text
POST /api/reservation/tasks/{taskId}/manual-review-resolutions
Content-Type: application/json
```
请求示例:
```json
{
"confirmed_order_id": "20001",
"reason": "确认 PMS 房型代码后解阻。",
"field_overrides": [
{
"field_pointer": "/extracted_fields/room_items/0/pms_room_type_code",
"field_path": "extracted_fields.room_items.0.pms_room_type_code",
"value": "RM3"
}
]
}
```
响应要点:
- `task_status=READY`
- `review_status=RESOLVED`
- `review_resolution.field_overrides[]` 同时返回 `field_pointer`、矩阵主 `field_path``legacy_field_path` 和人工值。
- `review_resolution.resolved_at` 使用带 `Z` 的 UTC 时间点。
- `confirmed_payload.field_values` 使用 P0 主 `field_path` 保存,`legacy_field_values` 仅用于旧扁平字段过渡回显;`effective_payload` 是嵌套结构,不等同真实 OPERA 参数。
- 通用最终确认不会放宽历史 V2 只读必填证据字段;仅对 V3 message_event 缺省的旧根 `visible_reason` 做窄口兼容,防止旧结构普通任务缺少证据仍进入 READY。
- 自动生成第一版固定两条 OPERA 模拟操作。
- 写入 `MANUAL_REVIEW_RESOLVE` 审计。
- type-known manual review 不允许走通用 `POST /api/reservation/tasks/{taskId}/confirm`,否则会返回 `TASK_REVIEW_RESOLUTION_REQUIRED`
## 10. P1/P2 未闭合范围处理
0711 导入包已经明确 P1/P2 未闭合。后端、前端、Adapter 都不得自行发明规则。
命中以下情况时,第一版应 fail closed
- 40 路由与 runtime 输出不一致或无法唯一匹配。
- `manual_review` 九字段不完整。
- `missing_fields[]` 不是 RFC 6901 pointer或无法映射到可编辑字段。
- Parent split 关系字段不完整或无法一一对应。
- 当前 producer 输出 `Cancel Booking + linked_parent_release_after_child_split`
- `Note``Allotment Maintenance``update_allotment_control_block` 新数据出现。
- Fix Charge、Preflight/lock、Fallback 非字段解阻、Voucher 文件对象缺失、Manual RateCode 边界等 P1/P2 未闭合场景。
处理建议:
- 单个 event 契约错误时,该 event 0 卡并记录 `adapter_contract_error`
- 同一邮件的 sibling events 继续独立处理。
- 契约错误不是人工复核,不能用 Fallback 吞掉。
- 前端应展示“契约问题 / 暂不支持”的稳定 code不把它当成可编辑业务卡。
## 11. 前端影响
前端需要按 V3 调整以下行为:
- 任务列表支持展示旧 `S000/S999` 和新 `S10/S99`,但新文案以 `S10/S99` 为主。
- `S10/S99` 只读卡只出现在任务列表和任务详情,不出现在订单列表。
- 任务列表不应仅按旧 `SOURCE_MESSAGE_ONLY` 判断;当前后端已返回 `route_code=S10/S99``result_type=source_message_review_notification`
- type-known manual review 不再统一展示成 Fallback应展示原业务卡名称和 subtype并显示复核状态。
- 复核解阻页需要能提交 `field_overrides[]`,并在复核场景下确认订单归属。
- `unhandled_current_intents[]` 只作为展示块,不提供执行按钮。
- P1/P2 fail-closed 返回时,前端展示稳定错误和源邮件入口,不让用户误以为可以确认执行。
- Parent split 父事件展示为 `Cancel Allotment / cancel_allotment_control_block`,不再展示独立 Parent Cancel Booking 卡。
- 任务列表筛选不提供 `linked_parent_release_after_child_split`;新开发阶段只展示 `S10/S99` 筛选,不再展示旧 `S000/S999` 筛选项。
- 任务详情字段控件以 `M002-task-field-control-contract-v1.md` 为准:前端优先消费后端 `fields[]` 中的 `control_type``edit_scope``write_target``options_source``raw_readonly`,旧矩阵开关只作为兼容兜底。
- 任务详情 `fields[]` 由后端按当前任务 active definition 过滤后返回,前端不得自行补齐完整字段矩阵;后端未返回的字段对当前任务视为不展示、不校验、不提交。
- type-known manual review 的 `missing_fields[]` 不应统一渲染为普通文本输入;前端应按 `field_pointer` 匹配 `fields[]`,复用对应字段控件并提交 `review_resolution.field_overrides[]`
- 前端不得自行硬编码 PMS 房型目录、Rate Code 全集、Fix Charge 枚举或 P1/P2 未冻结字段;选项来源未接入时按只读、容错或“目录待接入”处理。
## 12. 后端实施 checkpoint 建议
V3 建议拆成以下 checkpoint避免一次性重构过大
| Checkpoint | 目标 | 说明 |
| --- | --- | --- |
| M002-V3-CP1 | 文档和枚举基线 | 已完成:建立 0711 P0 42 路由枚举 / 稳定配置P0.1 后已调整为 40 路由 |
| M002-V3-CP2 | 入站解析兼容 | 已完成:正式回调支持结构化 S10/S99 和 V3 业务根,保留旧 S000/S999 兼容 |
| M002-V3-CP3 | 路由持久化 | 已完成第一版:已保存 AI 原始三元组、route_code、system_process_category、unhandled_current_intents 和 adapter_contract_error |
| M002-V3-CP4 | 列表 / 详情展示 | 已完成第一版:任务列表、订单任务时间线和任务详情透出 V3 路由字段;任务详情支持 S10/S99 入口通知结构、unhandled intent 展示块和 adapter contract error 展示块 |
| M002-V3-CP5 | 同卡复核解阻 | 已完成第一版:支持 review_status、review_resolution.field_overrides[]、复核场景订单归属确认、JSON Pointer 校验和 READY 流转 |
| M002-V3-CP6 | P0 fixtures 回归 | 已完成第一版:引入 0711 P0 fixtures / validator 作为后端适配测试参考,覆盖 main_outcomes、candidate_gate、manual_review_resolution、source_identity_errors、parent_split_two_children、row_multiple_derived、allotment_scope其中 candidate_gate 是 Main Agent 调 Skill 前契约,后端以 validator 和 fixture reference 固化,不作为任务结果回调直接建任务 |
| M002-V3-CP7 | P0.1 Parent Group 路由修订 | 已完成:将 Parent split 父事件从旧 Cancel Booking 迁移为 Cancel Allotment路由总数 42 → 40并保留旧 payload 只读兼容 |
| M002-V3-CP8 | MCP submit 稳定性 | 已完成 review 修正版MCP `th_hotel_submit_task_results` 支持 V3 业务根、结构化 S10/S99 和 V2 兼容V2 item 已暴露完整 schema 并在提交前校验V3 按 `message_events[]` 顺序把 Agent 内部事件 ID 映射为本系统一基 `source_event_index`,返回 `mapping_diagnostics` 但不污染业务 JSONMCP 层只拦 transport 问题event 业务契约问题继续由业务入站层落 `adapter_contract_error` |
| M002-V3-CP9 | 字段控件契约 V1 | 已完成后端第一版:`fields[]` 返回 `control_type/edit_scope/write_target/options_source/raw_readonly/control_hint`,覆盖 room_items、只读证据、S10/S99 只读卡和 type-known manual review 缺失字段控件;前端后续按契约接入 |
## 13. 明确不做
V3 P0.1 不做以下事项:
- 不做真实 OPERA / OHIP 写入。
- 不做普通任务任意切换订单。
- 不由前端直接调用 SuperAgent、AgentBus、OPERA、OHIP 或数据库。
- 不把 `candidate_events[]` 当成最终任务。
- 不自动根据 `unhandled_current_intents[]` 创建业务任务卡。
- 不用 P1/P2 Known Issues 自行发明字段或 schema。
- 不移除历史 `S000/S999` 数据展示。
- 不让前端绕过后端字段控件契约自行发明 PMS 房型、Rate Code、Fix Charge 或未冻结枚举。
## 14. 当前代码现状提醒
截至 M002 V4 入站解析基线落地后,当前后端已经实现:
- `S000/S999` 文本结果兼容处理。
- 结构化 `S10/S99` 入站处理,复用 `SOURCE_MESSAGE_ONLY` 只读特殊任务。
- V4 包级 `route_code=S10/S99` 已识别M002 V4 CP4 后,新 V4 S10/S99 写入来源通知模型,普通 V4 业务包要求 `route_code=null`
- V4 业务根 `source_message + order_contexts[] + message_events[]` 基础解析;`source_message.source_message_id` 按 SourceMessage Inbox 的 `external_message_id` 反查邮件。
- V4 第一版识别 `NEW_BOOKING``UPDATE_BOOKING``CANCEL_BOOKING``TRACE_RESERVATION_NOTES``ROOMING_LIST``PAYMENT`,可映射 event 先复用现有订单 / 任务 / 任务卡链路,并保存 `catalog_code=M002V4``skill_id=booking-desk-event-v4``field_contract_version=20260718-v4` 和 V4 原始三元组 / 原始 event payload。
- M002 V4 CP4 已补充新模型写入:普通 V4 业务包会额外创建 V4 订单任务、来源邮件展示卡、Basic Information 卡和业务卡;只有契约错误、没有合法业务 event 的包不会创建 V4 订单任务。
- M002 V4 CP4 后V4 `route_code=S10/S99` 写入 `workflow_reservation_v4_source_notification`不再创建隐藏技术订单或旧任务V3 S10/S99 和旧 S000/S999 仍保留历史兼容链路。
- M002 V4 CP5 已开放 V4 查询接口:`GET /api/reservation/workbench-items``GET /api/reservation/order-tasks``GET /api/reservation/order-tasks/{orderTaskId}``GET /api/reservation/source-notifications/{notificationId}`
- V4 包级契约错误在 `source_message.source_message_id` 可定位时只写 `adapter_contract_error` transition不创建订单、任务或用户可处理卡`source_message_id` 缺失或 SourceMessage 不存在时仍返回明确错误。
- V4 `PAYMENT.attachment_ids[]` 必须匹配 `source_message.attachments[].id`V4 `UPDATE_BOOKING` 不接受 `rate_code``after.rate_code`;这类契约错误只落 `adapter_contract_error` transition不创建用户可处理业务任务。
- 40 条 P0.1 路由枚举 / 稳定配置。
- V3 业务根 `source_message + message_events[]` 基础解析;能派生到稳定路由的 event 创建业务任务,无法派生的 event、显式 `contract_errors`、根 `missing_fields`、不完整 `manual_review`、当前 producer 旧 Parent Cancel Booking 和不完整 parent split 候选只落 `adapter_contract_error` transition。
- P0.1 Parent split 已支持单边 Parent key 归一Parent key 候选冲突且符合 `target_object_unclear + parent_identity_candidates[]` 时进入同卡 type-known manual review不再误判为 adapter contract error。
- `unhandled_current_intents[]` 只落 `UNHANDLED_CURRENT_INTENT` transition不创建订单和任务也不伪装成 adapter 契约错误。
- AI transition 最小保存 `route_code``system_process_category``adapter_error_code``adapter_error_message`
- 任务列表、订单任务时间线和任务详情顶层透出 `result_type``ai_task_type``task_subtype``route_code``system_process_category`
- `SOURCE_MESSAGE_ONLY` 任务详情透出 `source_message_only_result.result_type``route_code``agent_assessment``notification``manual_review``raw_answer`
- 业务任务详情按同一 AI 批次透出 `adapter_contract_errors[]``unhandled_intents[]` 只读展示块。
- type-known manual review 创建在原业务任务卡上,任务详情返回 `review_status``review_resolution``manual_review`
- `POST /api/reservation/tasks/{taskId}/manual-review-resolutions` 支持字段修正、当前订单归属确认、JSON Pointer 到可编辑字段校验、READY 流转、confirmed payload 写入、两条 OPERA 模拟操作创建和审计记录。
- `POST /api/reservation/tasks/{taskId}/manual-review-resolutions``field_overrides[]` 已支持 `field_pointer``field_path` 两种定位方式;`field_path` 可为 P0 主路径或旧扁平路径,成功后响应归一化到 P0 主 `field_path`
- 任务详情 `fields[]` 已新增 `control_type``edit_scope``write_target``options_source``raw_readonly``control_hint`,用于前端字段控件和同卡复核输入渲染。
- 任务详情 `fields[]` 已与保存草稿、最终确认和复核解阻使用同一套 active definition 规则;已按 `visible``result_type``task_type``task_subtype``display_condition` 过滤。
- `room_items[0]` 字段第一版已返回 P0 JSON Pointer 和控件契约:房量为 `number`PMS 房型代码为 `select + active_pms_room_type_catalog`,房型原文 `room_type_raw` 作为 raw 证据只读。
- type-known manual review 的缺失字段返回 `edit_scope=manual_review_only``write_target=review_resolution.field_overrides`;只读诊断字段、源邮件通知卡和 route/result/task 字段不返回可编辑控件。
- `CANCEL_ALLOTMENT` 第一版复用字段矩阵中的 `Cancel Booking 卡 / cancel_allotment_control_block` 规则Parent / Allotment 复核中 `/case_keys/block_code``case_keys.group_code` 别名处理,前端只需要提交任务详情 `fields[]` 暴露的 `case_keys.group_code`。后端会派生 `cancel_object_type=allotment_control_block` 并接受 `cancel_scope=entire_allotment_control_block`
- `source_message.source_message_id` 缺失时按 V3 typed `infrastructure_input_error` 结构响应。
- 0711 P0 fixtures 已纳入后端回归测试参考,并补齐 S10/S99 严格契约、P0 type-known manual review 解阻、candidate_gate reference 和当前扁平字段矩阵兼容Parent split 相关用例按 0712 P0.1 增量改为 Cancel Allotment。
- `field_contract_version` 历史迁移已收紧V18 只把没有 `draft_payload_json` 且没有 `confirmed_payload_json``code-v1` 任务卡标记为 `20260711-p0`;已经存在用户草稿或确认 payload 的历史任务卡保留旧版本,等待重新保存、确认或后续专项 backfill。
- 订单 / 任务列表、任务详情、草稿保存、最终确认、OPERA 模拟骨架和审计列表。
- SuperAgent 查询上下文接口 1、2以及邮件会话相关查询。
- MCP `th_hotel_submit_task_results` 的 V3/P0.1 payload adapter 和提交前校验;`E1/E_CHILD_1/E_PARENT` 等 Agent 内部事件 ID 不直接进入业务层,由 MCP adapter 映射为 `1/2/3` 等本系统一基索引,跨 Child Trace / Parent split 多事件关系保留顺序并拒绝悬空或重复引用。
- MCP submit V3 成功响应返回 `mapping_diagnostics.source_event_index_mapping[]`,用于排查 Agent 内部事件 ID 到本系统索引的映射;该诊断不写入 AI transition 业务 payload。
- MCP submit V2 兼容路径已在 `tools/list` 暴露 `ai_task_results[]` item schema并在 adapter 层校验必填字段、字段类型、允许 `result_type` 和未知字段。
- MCP submit 对缺失 `source_message.source_message_id` 或整个 `source_message` 保留业务入站层 `MISSING_SOURCE_MESSAGE_ID` 错误语义;对 V3 event 业务契约问题不提前整批拒绝,由业务入站层保存 `adapter_contract_error` transition。
M002 V4 CP2 设计文档已落地:
- 文档路径:`docs/project/requirements/M002-v4-order-task-card-domain-model-cp2.md`
- 设计内容SourceMessage 邮件展示卡、S10/S99 来源通知、`source_message_id + order_ref` 订单任务、Basic Information 独立卡、每个 V4 event 的业务卡、卡片确认 / 复核 / 锁定、同订单阻塞、表结构草案和后续接口草案。
- 已确认V4 工作台统一列表新开 `/api/reservation/workbench-items`,业务订单任务新开 `/api/reservation/order-tasks/**`S10/S99 来源通知使用 `/api/reservation/source-notifications/**`S10/S99 采用来源通知模型;`FIT + BOOKING_CODE` 不建 ACTIVE 唯一约束匹配多条进人工复核Basic Information 必须先确认其它业务卡第一版不强制逐张确认Account / Market / Source 目录第一版使用后端固定种子数据。
- 当前状态CP3 表结构 / Repository、CP4 入站写入新模型、CP5 查询接口和 CP6 普通卡片确认 / S10/S99 ack 已完成V4 复核接口和前端页面仍未实现。
仍需后续 checkpoint 实现:
- V4 表结构和 Repository 落地已完成第一版:新增 V4 订单任务表、V4 任务卡表和 V4 来源通知表,并提供 Entity、Mapper、Repository、幂等创建、`order_context_index` 稳定排序、非 event 卡 `source_event_index=0` 和 version 乐观锁更新基础方法。
- V4 入站写入新模型已完成第一版:真正创建 SourceMessage 展示卡、Basic Information 卡、业务卡和 S10/S99 来源通知。
- V4 复核解阻、复核场景订单归属确认和前端页面模型切换。
- V4 前端页面模型、任务详情字段矩阵和目录校验完全切换。
- 真实 OPERA / OHIP、普通任务任意切换订单、字段矩阵从当前扁平结构整体迁移到 0711 P0 新结构、历史旧 Parent Cancel Booking payload 批量迁移。