docs(booking): freeze v0.4 contracts and verification path

This commit is contained in:
鲨鱼辣椒
2026-08-08 16:03:35 +08:00
parent fcf9127ff0
commit c826b6e574
10 changed files with 526 additions and 18 deletions

View File

@@ -0,0 +1,71 @@
name: verify
on:
push:
pull_request:
jobs:
booking-verify:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: booking_ci
POSTGRES_USER: booking_ci
POSTGRES_PASSWORD: booking_ci
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U booking_ci -d booking_ci"
--health-interval 5s
--health-timeout 5s
--health-retries 20
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
cache: maven
- name: Set up Node 24
uses: actions/setup-node@v4
with:
node-version: '24.14.0'
cache: pnpm
cache-dependency-path: client/pnpm-lock.yaml
- name: Enable pinned pnpm
run: |
corepack enable
corepack install
- name: Backend verify
working-directory: server
run: ./mvnw -B verify
- name: Frontend install and quality gates
working-directory: client
run: |
pnpm install --frozen-lockfile
pnpm typecheck
pnpm lint
pnpm test
pnpm build
pnpm audit --prod
- name: Source secret scan
run: bash scripts/verify-no-secrets.sh
- name: Install PostgreSQL client
run: |
sudo apt-get update
sudo apt-get install --yes postgresql-client
- name: Verify Booking PostgreSQL migration boundary
env:
BOOKING_PG_VERIFY_URL: postgresql://booking_ci:booking_ci@localhost:5432/booking_ci
run: bash scripts/verify-booking-postgresql-migration.sh

View File

@@ -36,7 +36,7 @@ TH Hotel Simple 是一个前后端分离的酒店业务协同项目。
- PrimeVue 4、PrimeIcons 7。
- Vue Router 5、Vue I18n 11。
- Vitest 4、ESLint 10、vue-tsc 3。
- Node.js >= 22.13.0
- Node.js 24.x 与 pnpm 11.x项目文件 `client/.node-version``client/package.json` 固定验证基线)
## 4. 当前业务领域
@@ -44,7 +44,8 @@ TH Hotel Simple 是一个前后端分离的酒店业务协同项目。
- Email / Message Conversation邮件和邮件会话用于历史邮件查询、正文读取和会话级任务查询。
- Reservation Case / Task预订相关订单、任务卡、人工复核和任务结果。
- Reservation Order Task / CardM002 V4 后续采用的订单任务与多卡模型;一封来源邮件可按 `order_ref` 形成多个订单任务每个订单任务下包含来源邮件展示卡、Basic Information 卡和若干业务卡。
- Room Information CardV4 订单任务中由 New Booking、Update Booking 或 Cancel Booking 触发的房型信息卡;它展示订单房型、日期、早餐、晚数和 Group 状态等可确认业务信息
- Booking Email IntakeM012 普通员工预订邮件入口;可上传 `.eml`,按版本化 Catalog 和固定渠道严格底色 Parser 形成 V4 订单任务/来源通知,随后由用户复核和确认。手工导入无确定事实时当前生成 S10/S99不在请求内自动调用外部 Agent
- Room Information CardV4 可定位订单任务的房型与日期区块New / Update / Cancel 直接生成生命周期 Room只有 Trace / Rooming List / Payment 的订单任务补一张共享 current-only companion Room因此六类订单事件均具备 Basic + Room。
- Review Required CardV4 订单任务中需要人工复核的原业务卡状态;用户仍在原卡片内检查和修正业务字段,完成后确认卡片,不另建独立复核任务卡。
- Reservation Account预订业务中的公司、旅行社或客户账户不是系统登录账号它用于订单级 Basic Information并派生 Market / Source。
- Room Type Catalog预订业务可选房型代码目录第一阶段已确认稳定业务集合为 `RM2``RM3``RM4``SU1``SU2``SU3`,暂不按 Account 限制可用房型。
@@ -66,6 +67,7 @@ TH Hotel Simple 是一个前后端分离的酒店业务协同项目。
| SuperAgent MCP | SuperAgent 调用本项目能力的 MCP 映射,当前内嵌在后端服务。 | `docs/project/integrations/superagent-mcp/README.md` |
| Aliyun OSS | 调试 EML、附件或生成文件的对象存储。 | 相关配置和安全边界见项目文档与后端配置 |
| OHIP / PMS | 后续酒店系统集成方向。当前不允许前端直接访问。 | 后续 Spec / ADR 明确 |
| PostgreSQL 测试目标模型 | M012 已在测试库隔离创建 `th_hotel_booking`;当前 Spring 运行时仍保持 MySQL/H2PostgreSQL 方言接入另行设计。 | `database/postgresql/README.md` |
## 6. 当前开发方向
@@ -80,6 +82,8 @@ TH Hotel Simple 是一个前后端分离的酒店业务协同项目。
业务开发仍以 `docs/project/requirements/``docs/project/integrations/` 下的当前有效文档为准。
预订邮件识别到人工确认的当前基线见 `docs/project/requirements/M012-booking-email-confirmation-e2e-v01.md`;确认后的 PMS/Opera 执行不在该版本范围。
新增重要 V4 需求时,应先按项目级 Overlay 形成或更新模板化 Spec / Change Request再安排后端、前端或测试 agent 开工;现有 M002 V4 大文档继续作为字段、接口、安全和实现契约。
## 7. 新 Agent 阅读顺序

File diff suppressed because one or more lines are too long

View File

@@ -39,6 +39,8 @@ docs/
## 后端命令
本 checkpoint 固定本地验证基线为 JDK 17`server/.java-version`)。
```bash
cd server
./mvnw test
@@ -54,6 +56,8 @@ cd server
## 前端命令
本 checkpoint 固定本地验证基线为 Node 24 与 pnpm 11`client/.node-version``client/package.json`)。
```bash
cd client
pnpm install
@@ -73,6 +77,18 @@ pnpm build
- `pnpm lint`:运行 ESLint 检查。
- `pnpm build`:执行类型检查并构建生产产物。
### 本地安全运行与 BR00 原型
后端默认启用 `local` profile只使用进程内 H2本地启动不会连接远程数据库、AgentBus 或 SuperAgent。需要连接开发环境时必须显式启用 `dev` profile并由部署环境提供 `TH_HOTEL_DEV_DB_URL``TH_HOTEL_DEV_DB_USERNAME``TH_HOTEL_DEV_DB_PASSWORD` 三个环境变量;任一缺失会在启动阶段失败。
正式根路由 `http://127.0.0.1:5174/` 是登录/工作台入口不再承载原型。BR00 原型仅用于开发态人工演示,必须显式开启:
```bash
VITE_ENABLE_BR00_PROTOTYPE=true pnpm --dir client dev
```
开启后访问 `http://127.0.0.1:5174/prototype/br00`;任务详情位于 `/prototype/br00/tasks/:taskKey`。原型数据均为虚构内容,只使用 localStorage不连接正式 API也不会写入 Opera / PMS。生产构建不会注册这些路由。
本地联调指定后端示例:
```bash

View File

@@ -28,6 +28,7 @@
| `frontend-development-guidelines.md` | 当前有效 | 当前项目前端专属规范。 |
| `frontend-backend/README.md` | 当前有效 | 前后端协作入口,记录接口契约来源、字段白名单和当前后置事项。 |
| `go-live-notes.md` | 当前有效 | 当前项目上线注意事项记录上线前检查、环境变量、安全、AgentBus、验证和回滚。 |
| `operations/booking-v01-security-checkpoint.md` | 当前有效 | Booking V0.1 的凭据、默认本地 H2、BR00 原型隔离和 G0 外部前置记录;历史数据库凭据必须轮换,未完成前不得标记 G0 通过。 |
## AI-NSES 与可复用规范
@@ -44,10 +45,10 @@
| `requirements/M001-source-message-inbox-prd.md` | 当前有效 | M001 邮件来源入口 PRD记录 AgentBus 邮件 JSON 入库、历史查询、原文读取和媒体引用边界。 |
| `requirements/M002-order-task-workflow-v1.md` | 历史参考 | M002 订单任务主流程 V1已由 V2 承接,保留用于理解早期流程。 |
| `requirements/M002-order-task-workflow-v2.md` | 阶段记录 | M002 订单任务主流程 V2记录当前已阶段实现的 AI 过渡层、S000/S999 兼容、订单任务流转、任务确认和 OPERA 模拟骨架。 |
| `requirements/M002-order-task-workflow-v3.md` | 当前有效 | M002 订单任务主流程 V3,基于 2026-07-11 P0 冻结基线和 2026-07-12 P0.1 Parent Group 修订,记录 S10/S99、40 路由、方案 C、type-known manual review 同卡解阻和 fail-closed 边界。 |
| `requirements/M002-order-task-workflow-v3.md` | 历史参考 | M002 订单任务主流程 V3;保留用于旧 V4 兼容、迁移和回归,新 Booking 邮件主线不再以此作为实施依据。 |
| `requirements/M002-task-field-control-contract-v1.md` | 当前有效 | M002 任务卡字段控件契约 V1记录任务详情 `fields[]` 控件元数据、人工复核控件复用和前后端开发边界。 |
| `requirements/M002-v4-agent-callback-field-contract.md` | 当前有效 | M002 V4 Agent 回调字段契约,基于 2026-07-18 业务基线和最新答复,冻结 `source_message``order_contexts``message_events`、订单级 Basic Information、六类 Event、S10/S99 和校验口径;后端已完成 V4 入站解析、持久化、查询、确认、复核和当前酒店数据库目录校验。 |
| `requirements/M002-v4-order-task-card-domain-model-cp2.md` | 当前有效 | M002 V4 CP2 订单任务与多卡领域模型设计,并记录 CP3-CP8 表结构、入站写入、查询、确认、复核和目录校验已落地状态CP11 已完成 DB 目录与 lookup APICP12 已完成前端 lookup 接入CP13 已完成目录管理后台 CP1CP14 已完成订单列表 V4 继续处理入口CP15 已完成 V4 业务审计查询CP15.1 已完成订单详情 V4 总览后端补齐,当前已停止 V4 普通业务双写旧 `workflow_reservation_task`,并已完成 Room Information 后端展示模型和前端业务化展示第一版,以及 Rooming List 确认自动 DEF 后端联动;已补 OWNER RATE Room Type / Rate Code 目录口径、Payment 附件预览、Rooming List 事项确认卡、V4 复核态卡片交互、可编辑字段白名单和 V4 工作台 / 订单详情 / 任务详情普通酒店员工用户化展示契约;开发阶段不维护 V2/V3 旧任务兼容,测试数据可重建,生产迁移策略后置。 |
| `requirements/M002-v4-agent-callback-field-contract.md` | 阶段记录 | 旧 M002 V4 Agent 回调字段契约;只用于既有 V4 兼容、迁移和回归,新的 Booking 邮件跨层接口以 contracts-v1 为准。 |
| `requirements/M002-v4-order-task-card-domain-model-cp2.md` | 阶段记录 | M002 V4 订单任务与多卡领域模型;保留现有页面/数据兼容资料,新 Booking 主线不再把它作为跨层实现契约。 |
| `requirements/M002-v4-requirement-spec-template-alignment.md` | 当前有效 | M002 V4 近期增量需求的模板化 Spec 入口,汇总 Room Information 多房型、Payment、Rooming List、Trace、REVIEW_REQUIRED、SourceMessage Display、普通员工用户化展示和单卡可操作态测试数据的需求追踪表不替代字段契约、接口契约或安全边界。 |
| `requirements/M002-v4-real-catalog-lookup-api-design.md` | 当前有效 | M002 V4 真实目录与 Lookup API 设计及 CP11 / CP13 CP1 实现记录,记录 Account、Market、Source、Room Type、Rate Code 从固定种子导入数据库、前端 lookup API、目录管理后端接口、权限、缓存后置、PMS / OPERA / OHIP 同步后置和失败兜底;已记录 OWNER RATE `RATECODE (2)` 只读整理结论Room Type 第一阶段收敛为 `RM2``RM3``RM4``SU1``SU2``SU3`Rate Code 第一阶段暂不建立 Account 适用关系Q.B.D / LIAN TAI 清单作为酒店级目录候选。 |
| `requirements/M002-v4-test-machine-smoke-checklist.md` | 当前有效 | M002 V4 测试机冒烟清单覆盖登录、酒店权限、V4 工作台、订单任务详情、lookup、确认、复核解阻、S10/S99 ack、订单详情 V4 时间线和目录管理 CP1 排查点。 |
@@ -64,6 +65,10 @@
| `requirements/M009-manual-invoice-generation-v1.md` | 当前有效 | M009 Manual Invoice 手工开票生成方案;后端 CP2 已支持无订单 / 无任务手工填写、填充 Excel 模板、转 PDF、OSS 输出和生成记录。 |
| `requirements/M010-rooming-list-excel-generation-v1.md` | 当前有效 | M010 Rooming List Excel 生成方案;后端 CP1 已支持前端上传来源名单和手工字段,同步生成 `.xlsx` 直接下载,不落库、不上传 OSSCP2 已实现来源 `旅游日期` 派生 Arrival / Departure、Adults 系统计算,以及目标默认值区域只保留 Payment Type / NationalityCP3 已实现第二种 `英文姓` + `英文名` 名单样式CP4 已实现第三种单列 `英文名` 名单样式;无旅游日期来源样式由用户补充 Arrival / Departure。 |
| `requirements/M011-booking-excel-pre-superagent-enrichment-v1.md` | 当前有效 | M011 Booking Excel 附件预处理方案CP1/CP2/CP3 已支持 Debug EML 和 AgentBus dispatch 调 SuperAgent 前排除人员名单类 Excel、抽取 Booking / 附加费类 Excel 高亮行并追加 `attachment_extractions[]`;测试机 AgentBus 增强已开启生产默认关闭CP4 暂不推进。 |
| `requirements/M012-booking-email-confirmation-e2e-v01.md` | 阶段记录V0.1 已验收 | M012 以 BR00-BASELINE-1 为业务基线,记录普通员工 EML 导入、固定渠道严格底色 Parser、V4 建卡与人工确认、可点击前端、真实样本验收,以及隔离 PostgreSQL `th_hotel_booking` schema 的实现与边界;新实现的跨层边界以 architecture-v0.4/contracts-v1 为准。 |
| `requirements/booking-email-architecture-v0.4.md` | 当前有效 | Booking 邮件七层架构、信息系统/Agent 边界、状态机、结果类型、PostgreSQL 事实源与并行实施边界。 |
| `requirements/booking-email-contracts-v1.md` | 权威契约 | `SourceMessageEnvelope``MaterialPackage``ParsedFactSet``ContextPackage``CandidateDecision``ValidationResult``ConfirmationProjection` 及版本、证据、状态与 API 约束。 |
| `requirements/booking-email-br00-contract-acceptance-matrix-v1.md` | 当前有效 | BR00 业务类型、目标拆分、Context、校验/确认阻断与纵向切片验收矩阵。 |
## 集成契约
@@ -102,7 +107,7 @@
- SuperAgent MCP 文档以 `integrations/superagent-mcp/` 为对外交付资料包,但字段语义应跟随 HTTP 总契约。
- 接口暴露、权限、酒店隔离和审计边界以 `security-access-control-boundary.md` 为总检查清单;具体 SuperAgent / MCP / AgentBus 请求响应契约仍以 `integrations/` 下对应文档为准。
- AI-NSES 的通用标准以 `../import/reusable/ai-native-software-engineering-standard.md` 为复用来源;本项目采用方式以 `ai-native-adoption.md` 为准V4 需求门禁、核心概念守门、需求追踪和 agent 交接规则以 `ai-nses-project-overlay.md` 为本项目补充。
- M002 V1 只作为历史参考V2 记录当前阶段实现;后续 M002 新开发以 `requirements/M002-order-task-workflow-v3.md` 为开发基线。
- 2026-07-18 导入的业务基线已形成 `requirements/M002-v4-agent-callback-field-contract.md` 字段契约M002 V4 入站解析 CP1 已落地V4 订单任务 + 多卡领域模型设计和关键业务决策见 `requirements/M002-v4-order-task-card-domain-model-cp2.md`;近期 V4 增量需求的模板化入口和追踪表见 `requirements/M002-v4-requirement-spec-template-alignment.md`M002 V4 CP3 已落地 V4 订单任务、任务卡、来源通知表结构和 Repository 基线CP4 已落地普通 V4 业务包和 S10/S99 来源通知入站写入新模型CP5 已落地工作台、订单任务和来源通知查询接口CP6/CP7 已落地卡片确认、S10/S99 ack 和复核解阻CP11 已落地 DB 目录与 lookup APICP12 已落地前端 lookup 接入CP13 已落地目录管理后台 CP1CP14 已落地订单列表 V4 继续处理入口CP15 已落地 V4 业务审计查询CP15.1 已落地订单详情 V4 总览后端补齐且前端已接入Room Information 后端展示模型第一版、前端业务化展示和 Rooming List 确认自动 DEF 后端联动已落地;已确认 Rooming List 卡第一版只做事项确认,`REVIEW_REQUIRED` 保持原业务卡内编辑并统一显示“确认卡片”OWNER RATE Room Type / Rate Code 目录导入口径已落地V4 工作台 / 订单详情 / 任务详情页默认面向普通酒店员工,技术信息只允许放在高级筛选、折叠区或受控调试模式;真实 PMS / OPERA / OHIP 同步仍后置。
- M002 V1/V2/V3 与旧 V4 文档只作为历史参考或阶段记录;新的 Booking 邮件主线以 `requirements/booking-email-architecture-v0.4.md``requirements/booking-email-contracts-v1.md` 和 BR00 验收矩阵为开发基线。
- 2026-07-18 导入的业务基线已形成 `requirements/M002-v4-agent-callback-field-contract.md` 字段契约M002 V4 入站解析 CP1 已落地V4 订单任务 + 多卡领域模型设计和关键业务决策见 `requirements/M002-v4-order-task-card-domain-model-cp2.md`;近期 V4 增量需求的模板化入口和追踪表见 `requirements/M002-v4-requirement-spec-template-alignment.md`M002 V4 CP3 已落地 V4 订单任务、任务卡、来源通知表结构和 Repository 基线CP4 已落地普通 V4 业务包和 S10/S99 来源通知入站写入新模型CP5 已落地工作台、订单任务和来源通知查询接口CP6/CP7 已落地卡片确认、S10/S99 ack 和复核解阻CP11 已落地 DB 目录与 lookup APICP12 已落地前端 lookup 接入CP13 已落地目录管理后台 CP1CP14 已落地订单列表 V4 继续处理入口CP15 已落地 V4 业务审计查询CP15.1 已落地订单详情 V4 总览后端补齐且前端已接入Room Information 后端展示模型第一版、前端业务化展示和 Rooming List 确认无跨卡副作用已落地;已确认 Rooming List 卡第一版只做事项确认,`REVIEW_REQUIRED` 保持原业务卡内编辑并统一显示“确认卡片”OWNER RATE Room Type / Rate Code 目录导入口径已落地V4 工作台 / 订单详情 / 任务详情页默认面向普通酒店员工,技术信息只允许放在高级筛选、折叠区或受控调试模式;真实 PMS / OPERA / OHIP 同步仍后置。
- V3 / 旧任务前端展示和编辑字段仍以 2026-07-11 P0 冻结基线中的前端字段表、0712 字段控件说明和 `requirements/M002-task-field-control-contract-v1.md` 为白名单和控件契约基线V4 订单任务前端展示和编辑字段以 `requirements/M002-v4-order-task-card-domain-model-cp2.md`、后端返回的 `fields[]` 和 V4 前后端协作文档为准。
- 时间点语义以 `backend-time-design.md` 为准;数据库时间点按 UTC 理解API 返回带 `Z` 的 UTC 时间,页面再按酒店或用户时区展示。

View File

@@ -154,7 +154,7 @@ M002 V4 已有大量规则落在当前有效大文档中。短期不做大搬迁
- Room Information 多房型、展示模型、Nights / Breakfast / Group Booking Status 和复核白名单。
- Payment 附件安全摘要和前端预览。
- Rooming List 轻量事项卡确认自动 DEF
- Rooming List 轻量事项卡确认无跨卡副作用)
- Trace 普通事项和 EXTRA_BED 字段契约。
- V4 工作台、订单详情和订单事项办理页普通酒店员工用户化展示。
- 单卡可操作态测试数据和 smoke 追踪表。

View File

@@ -0,0 +1,54 @@
# Booking Agent Profile v1
> 状态contracts-v1 的 AgentBus / SuperAgent 配置说明。Agent profile 本身部署在 AgentBus本仓库只保留受控调用端口和验收边界。
## 输入边界
Booking Agent 只接收一个 JSON 对象:
```json
{
"parsed_fact_set": { "...": "contracts-v1 ParsedFactSet" },
"context_package": { "...": "contracts-v1 ContextPackage" }
}
```
- 不接收原始 `.eml`、原始邮件正文、附件二进制、附件 URL、数据库连接信息、PMS/Opera 凭据或旧 V4 payload。
- `parsed_fact_set.agent_input_material` 是唯一允许的文本材料:它只包含 current subject/body 的脱敏、限长摘要,绑定 `CURRENT_BODY` evidence最多 12,000 个 code pointquoted history、sender、URL、附件 bytes 和 Secret 不得出现在其中。
- `ParsedFactSet` 已包含当前材料的事实、未解决字段、Catalog/Parser 版本和安全 evidence reference`ContextPackage` 只包含按 Group Code/订单定向取得的当前态,以及不含历史自由文本的 Trace 顺序摘要。
- quoted history 不能单独触发动作;它只允许解释当前邮件中已有的目标。
## 输出契约
Agent 必须只返回一段合法 JSON结构为 `booking-contracts-v1``CandidateDecision`
```json
{
"contract_meta": { "contract_version": "booking-contracts-v1" },
"decision_origin": "AGENT",
"result_disposition": "IN_SCOPE_TASKS | GENERAL_NOTIFICATION | RISK_NOTIFICATION | IGNORED_DIRECTION",
"target_decisions": [],
"message_notifications": [],
"issues": []
}
```
- 每个 evidence reference 的 `evidenceId` 必须来自输入不得捏造证据、URL、附件内容或分析过程。
- 不确定、目标/材料/Parser 结果歧义时返回 `RISK_NOTIFICATION` + `S99`,不得猜测字段或把未知房量变为 FIT/0。
- 已知业务但字段缺失时保留原业务类型和缺失字段;由 Validator / 用户确认处理。
- 确定整封邮件无支持任务时才可返回 `GENERAL_NOTIFICATION` + `S10`
- 确定为酒店外发或内部方向邮件时返回 `IGNORED_DIRECTION`,不生成任务。
- 只有 `ParsedFactSet` 中已有明确 `GROUP_CODE_REPLACEMENT` relation 时,才能把 old→new 团号作为 Update不得从两个团号自行推断替换关系。输出 new group 的 Update 时必须保留该 relation 的 old/new/relationship ID。
- Trace 部门只有输入证据唯一明确时可预填;否则保持空并令本地 Validator 阻断确认。可选部门为 `FO``HSK``department_codes: ["FO", "HSK"]`。同团同封的多个 standalone Trace 可以分别输出,信息系统会本地合并且保留每条 linked action不得合并跨封 Trace。
- 不调用工具,不下载附件,不写数据库,不建最终任务,不调用 PMS/Opera不向客户发信。
## 本地防线
后端适配器会:
1. 只传递 `ParsedFactSet + ContextPackage`,并二次校验/脱敏 `agent_input_material`
2. 将 Agent 输出标准化为服务端的 `contract_meta` 和 evidence 集;
3. 拒绝未知 evidence
4. 将调用/JSON 失败转换为目标级/邮件级 Risk
5. 始终交给本地 `BookingDecisionValidator`,不能绕过确认页;
6. 默认关闭,只有 `TH_HOTEL_BOOKING_AGENT_ENABLED=true` 且部署了 profile 后才允许调用。

View File

@@ -0,0 +1,121 @@
# Booking 邮件处理架构 v0.4
| 项目 | 内容 |
| --- | --- |
| 文档状态 | 当前有效 |
| 架构版本 | `booking-architecture-v0.4` |
| 契约版本 | `booking-contracts-v1` |
| 业务基线 | `BR00-BASELINE-1` |
| 范围终点 | 用户确认;不调用 PMS、Opera、付款或部门流转 |
## 1. 目的与替代关系
本架构把邮件获取、附件识别、固定渠道确定性解析、历史上下文、Booking Agent、校验和人工确认收敛为一条可追溯主线。它替代以附件 Parser 或旧 V4 入站模型为中心的实施方式。
早期 `architecture-v0.3`、M002 叙述和 M012 V0.1 实现记录仍可用于迁移和回归,但不能再单独作为新功能的实施依据。新增实现必须以本文和 [Booking 邮件 contracts-v1](booking-email-contracts-v1.md) 为准发生冲突时contracts-v1 优先。
## 2. 七层职责与边界
| 层 | 负责什么 | 输入 | 输出 | 不负责什么 |
| --- | --- | --- | --- | --- |
| 1. 信息系统接入与编排 | 接收 AgentBus 邮件或手工 EML建立幂等、处理批次与状态查询 | AgentBus payload / `.eml` | `SourceMessageEnvelope` | 不理解业务、不直接建最终任务 |
| 2. 材料预处理 | 分离 current/quoted history列举附件、图片、工作簿结构和候选材料保留证据引用 | `SourceMessageEnvelope` | `MaterialPackage` | 不把历史内容重复当作本次动作 |
| 3. 确定性 Parser + Catalog | 对适用固定渠道使用版本化渠道 Profile、字段别名和底色规则提取标准事实 | `MaterialPackage` | `ParsedFactSet` | 不猜映射、不做最终业务决定 |
| 4. 当前态与邮件上下文 | 按 Group Code、订单线索或会话定向读取当前事实、有效未完成任务与计划完成态 | `ParsedFactSet` + 来源/历史线索 | `ContextPackage` | 不扫描全库、不让历史邮件重新触发动作 |
| 5. 业务识别 / Booking Agent | 合并当前材料、Parser 事实和 Context形成候选业务决定Parser 失败/不适用/歧义时按需兜底 | `ParsedFactSet` + `ContextPackage` | `CandidateDecision` | 不下载附件、不直接读写数据库、不建最终任务、不调用 PMS |
| 6. Validator 与人工确认准备 | 校验 schema、Catalog、证据、目标、生命周期、前置关系和确认必填项 | `CandidateDecision` | `ValidationResult``ConfirmationProjection` | 不绕过校验建卡、不执行外部业务动作 |
| 7. 用户确认 | 展示安全的关键参数、证据、阻断、可编辑字段和链接动作;冻结已确认参数与审计 | `ConfirmationProjection` | `CONFIRMED` 记录 | 不调用 PMS/Opera不改变付款或部门状态 |
### 2.1 信息系统与 Agent 的职责分界
- **信息系统**拥有 SourceMessage、幂等、附件/证据存储、Catalog、确定性 Parser、Context 查询、Validator、数据库事务、确认 API 和审计。
- **AgentBus**既是邮件消息入口适配器,也是 Booking Agent 的承载平台;它不成为业务事实源。
- **Booking Agent**只消费最小化的 `ParsedFactSet + ContextPackage`,其中唯一的正文材料是 policy 脱敏、限长的 `agent_input_material` current excerpt它不能自行扩大材料范围、下载附件、调用 PMS 或写任务表。
- Parser、Agent 和 Validator 使用同一 `catalog_version`。Catalog 是跨层的版本化业务词典,不属于某一个 Agent skillAgent 的 reference 是 Catalog 的受控消费视图。
- `Name of Group``Group Name``Tour Code``Group Code` 是固定渠道对同一团号的不同列名;第 3 层统一写入 `group_code`,第 4 层也只以该统一值定向查询,不能把列名差异制造成多目标。
## 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 的受控分支。
- 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。
### 5.2 严格底色与 Profile
- 固定渠道 Profile 必须同时满足文件信号、明确业务 Sheet 规则和表头签名;平分、未知或非法 Sheet 均停止确定性解析,进入 Risk/fallback。
- `STRICT_CURRENT_CANDIDATE` 必须在 Catalog 定义的业务范围内整行非白底。字体颜色、批注、条件格式推测和白底不计入。
- anchor 行提供身份/明细列;合法 continuation 行仅补动作/状态列。任意多行互补都不能升级为确定事实。
- 未知房量保持 `booking_type=null/UNRESOLVED`,不能按 0 推断 FITTrace 部门只有邮件证据唯一明确时预填,否则由用户选择 FO、HSK 或二者。
### 5.3 改团号与 Trace 生命周期
- old→new 团号只在 current body 明确标注后进入 `GROUP_CODE_REPLACEMENT`Context 只读 old/new 两个 Group Codeold 有效且 new 不存在才允许 Update 继续。两个普通团号、历史引用或多条矛盾关系均进入复核。
- 同团同封的 standalone Trace 在信息系统内合并为一张候选卡,保留每条服务项和证据;跨封 Trace 绝不并入旧卡Context 只以无自由文本的时间序摘要提供历史顺序。
- Trace 的最终确认至少选择 `FO``HSK`,可同时选择二者;本期确认不触发部门流转。
## 6. 数据与事实源
- 新 Booking 主线的事实源是 PostgreSQL schema `th_hotel_booking`。处理运行、版本化契约、证据引用、候选、校验和确认投影均落入该 schema。
- 旧 MySQL V4 数据仅作历史兼容读取;禁止未定义双写、跨库事务或把 MySQL 记录当作新主线事实源。
- 每次读取 Context 必须按 Group Code、订单线索或已知 SourceMessage 定向查询;无目标线索时不能扫描全库找“最像”的订单。
- 主数据渠道白名单、sender → Account/Market/Source、Rate Code 映射)也是版本化事实。零候选、多候选和未配置均保留待用户补充,不能猜测。
## 7. 接口与并行工作边界
后续实现可以并行,但只能依赖 contracts-v1
- Track A`BookingMessageOrchestrator` 和入口适配器。
- Track BBooking Agent profile、prompt、skill/reference 与离线 contract tests。
- Track CContext/lifecycle assembler。
- Track DPostgreSQL 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 内部结构作为新模块之间的接口。

View File

@@ -0,0 +1,53 @@
# BR00 业务类型 contracts-v1 验收矩阵
| 项目 | 内容 |
| --- | --- |
| 文档状态 | 当前有效 |
| 业务基线 | `BR00-BASELINE-1` |
| 契约版本 | `booking-contracts-v1` |
| 目的 | 把业务理解、契约、实现切片与验收证据对齐;不是旧 V4 卡片清单的替代品 |
## 1. 共同判定规则
- 只由 current 邮件正文、当前附件和明确当前指令触发业务。quoted history 只用于理解、继承身份和重复提示。
- `Name of Group``Group Name``Tour Code``Group Code` 都是**团号的来源别名**,统一标准化为唯一业务字段 `group_code`;不得把同一团号拆成四个独立身份字段。若有真正独立的展示名称,才可额外填 `group_name``tour_code` 仅保留兼容镜像,不能作为第二个目标。
- 已知业务但字段缺失:保留原业务类型进入复核;不降格为 General/Risk。
- 整封没有任何支持任务才产生一条 General。存在不可安全解释片段时每封最多一条 Risk同封清晰任务继续生成。
- 用户确认是本期终点。任何卡片、确认、Allotment source 关系、图片或付款说明都不得触发 PMS/Opera、付款核销或部门流转。
## 2. 类型矩阵
| 业务类型 | 识别与拆分 | Context 必要信息 | Validator / 确认阻断 | 当前实现状态与后续切片 |
| --- | --- | --- | --- | --- |
| `NEW_BOOKING` | 每个清晰预订目标一张候选;同一 `group_code` 下的多个房型/日期段可属于同一目标,不按团号别名误拆 | 是否已有同 Group Code/订单、sender 映射、Rate Code 候选 | Booking Type、可定位身份`group_code` 或明确姓名)、入住/离店、房型+数量、Rate CodeGroup 必须有 `group_code`,不要求凭空填写 `group_name`;房量未知不得推 FIT | 固定渠道纵向切片已存在;迁移到 contracts-v1/PostgreSQL 主线 |
| `UPDATE_BOOKING` | `AMEND``AMD``AMEND TO` 等归一;每封实际 Update、每个目标生成新的 Update 候选 | 目标当前确认态、有效未完成任务、old→new Group Code 链、revision | 目标必须唯一或由用户选择;前置 New/Update 关系、Cancel 后冲突、变更字段与证据 | 固定渠道纵向切片已存在;连续生命周期在 Phase 4 收口 |
| `CANCEL_BOOKING` | 当前邮件明确取消指令;不能把 quoted history 的旧 Cancel 再触发 | 目标当前态、未完成 Update/Cancel、关联证据 | 目标/前置链/重复判断;确认只是冻结取消参数,不结束订单 | 固定渠道纵向切片已存在Cancel 后冲突在 Phase 4 收口 |
| `TRACE_RESERVATION_NOTES` | Extra Bed 是 Trace不是房型同一 Group Code、同一 current 邮件的多个 Trace 合并 | 同 Group/订单、相邻 lifecycle 任务、既有 Trace | Department 仅在邮件证据唯一明确时预填;否则确认前必须选 FO、HSK 或两者 | 基础卡已存在;文字/图片证据和跨封顺序在 Phase 4 收口 |
| `ROOMING_LIST` | 当前附件/正文表明房表事项;一 Group Code 一项 | 目标识别或未知目标线索 | 只展示/下载 Excel不解析旅客、不改 DEFGroup Code 不明仍应生成目标未识别通知 | 原生通知卡已存在;材料展示和下载在 Phase 4 收口 |
| `PAYMENT` | 当前附件/图片/正文表明付款凭证或替换说明 | 目标识别、附件/图片与当前邮件的关联 | 只展示图片/替换说明;不核对到账、不改订单状态;目标不明保留通知 | 基础附件摘要已存在;图片路径在 Phase 4 收口 |
| `ALLOTMENT` | 每个 actual 团独立识别为 Newsource 团与 actual 团的关系必须显式表达 | source 团当前库存/状态、每个 actual 的准入结果 | 先验证每个 actual只汇总通过准入的房量给 sourcesource 不存在/不足不回滚安全 actual只提示人工 | 未作为已完成切片Phase 4 独立主线最后收口 |
| 图片 / Voucher 媒体 | 图片不是单独业务类型;结合 current 正文判断其支持 Trace、Payment/替换说明或不在范围 | 当前正文、附件关系、目标线索 | 证据不足不猜业务类型;可形成 Risk 或 General/ignored不能自行创建“Voucher 订单” | Phase 4 与 Payment/图片一并完成 |
| `GENERAL_NOTIFICATION` | 整封 current 邮件经材料、Parser 和业务词典确认没有支持任务 | 仅消息级最小上下文 | 不得因已知业务缺字段而生成 General | 基础通知已有;迁移后由 contracts-v1 统一输出 |
| `RISK_NOTIFICATION` | 业务类型、目标、材料或 Parser 结论有不可消解歧义 | 受影响目标/材料/历史摘要 | 每封最多一张只隔离歧义片段Agent invalid 也必须经 Validator 进入 Risk | 基础通知已有;目标级隔离在 Phase 3 收口 |
| `IGNORED_DIRECTION` | 可确定为酒店外发、内部邮件或不属于处理范围 | 邮件方向、sender/recipient、受控规则 | 不创建待办或业务卡,保留安全处理记录 | 新 contracts-v1 主线能力,随 Orchestrator 实现 |
## 3. 核心样例到契约的断言
| 场景 | 必须形成的事实 | 禁止推断 |
| --- | --- | --- |
| `【U-TWN8.5】 12` | 房型线索 `U-TWN`、价格证据 `850`、数量 `12`;与备注共同形成当前动作线索 | 不从价格直接猜 Rate Code |
| `【U-TWN】 6)(850...)` | 房型线索 `U-TWN`、数量 `6`、价格证据 `850` | 不因格式差异丢失 New Booking 语义 |
| `NEW BOOKING ยกเลิก``NEW BOOKING CXL` | Parser 可保留动作候选及原始证据;业务/生命周期最终解释由 Catalog+Context+Validator | 不穷举所有自然语言组合后把未覆盖文本静默当普通 New |
| Excel 非白底整行 | 严格候选行和行/列/Sheet 证据 | 不能靠任意一个底色单元格、字体颜色或多行互补建立确定事实 |
| 无附件 current 邮件 | `MaterialPackage(NO_ATTACHMENT)`,仍进入 Context 和业务识别 | 不能绕过 SourceMessage 或直接生成 General |
| 同一信息再次出现 | 重复/陈旧提示与消息幂等证据 | 不能静默丢弃真实新邮件或把两封邮件强行合并 |
## 4. 验收最低集
每个业务类型在实现完成前都必须至少有:
1. 一个去隐私的 contracts-v1 正例与一个错误/歧义例。
2. Parser、Agent如适用和 Validator 对同一输入的版本、evidence reference 与目标范围断言。
3. PostgreSQL `th_hotel_booking` 的 processing run、候选、校验和确认投影持久化断言。
4. 前端的展示/阻断/确认行为断言;确认后不产生 PMS/Opera、付款或部门副作用。
5. 对应真实或脱敏 E2E 样例;真实邮件只通过 opt-in 路径读取。

View File

@@ -0,0 +1,168 @@
# Booking 邮件 contracts-v1
| 项目 | 内容 |
| --- | --- |
| 文档状态 | 权威契约 |
| 契约版本 | `booking-contracts-v1` |
| 对应架构 | [Booking 邮件处理架构 v0.4](booking-email-architecture-v0.4.md) |
| 适用终点 | 用户确认PMS/Opera 不在本契约执行范围 |
## 1. 共同信封与版本规则
七层之间传递的每个顶层对象必须包含 `contract_meta``evidence_refs[]`。禁止靠调用方上下文、数据库隐式默认值或 Agent prompt 隐式补齐版本。
| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `contract_version` | 是 | 固定 `booking-contracts-v1`。不兼容变更必须新版本。 |
| `catalog_version` | 是 | 本次使用的业务目录版本;尚未执行目录处理时填 `catalog-not-applied`。 |
| `parser_version` | 是 | 本次 Parser 版本;未执行时填 `parser-not-run`。 |
| `agent_profile_version` | 是 | Booking Agent profile 版本;未调用时填 `agent-not-invoked`。 |
| `processing_run_id` | 是 | 一次处理运行的稳定 ID重试使用同一 run、不同 attempt。 |
| `source_message_id` | 是 | 平台 SourceMessage 的稳定 ID不可使用邮件主题代替。 |
| `source_revision` | 是 | 同一来源消息在材料重取或重放后的可追溯版本。 |
| `evidence_refs` | 是 | 最小化证据引用不嵌入原始邮件、完整附件、Secret 或外链 URL。 |
`evidence_ref` 至少包含 `evidence_id``kind``source_message_id``locator``content_hash``is_current_material``kind` 允许 `CURRENT_BODY``QUOTED_HISTORY``ATTACHMENT``WORKBOOK_SHEET``WORKBOOK_ROW``IMAGE``OCR_TEXT``CONTEXT_RECORD``USER_CORRECTION``locator` 只能表达安全定位(例如 Sheet/行号、附件逻辑 ID、上下文记录 ID不能含签名 URL 或原文全文。
所有 issue 使用同一结构:`code``severity``INFO`/`WARNING`/`BLOCKER`)、`scope``MESSAGE`/`MATERIAL`/`TARGET`/`FIELD`)、`message_key``evidence_refs[]`、可选 `retryable`。用户可见文本由 `message_key` 和前端文案生成,避免把原文写进 API。
## 2. SourceMessageEnvelope
**层 1 输出。** 统一 AgentBus 与手工 EML不携带业务判断。
| 字段 | 说明 |
| --- | --- |
| `message_origin` | `AGENTBUS``MANUAL_EML`。 |
| `external_message_id``conversation_id``in_reply_to` | 邮件身份与会话链路;缺失时保留 null不用主题猜。 |
| `idempotency_key` | 基于可信消息身份/内容摘要形成;只处理外部重复投递,不合并两封真实邮件。 |
| `sender``recipients``subject` | 最小化安全摘要或受控引用;不作为唯一业务事实。 |
| `received_at` | 收件时间点UTC。 |
| `current_body_ref``quoted_history_ref` | 对正文 current/history 分离后的证据引用。 |
| `attachment_descriptors[]` | 逻辑附件 ID、文件名摘要、媒体类型、大小、内容哈希、受控原件引用。 |
不可接受:入口直接调用 Parser/Agent 后跳过 SourceMessage、入口把 AgentBus 的原始 JSON 当领域对象、或根据邮件主题创建订单。
## 3. MaterialPackage
**层 2 输出。** 描述可供解析/理解的材料,不表达最终业务类型。
| 字段 | 说明 |
| --- | --- |
| `message_envelope` | `SourceMessageEnvelope` 的最小必要摘要与 ID。 |
| `current_materials[]` | 本次可触发业务的 current body、当前附件、当前图片、明确版本指令。 |
| `quoted_history_materials[]` | 仅用于解释、继承身份、重复检查的历史材料。 |
| `workbook_inspections[]` | 文件哈希、Sheet 名称、表头签名、候选行/列、底色证据、Profile 候选与检测结果。 |
| `image_inspections[]` | 图片证据与可选 OCR 安全摘要;不把 OCR 当唯一事实。 |
| `material_selection_status` | `READY``NO_ATTACHMENT``UNSUPPORTED``AMBIGUOUS``FAILED`。 |
| `issues[]` | 材料层问题,例如超限、文件损坏、多个 Profile 平分、非法 Sheet。 |
规则current 与 quoted 必须可区分;没有附件时输出 `NO_ATTACHMENT` 但仍为有效 package固定渠道只把严格候选行送入确定性 Parser其他行只能作为复核证据。
## 4. ParsedFactSet
**层 3 输出。** Parser 的标准事实集合;它不等于最终业务决定。
| 字段 | 说明 |
| --- | --- |
| `parser_applicability` | `APPLICABLE``NOT_APPLICABLE``FAILED``AMBIGUOUS`。 |
| `channel_profile_code` | 成功解析时的固定渠道 Profile不能唯一确定时为 null。 |
| `facts[]` | 可追溯的标准事实,必须逐项带 `fact_id``confidence_kind=DETERMINISTIC``evidence_refs[]`。 |
| `unresolved_fields[]` | 未能确定的字段及原因未知房量、Rate Code 映射等必须保留。 |
| `fallback_reasons[]` | 需要 Booking Agent 或 Risk 的明确原因代码。 |
| `issues[]` | Profile、底色、字段格式、解析失败等问题。 |
| `agent_input_material` | 可选、受控的 Agent current-message 文本;只在本地 policy 脱敏、限长后出现。 |
`facts[]` 的稳定字段包括:
- `action_hint``NEW_BOOKING``UPDATE_BOOKING``CANCEL_BOOKING` 或 null`booking_type` 只在房量足以确定时为 `FIT`/`GROUP`,否则为 null。
- `target_identity``group_code` 是团号统一字段;`Name of Group``Group Name``Tour Code``Group Code` 进入该字段。`group_name` 只用于邮件明确给出的独立展示名称;`tour_code` 是历史兼容镜像,不能与 `group_code` 形成两个目标。`name_values` 只保存真正的客人/联系人姓名;字段未知必须为 null。
- `stay``arrival_date``departure_date``nights``room_items[]`、价格原始证据。
- `room_items[]``room_type_code_hint``room_count``rate_hint``evidence_refs[]`Extra Bed 不能写入房型。
- `related_hints[]`Trace、Rooming List、Payment、Allotment source/actual、明确 `GROUP_CODE_REPLACEMENT` old→new 关系等候选线索。
`agent_input_material` 是为了让 Parser fallback 能理解无固定渠道的正文,而不是第二份原始邮件:它只能绑定一个 `CURRENT_BODY` evidence内容仅来自 current subject/body`booking-agent-current-message-v1` 脱敏并限制为最多 12,000 个 code point。它必须排除 quoted history、原始附件、附件 URL、sender 原文和 Secret该受控摘要可随 `PARSED_FACT_SET` 在项目 schema 保留至 `retention_until`,以支持同一 run 的异步 Agent/retry不得用它还原原始邮件。
`GROUP_CODE_REPLACEMENT` 只接受 current body 中明确标注的 old→new 指令。单封普通文本中出现两个团号、主题猜测或 quoted history 都不能生成关系。该 relation 在 Parser fallback 中是无动作 Context/Agent clue固定渠道仅能绑定到同一 new group code 的 `UPDATE_BOOKING` fact。
Parser 不得:将 `room_count=0` 解释为 FIT、在 Profile 平分/未知/非法 Sheet 时产生确定事实、用多行互补制造 anchor 事实、或因字段缺失把已知动作改写成 General/Risk。
## 5. ContextPackage
**层 4 输出。** 面向一封当前邮件与已识别目标的最小上下文,而不是历史全量 dump。
| 字段 | 说明 |
| --- | --- |
| `context_scope` | `MESSAGE` 或一个/多个 `TARGET`;每个 target 有独立查询边界。 |
| `target_resolutions[]` | 输入线索、零/一/多候选、解析状态和证据;多候选不自动选择。 |
| `current_state` | 已确认事实、有效未完成任务、计划完成态;带数据来源与更新时间。 |
| `conversation_context` | 当前邮件的必要历史摘要、revision 关系与重复线索;历史内容不重新触发动作。 |
| `lifecycle_context` | New/Update/Cancel 前置链、old→new Group Code、Cancel 后冲突、Trace 顺序。 |
| `allotment_context` | source 团与 actual 团候选关系、库存/扣减可用性;不是最终扣减命令。 |
| `issues[]` | 上下文缺失、多目标冲突、历史证据冲突等。 |
读取规则:优先 Group Code、明确订单 ID、已确认消息关联无可靠目标时返回未识别而不是全文/全库模糊扫描。
`GROUP_CODE_REPLACEMENT` 存在时Context 必须只读取 old/new 两个明确 Group Codeold 有效已确认链且 new 不存在才是 `RESOLVED`old 已取消/不存在为 `UNRESOLVED`new 已存在为 `CONFLICT``group_code_replacements[]` 必须保留 relation ID、old/new、状态、候选 ID 和 issue。Trace 历史按 Group Code 和时间顺序只提供安全摘要(任务 ID、状态、FO/HSK、服务类型跨封 Trace 永远是新卡,历史自由文本、附件定位和 quoted 内容不能进入 Context。
## 6. CandidateDecision
**层 5 输出。** 可以来自纯确定性合成或 Booking Agent两者使用同一结构。
| 字段 | 说明 |
| --- | --- |
| `decision_origin` | `DETERMINISTIC``AGENT``MIXED`。 |
| `result_disposition` | `IN_SCOPE_TASKS``GENERAL_NOTIFICATION``RISK_NOTIFICATION``IGNORED_DIRECTION`。 |
| `target_decisions[]` | 每个目标独立的候选动作、目标身份、字段、linked/derived actions、证据和 issues。 |
| `message_notifications[]` | General/Risk/ignored 的消息级结果Risk 每封最多一条。 |
| `agent_trace_ref` | Agent 调用 ID/版本/安全摘要;纯 Parser 时为空。 |
| `issues[]` | 对整封消息的无法分配问题。 |
`target_decision``business_type` 为:`NEW_BOOKING``UPDATE_BOOKING``CANCEL_BOOKING``TRACE_RESERVATION_NOTES``ROOMING_LIST``PAYMENT``ALLOTMENT``action_kind` 由业务类型和当前态决定。Allotment 必须显式输出 actual 与 source 的关联,不能把多个 actual 或 source 扣减隐匿在一张普通 New 卡里。
Booking Agent 的受控输入只允许 `ParsedFactSet + ContextPackage``ParsedFactSet.agent_input_material` 是唯一可见的正文材料,且受上文 policy 约束。若 Parser `NOT_APPLICABLE``FAILED`,也必须先创建最小的 `ParsedFactSet`,明确未解析原因,而不是把原始附件或 quoted history 直接交给 Agent。
## 7. ValidationResult
**层 6 的校验输出。** 只有 `validation_status=VALID` 的目标才可产生确认投影。
| 字段 | 说明 |
| --- | --- |
| `validation_status` | `VALID``REVIEW_REQUIRED``RISK``REJECTED`。 |
| `validated_targets[]` | 目标级通过/阻断结果,不让一个目标阻断同封其他清晰目标。 |
| `schema_checks[]` | contracts-v1 结构和版本检查。 |
| `business_checks[]` | Catalog、必填、目标、生命周期、前置任务、linked action、重复/revision 检查。 |
| `blockers[]` | 必须由用户补齐或修复才可确认的条目。 |
| `risk_notification` | 仅隔离无法安全决定的部分;每封至多一张。 |
Validator 必须校验版本一致性、证据存在、目标解析、字段必填、Catalog 映射、当前生命周期、已确认/未完成任务、外部重复投递、真实新邮件、revision、历史底色遗留和业务内容相同。Agent 输出无效时,目标级进入 Risk不能绕过 Validator 建卡。
## 8. ConfirmationProjection
**层 6 面向前端的安全输出。** 它不是原始 CandidateDecision 的直通 JSON。
| 字段 | 说明 |
| --- | --- |
| `projection_status` | `AWAITING_CONFIRMATION``REVIEW_REQUIRED` 或不可生成。 |
| `confirmation_items[]` | 用户可见任务/通知,按目标拆分。 |
| `display_fields[]` | 已归一化的关键字段、展示值、来源证据、可编辑性与校验规则。 |
| `blocked_fields[]` | 缺失/冲突字段及需用户选择的候选;不暴露内部 payload。 |
| `linked_actions[]` | 如 Allotment source/actual、Trace 合并关系;只显示本期可确认参数。 |
| `safe_evidence[]` | 文件/Sheet/行/图片等安全引用与脱敏摘要。 |
| `processing_run` | run ID、当前状态、可重试状态与安全错误摘要。 |
确认 API 只冻结用户确认的参数和审计,必须携带 `processing_run_id` 与并发版本。确认成功不调用 PMS/Opera也不执行付款、库存扣减或部门流转。
## 9. 编排、持久化与 API 约束
1. AgentBus 与手工 EML 都调用同一个 `BookingMessageOrchestrator`,并产生一致的 `SourceMessageEnvelope` 幂等语义。
2. 同步完成且无需异步 Agent 时返回 `201`;进入 Agent 或异步处理时返回 `202``processing_run_id`
3. 状态查询为 `GET /api/reservation/booking-processing-runs/{runId}`;已有 `POST /api/reservation/booking-email-intakes` 逐步适配为统一入口。
4. PostgreSQL `th_hotel_booking` 保存 run、attempt、版本、证据引用、候选、校验和确认投影`PARSED_FACT_SET` 中只允许保存受 policy 约束的 Agent 摘要,所有这些项目 schema 数据按 `retention_until` 三个月清理。旧 MySQL 只能被 Context 兼容读取,不能参与新主线写入或跨库事务。
5. 所有持久化/接口代码必须使用 `contract_version` 做版本门禁;未知未来版本 fail closed 并形成安全 Risk/技术错误记录。
## 10. 兼容与测试要求
- Parser 与 Booking Agent 对相同事实必须输出可比较的 `CandidateDecision`;差异只能通过显式 `decision_origin` 和 issue 表达。
- 每个 Contract 都需 JSON/Java fixture、schema validation、正向/错误案例及 evidence reference 检查。
- 真实邮件只作为 opt-in 外部验收;仓库只保存去隐私 fixture 与样本哈希/Profile 断言。
- 后续对字段、枚举、状态机或业务动作做破坏性变更时,必须新增 contracts-v2而不是静默改 v1。