Complete the selective V2 checkpoint with its minimal AgentBus, object-storage, replay persistence, and validated-workbench shared dependency closure.
13 KiB
Booking 邮件处理架构 v0.4
迁移状态(2026-08-13):本版本仅用于旧 V4 读取和迁移回归。它曾配套的 CandidateDecision v1 正式契约 从未上线且已删除。新运行只以 v0.5、 contracts-v2 和 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_materialcurrent 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 4RateRoomResolver;QBD F 列完全忽略,且source_rate_code=NOT_APPLICABLE。
3. 统一状态机
处理运行(processing run)使用以下状态;状态是运行主线,不等同于单张业务卡的用户可见状态:
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-appliedEffectiveFactView后才能进入 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 运行重试与可观测性
FAILEDrun 只能从已保存的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 内部结构作为新模块之间的接口。