Files
th-hotel-simple/docs/project/requirements/M012-liantai-shared-parser-parsing-agent-change-request-v1.md
T
鲨鱼辣椒 694c4317a3 checkpoint: complete recoverable V2 pre-separation baseline
Complete the selective V2 checkpoint with its minimal AgentBus, object-storage, replay persistence, and validated-workbench shared dependency closure.
2026-08-20 17:09:00 +08:00

280 lines
19 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.
# M012 / LianTai 共享 Parser 与 Parsing Agent Change Request v1
> **Migration notice(2026-08-11)**:本文记录已验证的旧本地切片及 LianTai 业务规则。
> Parser 公共输出、状态与 source-room 字段以 ADR-008 和
> `M012-qbd-liantai-parser-output-contract-v1.md` 为准;内部 Q10/早餐拆解不得再输出为独立
> `ROOM_QUALIFIERS`,完整来源房型名称必须保留 BF/Q10。
>
> **Parsing Agent v1.0发布前纠错**:本文旧切片中由Layer 3直接形成Trace、linked action和部门映射的
> 描述已由ADR-009及`M012-fixed-channel-parsing-agent-v1-contract.md`取代。当前Layer 3只输出中立
> `structured_mentions[]`;Layer 5 Booking Agent决定业务类型、Trace和部门候选。
| 项 | 内容 |
| --- | --- |
| 状态 | **EXISTING LOCAL SLICE VERIFIED — Parsing Agent v1.0 offline Skill/schema/fixture/package implemented; runtime remains gated** |
| 日期 | 2026-08-11 |
| 用户确认范围 | LianTai |
| 共用基线 | ADR-008 `fixed-channel-parser-fact-material-v1`、ADR-009 `fixed-channel-parsing-agent-v1`、QBD Parser / shared Parsing Agent v1.0 |
| 影响范围 | Backend / Layer 3 / Parsing Agent asset / neutral structure and display / Test / Docs |
| 终点 | 用户确认;不调用 PMS、Opera、付款或部门流转 |
## 1. 变更目的
LianTai 的真实邮件使用带底色的月度 Booking 工作簿,主要业务规则与 QBD 高度重合。本变更不建立第二套 Parser 或第二个 LianTai Agent,而是在同一固定渠道 Parser core、同一 message-level Parsing Agent 和同一 Layer 3/5/6 契约中新增受控 LianTai Profile。
本次同时补齐三个共享缺口:
1. 将用户确认的九类来源房型语法放入 QBD/LianTai 共用 source-room 解析组件;
2. 将 G/I 自由文本分为中立结构化内容和员工展示信息;
3. 明确Layer 3不判断Trace、linked action或部门,相关业务决定由Layer 5 Booking Agent负责。
## 2. 架构决定
### 2.1 一套 Parser,一套 Parsing Agent
- sender registry在调用Parsing Agent前精确匹配渠道;LianTai进入`LIANTAI` active Profile,本期固定渠道只允许QBD与LianTai。
- Workbook/Header/动作/日期属于 Profile 规则;Observation、fact identity、evidence、source-room、合并、Agent 输入/输出和卡片投影属于共享 Core。
- message-level Parsing Agent 每封 current 消息只运行一次,可看到受控 current body、全部受控 history body、Parser contributions 及 LianTai G/I 材料;它不得覆盖 Parser 的确定性贡献。
- Agent asset/profile 可按来源加载受控 reference,但不得复制出 LianTai 专属长期契约或 LianTai 专属 Agent。
### 2.2 Field Recovery 兼容共存
- 现有 Field Recovery 只处理 `UNRESOLVED + RECOVERABLE` 的稳定字段,继续保留。
- message-level Parsing Agent 负责 current/history 正文、G/I 备注语义、Parser fallback 与跨材料关系,不接管已确定 Parser 字段。
- 两条链路不得对同一确定性槽位双写;真冲突并列形成 issue 并转人工。
- 下游只消费经过本地校验/合并后的单一 effective fact view。
### 2.3 中立结构再进入业务判断
- Layer 3保存材料事实、`DETAIL_RAW`、中立structured mentions和员工展示信息,不直接产出业务类型、部门、TaskCard或PMS动作。
- Layer 5 Booking Agent判断中立结构是否形成Trace、linked action或其他`CandidateDecision`,并仅在证据明确时提出部门候选。
- Layer 6 Validator对缺失部门或其他必需业务字段fail closed,再由Projection按固定字段生成卡片。
- 不需要业务拆解的G/I内容保存为员工可见只读信息,不伪装为动作。
## 3. Profile 与材料门禁
### 3.1 Sender 与附件
- active sender:精确规范化后的 `op.liantaitravel@gmail.com`。
- 只处理 current `.xlsx`;附件字节缺失、损坏、超限或多个匹配工作簿均 fail closed。
- 同封邮件有多个匹配 LianTai 工作簿且没有明确版本指令时,`AMBIGUOUS` / 人工复核。
- 不下载 history attachment,也不比较上一版月表;Update 的 BEFORE 可以为 null,只要 AFTER 清晰。
### 3.1.1 Current正文与固定邮件模板
- 固定邮件模板全部忽略,不形成业务事实、structured mention或员工展示信息。固定模板包括:固定问候、正文内固定`Update Booking`标题、重复出现的“无导游时联系酒店确认并联系OP”提醒、固定联系人区和公司页脚。
- 路由只使用受控邮件头中的发件人;正文、联系人区或公司页脚内出现的姓名、电话、邮箱和其他联系方式不得参与渠道识别或业务解析。
- Current正文中固定模板之外的新增内容,与G/I自由文本采用同一分流:可结构化的服务内容形成中立mention;只需员工知晓的内容原文展示;含义、目标或必要参数不清时进入人工复核,禁止静默丢弃。
- 正文没有团号的展示信息不强行关联某一条有底色业务行,应保持邮件级。服务内容目标不明确时不得猜测团号,进入人工复核。
- 正文明确出现团号时,只有附件中存在唯一、同团号且有底色的业务目标,才具备自动关联前提。对应团号没有底色、正文与附件团号不一致,或附件中存在多个有底色团号目标时,直接人工复核,不以文本相似度、行序或历史值选择目标。
- 这里的“关联/绑定”只表示正文材料属于附件中的哪一条有底色业务目标,不表示合并预订、跨行聚合或改写Parser事实。
### 3.2 August 9列模板
本期只支持 9 列 August 模板。July 7 列模板不适用并进入受控 fallback/review,不得猜测列位。
| 列 | 表头/业务含义 | 本期处理 |
| --- | --- | --- |
| A | `Tour Code / 主团号` | 必须提取;统一为 `group_code`,同时承担 group name 语义 |
| B | Tour Days / 行程天数 | 完全忽略 |
| C | 人数 | 完全忽略;不得决定 FIT/GROUP |
| D | `วางข้อมูลที่นี่ / 酒店明细` | 提取 stay、source room、source price、quantity 与剩余原文 |
| E | Nights Override | 忽略;晚数始终由 departure-arrival 计算 |
| F | 导游 | 完全忽略 |
| G | 动作 + 备注 | 取最新有效动作;完整原文及非动作残余保存并交 Parsing Agent |
| H | 酒店回执 | 内容完全忽略、不保存、不呈现 |
| I | REMARK | 完整原文保存并交 Parsing Agent;分流为结构化意图或普通备注 |
### 3.3 业务 Sheet
- 只选唯一能与标题/Sheet 名确定到同一业务月份、且表头唯一匹配 A:I 签名的业务 Sheet。
- `AUTO_CALC`、`DASHBOARD` 等辅助页完全忽略,不读业务行、不记录业务事实。
- 零个或多个业务 Sheet、重复/歧义表头、标题月份冲突均 fail closed。
### 3.4 底色选行
真实 August 工作簿的业务行并非 A:I 九格全部着色;5 条 current 黄色行稳定共同着色的是 A、D、G。现有 QBD 也只校验 Profile core cells,而非整张物理行。
因此 LianTai 严格候选规则为:
- A、D、G 均非空;
- A、D、G 均为 solid、非白/非默认底色;
- 三格使用同一 fill signature;不固定黄色或橙色 RGB;
- B/C/E/F/H/I 是否为空或着色不参与选行;
- A/D/G 任何一格缺色、白底或颜色不一致时不产生确定性事件,进入 review;
- 每条选中的物理行都是独立主业务事件,即使 `group_code` 相同也不跨行合并。
## 4. 确定性字段规则
### 4.1 A列目标
- A列非空原文完整保存;trim 后作为 `group_code` normalized value。
- `group_code` 同时承担 LianTai 的 group name / group code 业务含义,不制造第二目标字段。
- 同一物理行内多个 stay segments 共享该 row unit;不同物理行永远保持独立 row evidence/event。
### 4.2 D列日期与stay segment
- 每个业务明细段前缀必须为 `dd-dd`(允许空格和常见短横线差异),依次表示 arrival day 与 departure day。
- Sheet/标题提供权威业务 `YearMonth`。普通不跨月日期段默认落在该业务月;`departure day < arrival day` 的日期段以“arrival 在业务月前一月、departure 在业务月”解释。
- 同一D列的相邻日期段必须按原顺序做连续性锚定;例如August业务表中的`30-31 ... 31-02 ...`解析为`Jul 30-31`、`Jul 31-Aug 02`,而不是把前段强行放入August。不存在唯一连续解释时进入field review。
- arrival、departure 和 `nights=departure-arrival` 均保存;E列不得覆盖。
- D列出现多个日期段时按原顺序形成多个 stay segments;它们属于同一个 row unit/group target。
- 无法唯一确定年月、非法日期、缺失日期段或相互重叠语法进入 field review,不使用 tour days 或历史月表补齐。
### 4.3 D列模板噪音与剩余原文
固定删除以下组合模板,不产生任何业务事实:
- 固定酒店名 `芭提雅中天温德姆 / Jomtien Wyndham Pattaya`;
- 入住前导游路线、出门右转、射击场、7-11、`LTVC不现付` 的固定长句。
模板外的所有内容保留原文。独立 `ออฟฟิศจ่าย` / `ยืนยันแล้ว` 等付款/确认残余保存为展示材料,但不生成付款事实。固定噪音删除必须是受控短语/模式,不得用宽泛关键字删除整段用户备注。
### 4.4 G列动作时间线
识别三类动作:
- `NEW BOOKING` → `NEW_BOOKING`
- `CANCEL BOOKING` → `CANCEL_BOOKING`
- `AMEND TO` → `UPDATE_BOOKING`
规则:
- 每个动作必须绑定其后的 `dd/MM/yyyy` 等受控完整日期;
- 选择日期最新的可识别动作;同一日期并列时取文本中靠后的动作;
- `FINAL`、已通过 LINE 发送等只是过程记录,不是动作;
- 普通 `AMEND TO + 日期` 只是 Update;只有 current 明确 `AMEND GROUP CODE`/泰文只改团号及可锁定 AFTER code 时才形成 `GROUP_CODE_REPLACEMENT`;BEFORE 可为 null;
- G列完整原文、已识别动作span及非动作残余都保存,供证据、普通备注和Parsing Agent使用。
### 4.5 BEFORE / AFTER
- 不要求删除线,不读取或比较上一版工作簿。
- 当前行房型、价格、数量和stay清晰时,作为 AFTER/CURRENT;BEFORE 可以为 null。
- 只有当前材料明确给出 old→new、删除线或其他受控 before证据时才保存BEFORE。
- AFTER不清晰或多种解释同优先级时进入review,不能用历史版本猜测。
## 5. 共享source-room规则
### 5.1 括号与数量
- D列括号组是主要room/material边界;`【...】` 内的房型token和括号外紧邻整数共同解析。
- 房型后的整数是房间/套数量;缺失时默认1。
- `Sup【高级房TWN】 16` 解析为 `source_room_type=SupTWN`、`source_price=null`、`quantity=16`;独立 `ออฟฟิศจ่าย/ยืนยันแล้ว` 原文保留。
### 5.2 价格
- `8.5` 唯一特殊归一为 `850`;其他合法正数token归一为 `token × 1000`。
- 价格必须紧贴在房型token内,不能把后面的房量整数当价格。
- `U-TWN8.5` → room `U-TWN`、price `850`;括号外数量另取。
- REMARK/G中的价格语义只保留原文给Parsing Agent/用户,不在Parser阶段映射Rate Code或绑定房型。
### 5.3 九类来源房型
共享组件至少识别以下语义族,并保留raw与normalized:
1. U升级房:`U-DBL/TWN/TRP/HNM`;
2. Superior:`Sup DBL/TWN/HNM`、`SupDBL/TWN/TRP`;
3. 基础简写:`DBL/TWN/TRP/HNM`;
4. Deluxe:King/DBL/TWN/TRP/TRIPLE;
5. Family:`FAM 6+4`、`FAM (6+4)`、`Family Room - King and 1 Single`;
6. One Bedroom Suite基础写法,含DBL/TWN/TRP、Q10、FAM 3PAX;
7. One Bedroom Suite Garden/Pool,含DBL/TWN/TRP;
8. One Bedroom Suite Garden/Pool View,保留前后置view写法;
9. Two Bedroom / Family Suite,含FAM 3/4PAX、Q10、DBL/TWN与Pool View。
规范化允许统一大小写、重复空格和连字符差异,但不得丢失:`Q10`、ONE/TWO-BEDROOM、DBL/TWN/TRP、HNM/KING、GARDEN/POOL/VIEW、FAM/PAX/6+4、U升级标记及其内含价格。无法归入冻结语法的混合房型进入人工复核,raw仍保留。
## 6. 中立结构与员工展示信息
### 6.1 `structured_mentions[]`
- Parsing Agent只保存来源服务语义、原文、已知数量、来源房型、scope/target、顺序和证据。
- 允许语义为加床、蜜月布置、房间布置、水牌、会议室和其他服务;这些值不等于业务类型。
- 必要参数不完整时保留已知结构并生成review,不猜数量、房型、目标或部门。
- 合法mention未来只能以`STRUCTURED_MENTION`进入有效视图;Layer 5再决定是否形成Trace、linked action和部门候选。
### 6.2 员工展示信息
- Current正文的非模板内容、G/I和D残余中不属于支持业务意图的内容仍须保存和呈现。
- 员工展示信息至少保存:稳定ID、原文text、来源列、顺序、scope、target/row ref和evidence refs。
- 正文没有团号且无需行级目标的展示信息保持邮件级作用域,不得为了满足`target/row ref`强行猜测有底色行。
- 前端只显示后端白名单的remark text/source label,不返回邮件正文、raw evidence、附件URL、AI原始payload或内部locator。
- 过程记录(如LINE已发送)可以显示/审计,但不生成业务动作;酒店回执H列除外,H列完全忽略。
### 6.3 Agent失败
- Parser确定性主预订事实、G/I原文材料和既有普通备注都保留。
- 如果G/I存在可能执行但未识别的文本,目标进入人工复核;禁止静默自动提交或丢弃文本。
- Agent不得通过失败/空结果使已确定主预订事实消失。
## 7. Layer边界
| 层 | 本次职责 | 禁止 |
| --- | --- | --- |
| Layer 2 | current/history分离、附件与Sheet候选 | 用history触发新业务 |
| Layer 3 Parser | A/D/G/I确定性观察、stay/room/action/raw、evidence | Rate/Room目录、最终卡片、跨版本比较 |
| Layer 3 Recovery | 精确恢复获准的未决field | 重写整行或G/I语义 |
| message-level Parsing Agent | 正文/G/I中立structured mentions、员工展示信息、受控fallback | 业务分类、Trace、部门、覆盖Parser、直接建卡、查PMS/数据库 |
| Layer 4 | Context与canonical Rate/Room解析 | 改写source_room/source_price |
| Layer 5 | 最终业务类型、linked/derived action、CandidateDecision | 绕过Validator写任务/PMS |
| Layer 6–7 | 校验、安全投影、用户确认 | 暴露raw payload或隐式执行外部动作 |
## 8. Fixture与验收矩阵
仓库只保存去隐私/合成fixture,不保存真实邮件、工作簿、团号、联系人、电话或备注全文。真实材料仅以opt-in只读验收和安全hash记录。
最低fixture:
1. 唯一August业务Sheet + AUTO_CALC/DASHBOARD忽略;
2. A/D/G同一非白fill正向、任一anchor缺色/异色review;
3. 相同group_code两条有色物理行保持两个row unit;
4. New、Update、Cancel及同日后出现者胜出;
5. 一个row unit多个有序stay segments;
6. BEFORE null、AFTER清晰的Update;
7. 九类source-room、`U-TWN8.5`、`SupTWN 16`、quantity默认1;
8. 固定模板噪音删除、独立付款/确认残余保留;
9. G/I structured mention、员工展示信息、LINE过程记录、H列彻底忽略;
10. 加床/蜜月/房间布置/水牌/会议室仅保留中立语义、数量和来源房型,不输出部门;
11. 多业务Sheet/多匹配workbook/7列模板/Profile sender歧义fail closed;
12. Agent冲突/失败不覆盖Parser,可能执行的未识别文本转人工。
13. 固定邮件模板完全忽略;非模板正文分别覆盖structured mention、邮件级展示,以及“正文团号无同团有底色目标/存在多个有底色团号目标”人工复核。
## 9. 安全与发布边界
- 本次Parser/Parsing Agent能力均为`INTERNAL_ONLY`;不新增Controller、权限码或第三方入口。
- 不提交真实EML/XLSX、邮件正文、客户数据、Secret、附件URL或Provider raw answer。
- 现有Order Task详情若增加普通备注字段,继续使用`FRONTEND_USER + RESERVATION_TASK_READ + 订单任务所属酒店访问权`,只返回白名单安全文本。
- 真实Provider/runtime启用、AgentBus worker、数据库migration、PMS/Opera/OHIP均需独立发布门禁;本CR不自动放行。
## 10. 实施顺序
1. 冻结本CR、ADR和fixture;
2. 抽共享source-room与fixed-channel parse result/projector;
3. 实现LianTai Profile parser并激活受控sender;
4. 扩展共享Parsing Agent schema/reference与Layer3 fixture;
5. 实现中立structured mention和员工展示信息安全投影;业务/部门mapping留给Layer 5;
6. 接入单一effective fact view,保留Field Recovery兼容;
7. 运行focused/full backend、frontend、schema、安全和项目文档检查。
## 11. 完成标准
- 所有最低fixture通过且不访问真实材料;
- 三份hash锁定的opt-in真实工作簿只读测试通过:两版August各自独立解析,July 7列模板受控进入`AMBIGUOUS`;测试不输出真实值;
- QBD既有Parser/Recovery测试无回归;
- 员工展示信息可在安全响应/页面看到;Parsing Agent结果不含Trace或部门字段;
- Parser/Agent冲突、歧义与失败均fail closed或进入人工复核;
- 不存在第二套LianTai契约/Agent、不新增外部接口、不触发PMS/Opera。
## 12. 本地实施与验证结果
- LianTai sender已接入共享Profile registry与统一`BookingContractAssembler`。
- QBD/LianTai共用source-room parser、current-fact projector与fixed-channel facade;旧QBD入口由兼容wrapper保留。
- LianTai 9列Parser已实现Sheet/header/fill/action/stay/room/raw remark门禁;每条有底色物理行保持独立row unit。
- 共享Parsing Agent v1.0离线 Skill、闭合 input/output/Parser dependency Schema、QBD/LianTai synthetic fixture、材料闭环/证据/不可覆盖校验器与确定性`.skill`包已实现;资产保持`HOLD/INTERNAL_ONLY`,尚未启用真实Provider调用。
- v1.0 Skill reference/Schema/Fixture已写入固定模板忽略、邮件级展示、员工可见 FINAL/LINE、唯一团号关联门禁、附件 action 优先级与同 Tour Code 冲突 review;独立中文Main Prompt不进入`.skill`,不接运行时 Merger、AgentBus、Booking Agent、PMS/Opera。
- `DISPLAY_REMARK`已安全投影到后端只读字段并在processing-run页面呈现;raw/unresolved材料不进入普通用户响应。
- 旧本地切片曾在Layer 3投影Trace部门;该离线契约已由v1.0发布前纠错取代,未来由Layer 5提出部门候选。
- Recovery后的`EffectiveFactView`会投影为下游唯一`ParsedFactSet`,并传给MasterData、Context、Decision与异步/同步后续分支;原Parser artifact保持不可变。
- 验证结果:后端全量672 tests通过(0 failure/error,6 skipped,其中3个真实样本测试默认opt-in);前端34 files/300 tests、lint与production build通过;16个Agent package tests通过;三份真实工作簿opt-in测试另行显式运行通过。
- 未放行:真实Parsing Agent Provider、AgentBus worker、PMS/Opera/OHIP、付款与部门流转。