Complete the selective V2 checkpoint with its minimal AgentBus, object-storage, replay persistence, and validated-workbench shared dependency closure.
15 KiB
M012 / QBD+LianTai Parser 输出冻结契约 v1
| 项 | 内容 |
|---|---|
| 状态 | FROZEN — USER CONFIRMED;PARSER IMPLEMENTED;REAL-SAMPLE CORRECTIONS ACCEPTED |
| 日期 | 2026-08-11 |
| 契约名称 | fixed-channel-parser-fact-material-v1 |
| 适用渠道 | QBD、LianTai |
| 不在范围 | 其他 sender、Parsing Agent 完整输出 schema、Rate/Room、TaskCard、PMS/Opera |
| 变更规则 | 冻结后只能通过新 ADR 和新 contract version 修改 |
1. 给业务人员看的结论
Parser 每次处理一份工作簿,只交付:
- 本次处理是否正常完成;
- 程序已经确认的业务信息;
- 程序看到了、应该继续处理、但无法确认的原文。
程序不再输出“缺失、未解决、歧义、冲突、原因代码”等分类。
2. 顶层输出
{
"meta": {},
"status": "SUCCESS",
"facts": [],
"agent_materials": []
}
| 字段 | 必填 | 业务含义 |
|---|---|---|
meta |
是 | 来源文件、渠道 Profile 和版本等追踪信息 |
status |
是 | SUCCESS 或 FAILED |
facts |
是 | 已经形成唯一确定值的事实,允许空数组 |
agent_materials |
是 | 需要继续处理的原始材料,允许空数组 |
业务结果只有 facts 和 agent_materials 两类。meta/status 只是运行外壳。
3. meta 冻结字段
{
"parser_result_id": "pr_xxx",
"source_message_id": "msg_xxx",
"attachment_id": "att_xxx",
"attachment_content_hash": "sha256:...",
"file_name": "QBD月表.xlsx",
"profile_code": "QBD",
"contract_version": "fixed-channel-parser-fact-material-v1",
"parser_version": "1.0.0",
"profile_version": "1.0.0",
"rule_bundle_version": "1.0.0"
}
profile_code v1 只允许:
QBD
LIANTAI
文件名只用于描述和审计,不参与渠道业务判断。
4. facts[] 冻结字段
{
"fact_id": "fact_xxx",
"fact_key": "target_1/room_1/SOURCE_ROOM_NAME/CURRENT",
"target_ref": {
"target_id": "target_1",
"row_unit_id": "row_12",
"segment_id": "segment_1",
"room_item_id": "room_1"
},
"semantic_role": "SOURCE_ROOM_NAME",
"material_state": "CURRENT",
"value_type": "STRING",
"raw_value": "ONE-BEDROOM-SUITE TWN BF(Q10)",
"normalized_value": "ONE-BEDROOM-SUITE TWN BF(Q10)",
"source_locations": [],
"rule_ref": "shared-source-room-name-v1"
}
| 字段 | 必填 | 说明 |
|---|---|---|
fact_id |
是 | 本条事实的稳定唯一 ID |
fact_key |
是 | 合并时识别同一事实槽位的稳定键;由 target、role、state 构成 |
target_ref |
是 | 事实属于哪一业务行、住宿段和房型项;不适用的下级 ID 为 null |
semantic_role |
是 | 本契约允许的业务事实类型 |
material_state |
是 | CURRENT、BEFORE 或 AFTER;fact 不允许 MIXED |
value_type |
是 | STRING / INTEGER / DECIMAL / DATE / BOOLEAN / JSON |
raw_value |
否 | 来源中的原始值;确定性默认值允许为 null |
normalized_value |
是 | Parser 依据冻结规则形成的唯一规范值 |
source_locations |
是 | 一个或多个可复核来源位置,不允许空 |
rule_ref |
是 | 形成该事实的确定性规则引用;不是失败原因代码 |
facts 内不存在独立的状态、缺失标志或 reason code。fact 存在本身就表示该值已确定。
5. 冻结的十类业务事实
semantic_role |
给业务人员的含义 | v1 规则摘要 |
|---|---|---|
GROUP_CODE |
团号/预订目标代码 | 统一承接 Tour Code、Group Code 等已确认来源别名 |
SOURCE_ACTION_DATE |
来源动作指令日期 | 只表示表格指令写出的日期,不是处理时间或入住日期 |
SOURCE_ACTION_KIND |
来源动作类型 | 规范值只允许 NEW_BOOKING / UPDATE_BOOKING / CANCEL_BOOKING;原始细分文字保存在 raw_value |
ARRIVAL_DATE |
入住日期 | 必须由当前材料和 Profile 日期规则唯一确定 |
DEPARTURE_DATE |
离店日期 | 必须由当前材料和 Profile 日期规则唯一确定 |
NIGHTS |
晚数 | 入住、离店均确定后按日期差确定;不跨住宿段累加 |
SOURCE_ROOM_NAME |
完整来源房型名称 | 保留 BF、Q10、FAM/PAX、床型、景观等来源含义 |
BREAKFAST_INCLUDED |
来源明确声明的早餐条件 | 独立 BF=true;明确 RO/不含早=false;未声明时不生成该事实 |
ROOM_QUANTITY |
房间数量 | 明写数量按原文;Profile 已冻结的“缺数量默认 1”可生成事实并保留 rule ref |
SOURCE_PRICE |
来源价格 | 只有来源价格存在且能按冻结规则唯一规范化时生成 |
以下内容不属于 Parser v1 公共事实:
GROUP_IN
SOURCE_RATE_CODE
ROOM_QUALIFIERS
BOOKING_TYPE
canonical Room / Rate Code
Allotment source/actual relationship
最终业务事件
Trace / 普通备注的最终业务处置
TaskCard / 部门 / PMS或Opera执行状态
6. 完整来源房型名称、BF 与 Q10
6.1 不拆 Q10
原文:
ONE-BEDROOM-SUITE TWN BF(Q10)
正确输出:
SOURCE_ROOM_NAME = ONE-BEDROOM-SUITE TWN BF(Q10)
BREAKFAST_INCLUDED = true
错误输出:
SOURCE_ROOM_NAME = ONE-BEDROOM-SUITE TWN
ROOM_QUALIFIERS = Q10
6.2 允许的规范化
raw_value 保留准确来源文本。normalized_value 可以统一大小写、重复空格和无业务含义的连字符差异,
但不能删除或拆分 BF、Q10、ONE/TWO-BEDROOM、DBL/TWN/TRP、FAM/PAX、U、GARDEN/POOL/VIEW
等业务区分项。
若数量或价格与房型名称紧邻,只有在 Profile 规则能唯一证明它们分别属于数量/价格时才允许拆出; 拆出后仍不得破坏完整来源房型名称中的 BF/Q10 语义。
6.3 早餐
- 出现独立
BF标记:BREAKFAST_INCLUDED = true。 - 出现明确
RO或“不含早”:BREAKFAST_INCLUDED = false。 - 两者均未出现:不生成
BREAKFAST_INCLUDED,不得把未声明解释为不含早。 Q10与早餐判断无关。- 输出早餐布尔值时,不能从
SOURCE_ROOM_NAME中删除BF。 - 公共字段结构仍为 v1;本次语义通过
shared-breakfast-explicit-token-v2规则引用版本化,不新增字段。
7. agent_materials[] 冻结字段
{
"material_id": "material_xxx",
"target_ref": {
"target_id": "target_1",
"row_unit_id": "row_12",
"segment_id": "segment_1",
"room_item_id": "room_1"
},
"expected_fact_keys": [
"target_1/room_1/SOURCE_PRICE/CURRENT"
],
"material_state": "CURRENT",
"material_kind": "WORKBOOK_TEXT_SPAN",
"raw_content": "【U-DBL1.2/1.3】",
"context": {
"header": "房型及价格",
"neighboring_cells": ["2间", "含早"]
},
"source_locations": []
}
| 字段 | 必填 | 说明 |
|---|---|---|
material_id |
是 | 待处理材料的稳定唯一 ID |
target_ref |
否 | 能安全定位所属目标时填写;不能猜测 |
expected_fact_keys |
是 | 已知待解决事实槽位时填写;整表兜底时允许空数组 |
material_state |
是 | CURRENT / BEFORE / AFTER / MIXED |
material_kind |
是 | ATTACHMENT / SHEET / ROW / CELL / TEXT_SPAN |
raw_content |
是 | 原文、结构化单元格内容或受控附件引用 |
context |
是 | Agent 理解该材料所需的最小表头、相邻值和格式上下文;允许空对象 |
source_locations |
是 | 一个或多个准确来源位置,不允许空 |
agent_materials 不包含:
MISSING
UNRESOLVED
AMBIGUOUS
CONFLICT
reason_code
每个 material 应尽量对应一个待决事实问题;可以带更宽的只读上下文,但不能成为无边界原文垃圾桶。
8. 共用来源位置
{
"attachment_id": "att_xxx",
"sheet_name": "2026.08",
"row_number": 12,
"cell_ref": "F12",
"text_start": 0,
"text_end": 15,
"formatting_signature": "fill:#FFFF00",
"content_hash": "sha256:..."
}
不适用的细粒度位置字段可为 null,但 attachment ID、content hash 和能够达到的最精确位置必须存在。
不得在结果中嵌入附件 URL、Secret 或附件二进制/Base64。
9. 唯一判断规则
Parser 按事实槽位判断,不按整行或整格一刀切:
- 唯一规范值成立:输出 fact。
- 有原文但不能唯一确定:不输出该 fact;输出 agent material。
- 来源中完全没有该内容:fact/material 都不输出。
- 同槽位多个来源给出相同规范值:输出一个 fact,并保留全部来源位置。
- 同槽位存在不同规范值:不选择任何一个作为 Parser fact;保留全部相关原文为 material。
例如 【U-DBL1.2/1.3】2:若房型和数量可以唯一确认,Parser 输出
SOURCE_ROOM_NAME = U-DBL 与 ROOM_QUANTITY = 2;价格原文进入 material,不生成 SOURCE_PRICE。
10. SUCCESS / FAILED
SUCCESS
表示 Parser 正常结束且结果可信,不表示“所有字段齐全”。以下均合法:
facts有值,agent_materials为空
facts有值,agent_materials有值
facts为空,agent_materials有值
facts为空,agent_materials为空(工作簿中没有本期业务行)
能安全读取但不支持的版式、多个候选业务表或无法唯一识别的业务区域,使用 SUCCESS 并把必要的
Sheet/Row/Attachment 材料交给 Agent,不改成歧义状态。
FAILED
只用于结果无法被信任的技术失败,例如:
- 文件损坏、加密或无法安全读取;
- 文件大小/安全限制;
- Parser 未处理异常;
- 结果身份、来源定位或序列化契约无法成立。
FAILED 时 facts 必须为空,不发布部分事实。原始附件仍由外层 SourceMessage/Attachment 记录保留,
由外层流程进入失败复核或受控兜底;Parser 不伪造材料内容。
11. 合并结果边界
本契约同时冻结合并结果的两类顶层业务内容:
{
"effective_facts": [],
"review_items": []
}
- Parser facts 不可被 Agent 覆盖。
- Agent 只能基于获准的 agent material 补充候选事实。
- 同一事实键同值可以合并来源;不同值不得静默覆盖,进入 review。
- 每个 agent material 最终必须被接受事实覆盖,或进入 review,不能静默消失。
- 必需事实完全缺失时,由合并后的完整性校验产生 review,不由 Parser 伪造材料。
Parsing Agent 自身的完整输入/输出字段和 review item 的展示分类不在本 Parser 契约中冻结,后续单独确认。
12. Core 与 Profile 边界
共享 Parser Core
- 输出结构、版本和运行状态;
- fact/material 稳定 ID、事实键和 target 结构;
- “唯一值才形成事实”的门禁;
- 来源位置与上下文封装;
- 结果 schema 校验。
Core 提供一个只供 Profile 使用的原始材料入口。Profile 交入业务行、整段原文、上下文和证据位置,Core
统一生成正式 agent_materials。备注类材料固定为 CURRENT,expected_fact_keys=[],上下文固定包含
material_purpose=USER_REMARK、source_column,能取得表头时还包含 source_header。Core 必须验证材料
引用的业务行、来源消息、附件、Sheet、行号和单元格都与已登记证据一致;任一不一致时 Parser 整体
FAILED,不发布部分结果。
QBD / LianTai Profile
- 工作簿、Sheet、表头和业务行识别;
- 渠道列位、底色、rich text 和模板噪音;
- 日期、来源动作、房型、数量和价格语法;
- Profile 确定性默认规则。
Profile 允许内部临时拆分 BF、Q10、价格 token 或 QBD GROUP IN 单元格,但公共输出必须重新符合本契约;
内部字段不得泄漏成第十一类公共事实。
QBD Profile 补充规则:
WAITING 等待确认 / อักษรดำ是可选备注列,按表头文字识别,不固定为 K 列;只在核心表头行及其紧邻 上一行寻找。没有该列不影响旧模板;同一表头带出现多个候选时不得猜测,走既有附件级兜底材料;- WAITING 不参与业务行选中。只对已经选中的有色业务行读取非空单元格,每格整段原文形成一条备注材料;
空格不生成任何输出,
2300 THB等内容不得拆数字、解释为价格或生成SOURCE_PRICE; - 每个物理明细行先按完整“房型+数量”块判定状态。所有块均划线时,该行日期、晚数、房型、数量都属于
BEFORE;所有块均未划线且同一业务行已有修改前内容时都属于AFTER;没有修改前内容时仍为CURRENT。不同房型块状态不一致或单块内部混合时保持MIXED,不强行生成整行日期事实;没有房型块时 沿用整行格式判断。
LianTai Profile 补充规则:
- G、I 列完整原文及 D 列完成确定性字段提取后的残余原文,均通过上述共享入口形成备注材料;
- G 列已经唯一形成的
SOURCE_ACTION_DATE、SOURCE_ACTION_KINDfacts 继续保留,完整 G 原文可以同时 作为补充材料保留;旧内部classification_status、reason code 等状态不得进入公共结果。
13. 迁移与验收门禁
本契约冻结时,现有代码仍使用旧 FieldObservation、多状态和 Recovery Patch 模型。2026-08-11 已完成
Parser-only 迁移切片,实施状态如下:
- 已以本契约替换 QBD、LianTai 和共享入口的默认
parse公共 DTO; - 目标输出已移除旧公共状态、reason code、
GROUP_IN、SOURCE_RATE_CODE、ROOM_QUALIFIERS; - 完整来源房型名称与 BF/Q10 规则已进入双渠道共享契约测试;
- 十类 facts、部分确定、完全缺失、材料冲突、SUCCESS/FAILED 已有契约测试;
- 真实样本缺口已修正并回放通过:QBD 为 114 facts、4 条 WAITING materials,rows 118/121 的 BEFORE/AFTER 日期、晚数、房型和数量完整;LianTai AI 样板为 70 facts、6 materials,其中 G 列 5 条、 I 列 1 条。公共 DTO 与十类 fact 目录未改变;
- Parsing Agent v1.0 已由独立 ADR-009 冻结;CP4 已接通默认关闭的 runtime/merge/fake链。旧
observation/Recovery只保留在显式
parseLegacy兼容桥,尚未删除; - 本次没有启用 Provider、AgentBus Recovery、PMS、Opera 或生产功能。
14. 权威性
对 QBD/LianTai Parser 公共输出,本文件与 ADR-008 的优先级高于:
- ADR-001 的字段 Recovery 公共边界;
- ADR-007 的旧 observation/Field Recovery 兼容描述;
C03-v2Draft 的多状态 contribution core;- 旧 QBD/LianTai Parser CR 中的 observation status、reason code 和内部拆分字段。
历史文档继续保留用于说明当前代码和迁移来源,不得再作为新 Parser 输出的实现依据。