Complete the selective V2 checkpoint with its minimal AgentBus, object-storage, replay persistence, and validated-workbench shared dependency closure.
146 lines
13 KiB
Markdown
146 lines
13 KiB
Markdown
# Booking 邮件处理架构 v0.4
|
||
|
||
> **迁移状态(2026-08-13)**:本版本仅用于旧 V4 读取和迁移回归。它曾配套的 CandidateDecision v1 正式契约
|
||
> 从未上线且已删除。新运行只以 [v0.5](booking-email-architecture-v0.5.md)、
|
||
> [contracts-v2](booking-email-contracts-v2.md) 和 ADR-012 为准;不得依据本文件产生新业务结果。
|
||
|
||
| 项目 | 内容 |
|
||
| --- | --- |
|
||
| 文档状态 | 历史读取兼容;新写入已由 v0.5 取代 |
|
||
| 架构版本 | `booking-architecture-v0.4` |
|
||
| 契约版本 | `booking-contracts-v1` |
|
||
| 业务基线 | `BR00-BASELINE-1` |
|
||
| 范围终点 | 用户确认;不调用 PMS、Opera、付款或部门流转 |
|
||
|
||
## 1. 目的与替代关系
|
||
|
||
本架构把邮件获取、附件识别、固定渠道确定性解析、历史上下文、Booking Agent、校验和人工确认收敛为一条可追溯主线。它替代以附件 Parser 或旧 V4 入站模型为中心的实施方式。
|
||
|
||
早期 `architecture-v0.3`、M002 叙述和 M012 V0.1 实现记录只可用于迁移和回归,不能作为新功能实施依据。
|
||
新增实现必须使用 v0.5 与 contracts-v2;本文件不再指向或定义旧 CandidateDecision 契约。
|
||
|
||
## 2. 七层职责与边界
|
||
|
||
| 层 | 负责什么 | 输入 | 输出 | 不负责什么 |
|
||
| --- | --- | --- | --- | --- |
|
||
| 1. 信息系统接入与编排 | 接收 AgentBus 邮件或手工 EML,建立幂等、处理批次与状态查询 | AgentBus payload / `.eml` | `SourceMessageEnvelope` | 不理解业务、不直接建最终任务 |
|
||
| 2. 材料预处理 | 分离 current/quoted history,列举附件、图片、工作簿结构和候选材料,保留证据引用 | `SourceMessageEnvelope` | `MaterialPackage` | 不把历史内容重复当作本次动作 |
|
||
| 3. 确定性 Parser + 字段恢复与本地组装 | 对适用固定渠道生成不可变来源观察与 AFTER/CURRENT facts;只将 `UNRESOLVED+RECOVERABLE` 字段送字段解析兜底 Agent,再由本地校验、依赖重算与投影形成统一有效事实视图 | `MaterialPackage` | `ParsedFactSet`(含 `ParserObservationSet`)+ `EffectiveFactView` | 不做 Rate/Room 目录映射,不让 Agent 重写整行,不做最终业务决定 |
|
||
| 4. Context Assembler + RateRoomResolver | 按 Group Code、订单线索或会话定向读取当前态;并将 Layer 3 `source_room_type/source_price` 与版本化 Rate/Room 目录确定性解析 | `EffectiveFactView` + 来源/历史线索 + Rate/Room 目录 | `ContextPackage`(含 `rate_room_resolutions`) | 不扫描全库、不让历史邮件重新触发动作、不回写 Layer 3 来源事实 |
|
||
| 5. 业务识别 / Booking Agent | 合并 Layer 3 有效事实和 Context,形成候选业务决定;Parser 失败/不适用/歧义时使用受控最小 ParsedFactSet 分支 | 固定渠道:`EffectiveFactView + ContextPackage`;其他分支:最小 `ParsedFactSet + ContextPackage` | `CandidateDecision` | 不下载附件、不直接读写数据库、不建最终任务、不调用 PMS |
|
||
| 6. Validator 与人工确认准备 | 校验 schema、Catalog、证据、目标、生命周期、前置关系和确认必填项 | `CandidateDecision` | `ValidationResult`、`ConfirmationProjection` | 不绕过校验建卡、不执行外部业务动作 |
|
||
| 7. 用户确认 | 展示安全的关键参数、证据、阻断、可编辑字段和链接动作;冻结已确认参数与审计 | `ConfirmationProjection` | `CONFIRMED` 记录 | 不调用 PMS/Opera,不改变付款或部门状态 |
|
||
|
||
### 2.1 信息系统与 Agent 的职责分界
|
||
|
||
- **信息系统**拥有 SourceMessage、幂等、附件/证据存储、确定性 Parser、本地 Recovery 校验/组装、RateRoomResolver、Context 查询、Validator、数据库事务、确认 API 和审计。
|
||
- **AgentBus**既是邮件消息入口适配器,也是 Booking Agent 的承载平台;它不成为业务事实源。
|
||
- **Booking Agent**对固定渠道只消费最小化的 `EffectiveFactView + ContextPackage`;Parser 不适用等分支可消费最小 `ParsedFactSet + ContextPackage`,其中唯一的正文材料是 policy 脱敏、限长的 `agent_input_material` current excerpt。它不能自行扩大材料范围、下载附件、调用 PMS 或写任务表。
|
||
- Rate/Room 目录从 Layer 4 开始使用独立 `catalog_version`;Layer 3 只记录 Parser normalization catalog/version,不消费 207 行目录,也不生成 canonical Room Type 或最终 Rate Code。Booking Agent 只消费 Layer 4 的受控解析结果,不能自行重做目录映射。
|
||
- `Name of Group`、`Group Name`、`Tour Code`、`Group Code` 是固定渠道对同一团号的不同列名;第 3 层统一写入 `group_code`,第 4 层也只以该统一值定向查询,不能把列名差异制造成多目标。
|
||
|
||
### 2.2 Layer 3 固定渠道内部链路
|
||
|
||
Layer 3 固定为:`Deterministic Parser → ParserObservationSet + AFTER/CURRENT facts → RecoveryRequestBuilder → 字段解析兜底 Agent → RecoveryPatchSet → 本地 RecoveryPatchValidator / dependency resolver / projector → EffectiveFactView`。详细字段身份、状态、patch 校验和 overlay 规则只在唯一共用协调契约 `../../../../.planning/booking_completion_roadmap/fixed_channel_parser_recovery_contract_v2_discussion_draft.md` 维护;本文只冻结层间边界,不复制第二套格式。
|
||
|
||
- `parser_observations` 是不可变来源观察,保存 BEFORE/AFTER/CURRENT、raw/normalized value、稳定 row/segment/room/field/evidence 身份及未解决原因;原 Parser facts 不被 Agent 改写。
|
||
- `facts[]` 只承载 Parser 首次确定的 AFTER/CURRENT 当前事实;BEFORE 只用于展示和审计。
|
||
- Recovery 只允许处理持久 `UNRESOLVED+RECOVERABLE` 的稳定 `field_id`,Agent 只能返回候选 PatchSet;冲突、结构问题、业务合并和校验失败保持人工复核。
|
||
- accepted patch 先经过本地校验和同版依赖重算,再使用与 Parser 相同的 current-fact projector 形成 `EffectiveFactView`;没有恢复任务时也建立同格式 baseline view。
|
||
- Layer 3 房型名固定为 `source_room_type`。`room_type_code` 和最终 Rate Code 只属于 Layer 4 `RateRoomResolver`;QBD F 列完全忽略,且 `source_rate_code=NOT_APPLICABLE`。
|
||
|
||
## 3. 统一状态机
|
||
|
||
处理运行(processing run)使用以下状态;状态是运行主线,不等同于单张业务卡的用户可见状态:
|
||
|
||
```text
|
||
RECEIVED
|
||
→ MATERIAL_READY
|
||
→ PARSER_COMPLETE | PARSER_NOT_APPLICABLE | PARSER_FAILED
|
||
→ CONTEXT_READY
|
||
→ AGENT_COMPLETE(仅在需要 Agent 时)
|
||
→ VALIDATED
|
||
→ AWAITING_CONFIRMATION
|
||
→ CONFIRMED
|
||
```
|
||
|
||
- `PARSER_FAILED`、`PARSER_NOT_APPLICABLE` 不代表整封邮件失败;它们是允许进入 Context 和按需 Agent 的受控分支。
|
||
- 对适用固定渠道,`PARSER_COMPLETE` 的 Layer 3 artifact 必须进一步形成 baseline 或 recovery-applied `EffectiveFactView` 后才能进入 Layer 4;字段恢复子步骤不新增一套跨层事实格式。
|
||
- Validator 可以把受影响目标隔离为 Risk,但同封其他清晰目标继续到确认准备。
|
||
- 任何阶段发生可重试技术错误时记录 run attempt、错误代码和安全摘要,不伪造业务完成。
|
||
- `CONFIRMED` 是本期终点。PMS/Opera 适配器必须是后续独立状态机,不得从本状态机隐式触发。
|
||
|
||
## 4. 处理结果与隔离规则
|
||
|
||
每封邮件及每个候选目标都使用以下稳定结果类型:
|
||
|
||
| 结果 | 适用条件 | 后续行为 |
|
||
| --- | --- | --- |
|
||
| `IN_SCOPE_TASKS` | 当前邮件存在可识别的 Booking 业务目标 | 形成候选卡,经过 Validator 后进入确认 |
|
||
| `GENERAL_NOTIFICATION` | 整封 current 邮件确定没有任何支持的业务任务 | 最多一条 General 通知 |
|
||
| `RISK_NOTIFICATION` | 业务类型、目标、材料或 Parser 结果存在无法安全消解的歧义 | 每封最多一张 Risk;隔离不明确部分 |
|
||
| `IGNORED_DIRECTION` | 确定为酒店外发、内部邮件或不属于本系统处理范围 | 不创建待办任务,保留安全处理记录 |
|
||
|
||
补充规则:
|
||
|
||
- 已知业务类型但字段缺失,保留原业务类型并标记 `REVIEW_REQUIRED`,不能降格成 General 或 Risk。
|
||
- 同封邮件存在清晰任务和不清晰片段时,清晰任务继续,Risk 只承载不清晰片段。
|
||
- 重复投递、真实新邮件、revision、历史底色遗留和业务内容相同是不同判断维度;由 Validator 结合证据、消息幂等键和生命周期处理。
|
||
|
||
## 5. 固定渠道材料与 Parser 边界
|
||
|
||
### 5.1 预处理为何独立
|
||
|
||
Excel、图片和正文的原始材料体积大、结构多变且含历史内容。预处理把“能安全给 Parser/Agent 的本次材料”缩小为可定位、可审计的引用集合,因此 Agent 不必读取整张工作簿或整段会话。
|
||
|
||
- current body 和 quoted history 必须分开;quoted history 只能辅助理解、继承身份或提示重复,不可再次触发动作。
|
||
- Excel 附件保留工作簿/Sheet/行/列/底色/哈希等证据;普通任务 API 不返回整行原文。
|
||
- 图片作为 `IMAGE` 材料进入预处理。它可辅助判断 Trace、Payment/Voucher 或不在范围,但不因“有图片”自动创建业务卡。
|
||
- 无附件邮件仍经过第 1 层接入和第 4 层 Context;仅跳过 Excel 专用预处理与 Parser。
|
||
- 对 Parser fallback,信息系统可从 current subject/body 生成受控 Agent excerpt,并提取唯一明确的 Group Code 或 old→new relation 供 Context 定向查询;这不是把全文、quoted history 或附件重新交给 Agent。
|
||
- 字段解析兜底 Agent 与 Layer 5 Booking Agent 是两个不同职责:前者只收到稳定 `field_id` 及同 row/segment/room item 的最小只读上下文,不能读取或重写整份附件;后者只在 Layer 4 之后形成业务候选决定。
|
||
|
||
### 5.2 严格底色与 Profile
|
||
|
||
- 固定渠道 Profile 必须同时满足文件信号、明确业务 Sheet 规则和表头签名;平分、未知或非法 Sheet 均停止确定性解析,进入 Risk/fallback。
|
||
- `STRICT_CURRENT_CANDIDATE` 必须在 Catalog 定义的业务范围内整行非白底。字体颜色、批注、条件格式推测和白底不计入。
|
||
- anchor 行提供身份/明细列;合法 continuation 行仅补动作/状态列。任意多行互补都不能升级为确定事实。
|
||
- 未知房量保持 `booking_type=null/UNRESOLVED`,不能按 0 推断 FIT;Trace 部门只有邮件证据唯一明确时预填,否则由用户选择 FO、HSK 或二者。
|
||
|
||
### 5.3 改团号与 Trace 生命周期
|
||
|
||
- old→new 团号只在 current body 明确标注后进入 `GROUP_CODE_REPLACEMENT`;Context 只读 old/new 两个 Group Code,old 有效且 new 不存在才允许 Update 继续。两个普通团号、历史引用或多条矛盾关系均进入复核。
|
||
- 同团同封的 standalone Trace 在信息系统内合并为一张候选卡,保留每条服务项和证据;跨封 Trace 绝不并入旧卡,Context 只以无自由文本的时间序摘要提供历史顺序。
|
||
- Trace 的最终确认至少选择 `FO` 或 `HSK`,可同时选择二者;本期确认不触发部门流转。
|
||
|
||
### 5.4 运行重试与可观测性
|
||
|
||
- `FAILED` run 只能从已保存的 `PARSED_FACT_SET`、`CONTEXT_PACKAGE`、`MATERIAL_PACKAGE` 重放;不会重新拉取邮件、附件或历史,也不会创建新的 source revision。重试在 worker 中继续,processing attempt 与 `retry_count` 形成可审计的尝试链。
|
||
- `FAILED` 之外的状态拒绝重试;旧的确认投影在重试期间不返回,避免用户确认过期候选。
|
||
- 管理员只读指标固定统计最近 24 小时:失败率、Agent fallback 比率、Risk 比率、活跃积压、已重试 run 与 retry attempt。指标只来自 `th_hotel_booking` 聚合,不含个人数据、邮件内容、附件、团号或跨库查询。
|
||
- 任何监控、重试或 retention 任务都以用户确认前为终点,不能触发 PMS/Opera、付款、库存扣减或部门流转。
|
||
|
||
## 6. 数据与事实源
|
||
|
||
- 新 Booking 主线的事实源是 PostgreSQL schema `th_hotel_booking`。处理运行、版本化契约、证据引用、候选、校验和确认投影均落入该 schema。
|
||
- 旧 MySQL V4 数据仅作历史兼容读取;禁止未定义双写、跨库事务或把 MySQL 记录当作新主线事实源。
|
||
- 每次读取 Context 必须按 Group Code、订单线索或已知 SourceMessage 定向查询;无目标线索时不能扫描全库找“最像”的订单。
|
||
- 主数据(渠道白名单、sender → Account/Market/Source、Rate/Room 目录映射)也是版本化事实。目录映射由 Layer 4 `RateRoomResolver` 执行;零候选、多候选和未配置均保留待用户补充,不能让 Parser 或 Recovery Agent 猜测。
|
||
|
||
## 7. 接口与并行工作边界
|
||
|
||
后续实现可以并行,但只能依赖 contracts-v1:
|
||
|
||
- Track A:`BookingMessageOrchestrator` 和入口适配器。
|
||
- Track B:Booking Agent profile、prompt、skill/reference 与离线 contract tests。
|
||
- Track C:Context/lifecycle assembler。
|
||
- Track D:PostgreSQL repository、Flyway、主数据与 processing run。
|
||
|
||
四条线不能直接依赖对方内部 Entity、Parser 私有 record 或 AgentBus payload。共享只通过 contracts-v1 的版本化数据结构、错误码和 evidence reference。
|
||
|
||
## 8. 实施前置与验收
|
||
|
||
G1 通过条件:信息系统、Agent、Context、数据库、Validator、前端和 QA 能在不引用旧 architecture-v0.3 的前提下,只基于 contracts-v1 明确输入、输出、版本字段、状态机、结果类型和失败边界后开始实现。
|
||
|
||
与现有 V0.1 的关系:V0.1 保留为受控纵向切片和回归基线;在 contracts-v1 适配完成前,不以其旧 V4 内部结构作为新模块之间的接口。
|