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

415 lines
22 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.1 |
| 日期 | 2026-07-11 |
| 状态 | 0711 P0 基线确认版;后端已完成 M002 V3 CP1-CP6 入站、路由持久化、列表 / 详情展示、同卡复核解阻和 P0 fixtures 回归第一版 |
| 适用范围 | 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 冻结基线,以及本项目已经确认的产品决策。后续 M002 新开发应优先按本文执行;当前代码中已经存在的 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 的 42 路由、人工复核、Parent split、fail-closed 规则 |
| `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不作为生产规则源 |
本项目确认的产品决策:
- M002 V3 正式采用 0711 P0 基线。
- 旧数据 `S000/S999` 继续在任务列表可见;新数据迁移为 `S10/S99`
- `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。
- 第一版保存全部 42 条路由 / 枚举,先支持保存和列表展示。
- 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]` 派生 42 条 P0 三元组 |
| 人工复核 | 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_provider + source_channel + source_message.source_message_id
→ platform_source_message_inbox.external_message_id
→ platform_source_message_inbox.id
→ workflow / task / transition 表内部 source_message_id 外键
```
V3 第一版继续使用单酒店阶段的系统默认酒店;后续多酒店或权限收口时再扩展显式酒店上下文。
### 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` 和入口说明。
### 6.3 旧 S000 / S999 兼容
旧数据 `S000/S999` 已经在系统中以只读特殊任务展示。V3 不删除旧数据,也不要求历史回写。
兼容规则:
-`S000` 在前端和查询层按 `S10` 语义展示。
-`S999` 在前端和查询层按 `S99` 语义展示。
- 如果旧任务已经是 `SOURCE_MESSAGE_ONLY` 或等价只读类型,继续在任务列表可见。
- 新入站不再优先使用 `S000/S999` 文本格式;实现迁移前,对外契约应清楚标记当前代码支持范围。
## 7. Adapter 路由模型
### 7.1 42 条 P0 路由
V3 第一版必须保存并支持以下路由类别:
- 19 个业务 subtype每个 subtype 都有 normal 和 type-known manual review 两条路由,共 38 条。
- `S10``S99` 两条源邮件通知路由。
- 类型或 subtype 未知的 Fallback 路由:`manual_review + Fallback + business_event_review`
- `unhandled_current_intent + Unhandled Current Intent + requires_business_approval_or_unsupported_task_card` 展示路由。
第一版后端要求:
- 42 条路由全部进入枚举或稳定配置,不能只硬编码已实现的少数几条。
- 每条入站 event 都按自己的 `message_events[i]` 独立派生,不能在邮件根只生成一个任务。
- 同一封邮件多个任务按 SuperAgent 返回数组顺序和事件顺序生成执行顺序。
- `Note``Allotment Maintenance``update_allotment_control_block` 仅历史兼容,不允许新数据生成。
### 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` 订单。
- `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`,否则返回 `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 原始结构,不回写用户修正。任务详情 `fields[]``field_path``field_pointer` 以 P0 主结构为准,`legacy_field_path` 仅用于前端过渡展示。草稿保存、最终确认和同卡复核解阻可继续提交旧扁平 key但后端会归一化到 P0 主 `field_path`;响应中的 `field_values` 使用主路径,`legacy_field_values` 提供旧扁平回显兼容,`effective_payload` 提供嵌套结构供后续 OPERA 参数组装使用。当前第一版只支持 `room_items[0]`,非 0 下标或不存在路径按 `TASK_REVIEW_POINTER_INVALID` / 字段校验错误处理,不自动映射。
### 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",
"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 参数。
- 自动生成第一版固定两条 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
- 42 路由与 runtime 输出不一致或无法唯一匹配。
- `manual_review` 九字段不完整。
- `missing_fields[]` 不是 RFC 6901 pointer或无法映射到可编辑字段。
- Parent 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 返回时,前端展示稳定错误和源邮件入口,不让用户误以为可以确认执行。
## 12. 后端实施 checkpoint 建议
V3 建议拆成以下 checkpoint避免一次性重构过大
| Checkpoint | 目标 | 说明 |
| --- | --- | --- |
| M002-V3-CP1 | 文档和枚举基线 | 已完成:建立 42 路由枚举 / 稳定配置,作为入站路由唯一代码源 |
| 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 固化,不作为任务结果回调直接建任务 |
## 13. 明确不做
V3 P0 不做以下事项:
- 不做真实 OPERA / OHIP 写入。
- 不做普通任务任意切换订单。
- 不由前端直接调用 SuperAgent、AgentBus、OPERA、OHIP 或数据库。
- 不把 `candidate_events[]` 当成最终任务。
- 不自动根据 `unhandled_current_intents[]` 创建业务任务卡。
- 不用 P1/P2 Known Issues 自行发明字段或 schema。
- 不移除历史 `S000/S999` 数据展示。
## 14. 当前代码现状提醒
截至 M002 V3 CP6 落地后,当前后端已经实现:
- `S000/S999` 文本结果兼容处理。
- 结构化 `S10/S99` 入站处理,复用 `SOURCE_MESSAGE_ONLY` 只读特殊任务。
- 42 条 P0 路由枚举 / 稳定配置。
- V3 业务根 `source_message + message_events[]` 基础解析;能派生到稳定路由的 event 创建业务任务,无法派生的 event、显式 `contract_errors`、根 `missing_fields`、不完整 `manual_review` 和不完整 parent split 候选只落 `adapter_contract_error` transition。
- `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 模拟操作创建和审计记录。
- `source_message.source_message_id` 缺失时按 V3 typed `infrastructure_input_error` 结构响应。
- 0711 P0 fixtures 已纳入后端回归测试参考,并补齐 S10/S99 严格契约、P0 type-known manual review 解阻、candidate_gate reference 和当前扁平字段矩阵兼容。
- 订单 / 任务列表、任务详情、草稿保存、最终确认、OPERA 模拟骨架和审计列表。
- SuperAgent 查询上下文接口 1、2以及邮件会话相关查询。
仍需后续 checkpoint 实现:
- 真实 OPERA / OHIP、普通任务任意切换订单、字段矩阵从当前扁平结构整体迁移到 0711 P0 新结构。