# 前端字段控件修改说明

## 给信息系统 / Adapter / Frontend Codex 的实施任务

日期：2026-07-12  
适用范围：任务卡展示、人工复核编辑、字段校验和同卡解阻  
不适用范围：Prompt、Skill、业务 references、MCP Server、Gateway、公开 JSON 业务规则重设计

---

## 0. 先读这些文件

请先从当前工作区根目录读取以下文件，再开始修改：

1. `prompt_skill_architecture_optimization_2026-07-12/README.md`
2. `prompt_skill_architecture_optimization_2026-07-12/01_PLAN/compatibility_invariants.md`
3. `prompt_skill_architecture_optimization_2026-07-12/03_VALIDATION/draft_validation_2026-07-12.md`
4. `outputs/黄哥codex读 2/README_先读_交给Codex.md`
5. `outputs/黄哥codex读 2/04_Adapter_Frontend_保持P0.1_40路由/任务卡前端字段变更与路由说明_3.0_to_current.md`
6. `outputs/黄哥codex读 2/04_Adapter_Frontend_保持P0.1_40路由/任务卡前端字段变更说明_3.0_to_当前版_2026-07-11.xlsx`
7. `prompt_skill_architecture_optimization_2026-07-12/02_DRAFT/working/skills/booking-desk-event/references/00-output-contract.md`
8. `prompt_skill_architecture_optimization_2026-07-12/02_DRAFT/working/skills/booking-desk-event/references/90-manual-review.md`
9. `prompt_skill_architecture_optimization_2026-07-12/02_DRAFT/working/skills/booking-desk-event/references/16-trace-notes.md`
10. `prompt_skill_architecture_optimization_2026-07-12/02_DRAFT/working/skills/booking-desk-event/references/31-allotment-control-block.md`
11. `prompt_skill_architecture_optimization_2026-07-12/02_DRAFT/working/skills/booking-desk-event/references/50-room-type-mapping.md`
12. `prompt_skill_architecture_optimization_2026-07-12/02_DRAFT/working/skills/booking-desk-event/references/51-rate-code.md`
13. `prompt_skill_architecture_optimization_2026-07-12/02_DRAFT/working/skills/booking-desk-event/references/52-fix-charge.md`

旧文件 `任务卡前端展示字段表 3.0(1).xlsx` 只作为历史基线，不得作为当前字段、路由和枚举的唯一来源。

如果上述交接文件或实际 Adapter/Frontend 源码不在当前工作区，请停止代码修改并报告缺失路径；不要根据旧 Excel 猜测当前字段。

---

## 1. 任务目标

把任务卡前端从旧版“是否输入 / 是否下拉”字段说明，升级为当前项目可执行的控件注册和人工复核编辑机制：

```text
Agent final result
  → adapter 按 event 派生任务卡
  → manual_review.missing_fields[] 指定可编辑字段
  → 前端展示对应控件
  → 用户修改
  → review_resolution.field_overrides[]
  → 重新校验依赖字段
  → Preflight
```

核心要求：

- 原 Agent payload 不可变。
- 用户覆盖值不得直接写回 Agent 原始 JSON。
- 不因为前端编辑而改变 `event_type`、业务 task type、task subtype 或关系语义。
- 不创建第二张 linked normal task。
- 只有同一业务卡的 `review_status` 从 `pending` 进入 `resolved` 后，才允许继续 Preflight。
- 邮件原文、附件、raw evidence、source ID、source event index 和关系索引只读。

当前项目的最新 Prompt/Skill 架构增量仍处于草案、未进入 `04_RELEASE` 状态；本任务只修改信息系统展示/编辑层，不把草案直接宣称为生产发布。

---

## 2. 修改范围

### 允许修改

- Adapter 的字段注册表 / 字段映射层。
- 任务卡展示组件和人工复核组件。
- 控件类型、编辑权限和字段校验逻辑。
- `review_status` / `review_resolution` 的前端交互。
- Adapter/Frontend 单元测试、契约测试和验收用例。
- 当前字段交接 MD/Excel 的控件列和实现说明。

### 不得修改

- `prompts/`、`skills/`、`booking-desk-event` Skill 业务裁决逻辑。
- 公开业务 JSON 根结构和既有五字段业务根。
- S10、S99、`infrastructure_input_error` 结构。
- 40 条 Adapter 路由数量和既有 task type/subtype 语义。
- MCP 工具名、MCP payload mapping、一次提交生命周期。
- `source_event_index` 的含义。
- Parent Group / Allotment 业务本体。
- 不得在前端新增 `Note`、`Allotment Maintenance` 或旧 Parent Cancel Booking 当前路由。

如果实现过程中发现必须改变上述内容，请先报告为“契约变更”，不要在前端代码中自行绕过。

---

## 3. 前端控件类型

字段注册表至少应支持以下 `control_type`。名称可按现有代码风格调整，但语义必须保持一致：

| `control_type` | 用途 |
|---|---|
| `readonly` | Agent 结果、raw evidence、路由、关系和审计字段 |
| `text` | Group Code、Confirmation No.、备注、旧/新 Group Code |
| `textarea` | 允许覆盖的业务备注；必须保留原始证据 |
| `number` | 房量、人数、PAX、结算价、附加费金额 |
| `date` | 入住日、离店日、服务日期、取消生效日期 |
| `lookup` | 可输入并检索当前系统目标对象的组合框 |
| `select` | 固定枚举或目录选择 |
| `multiselect` | 多部门、多标签、多项业务分类 |
| `structured_table` | `before_after[]`、`room_items[]`、`fix_charge_items[]`、`trace_items[]` |
| `workflow_state` | `review_status`、Resolve/重新校验等动作 |

字段注册表还应增加：

| 配置项 | 说明 |
|---|---|
| `edit_scope` | `never`、`manual_review_only`、`workflow_only`、`system_only` |
| `options_source` | 固定契约枚举、当前 PMS 目录、Rate 配置中心、无、待冻结 |
| `write_target` | `review_resolution.field_overrides`、系统状态、无 |
| `validation_rule` | 格式、必填、目录、依赖字段和 Preflight 前置校验 |
| `raw_readonly` | 是否必须保留原始值且禁止覆盖 |

示例：

```json
{
  "field_pointer": "/extracted_fields/pms_room_type_code",
  "control_type": "select",
  "edit_scope": "manual_review_only",
  "options_source": "active_pms_room_type_catalog",
  "write_target": "review_resolution.field_overrides",
  "raw_readonly": true,
  "validation_rule": "catalog_value_exists_and_is_active"
}
```

---

## 4. 字段控件实施矩阵

### 4.1 目标、身份和 Group Code

| 字段 | 控件 | 编辑范围 | 实施要求 |
|---|---|---|---|
| `case_keys.group_code` | `lookup` | `manual_review_only` | 可输入并检索候选；校验目标存在、唯一和当前业务卡匹配 |
| `case_keys.confirmation_number` | `lookup` 或 `text` | `manual_review_only` | 不使用固定下拉；允许粘贴后执行格式/目标校验 |
| `case_keys.reservation_number` | `lookup` 或 `text` | `manual_review_only` | 与当前事件对象类型匹配后才能提交 |
| Parent `case_keys.block_code` | `readonly` | `never` | 必须与 Parent `group_code` 相等；禁止独立编辑 |
| `extracted_fields.old_group_code` | `text` | `manual_review_only` | 与新 Group Code 成对必填 |
| `extracted_fields.new_group_code` | `text` | `manual_review_only` | 必须表达 old → new 方向关系 |
| `extracted_fields.target_key` | 不再作为主控件 | — | 当前应优先使用通用 `case_keys`；旧字段只做兼容迁移 |

### 4.2 日期、房量和房型

| 字段 | 控件 | 编辑范围 | 实施要求 |
|---|---|---|---|
| `extracted_fields.arrival_date` | `date` | `manual_review_only` | 使用 `YYYY-MM-DD`；修改后重新校验离店日和晚数 |
| `extracted_fields.departure_date` | `date` | `manual_review_only` | 必须晚于入住日；保留原始日期证据 |
| `extracted_fields.nights` | `readonly` | `never` | 由入住日和离店日计算，不直接输入 |
| `extracted_fields.date_evidence.*` | `readonly` | `never` | `hotel_date_raw`、`tour_date_raw`、`action_date_raw`、`sheet_month_year` 只读 |
| `extracted_fields.room_quantity` | `number` | `manual_review_only` | 整数、非负/正数规则按现有业务字段执行 |
| `extracted_fields.child_room_items[]` | `structured_table` | `manual_review_only` | 每个 Child 的房型、房量和 PMS code 分列；禁止单行自由文本 |
| `extracted_fields.room_type_raw` | `readonly` | `never` | 原始房型文本不可被用户覆盖 |
| `extracted_fields.pms_room_type_code` | `select` | `manual_review_only` | 只能从当前有效 PMS 房型目录选择；禁止自由输入 code |

Parent 原始房量汇总与 Child 房型/房量汇总可以因分配或房型重分配而不同。前端不得仅因数量不相等显示冲突、强制修改或自动创建人工复核。

### 4.3 业务路由和分类字段

以下字段是业务识别或 Adapter 路由判别字段，默认只读：

| 字段 | 控件 | 说明 |
|---|---|---|
| `event_type` | `readonly` | 前端不允许 New / Update / Cancel 之间切换 |
| `booking_object_type` | `readonly` | FIT、Group Block、Allotment / Control Block 由业务结果确定 |
| `cancel_object_type` | `readonly` 或同路由受控 `select` | Cancel Booking 只接受 FIT/普通 Group；Allotment 整块取消属于 Cancel Allotment |
| `cancel_scope` | `readonly` 或同路由受控 `select` | 不使用自由文本；不得用前端选择跨到另一张任务卡 |
| `update_actions[]` / 旧 `update_subtypes[]` | `readonly` 标签 | 当前 Update 统一走 `update_booking_amendment`；动作由结果派生，不能用下拉改路由 |
| `voucher_subtype` | `readonly` | `lian_tai_credit_voucher` 与 `Payment Evidence` 分开，不跨卡选择 |
| `list_evidence_type` | `readonly` 或复核时受控 `select` | 不允许通过它自行创建新任务类型 |
| `trace_subtype` | `readonly` | 由 `trace_items[]` 重新判断 `extra_bed` / `general_request` |

如果 `manual_review.missing_fields[]` 明确指向同一业务卡的分类字段，才可以显示受控选择；选择结果不得自动改变 `event_type` 或 Adapter 路由，除非项目另行冻结了跨路由 resolution 契约。

### 4.4 Update 和 Before/After

`extracted_fields.before_after[]` 使用 `structured_table`：

| 子字段 | 控件 |
|---|---|
| `field` | 当前支持字段的受控选择；不得任意输入路径 |
| `before` | 只读原值/证据值 |
| `after` | 按字段类型使用日期、数字、文字或目录选择 |
| `evidence` | 只读 |

如果 Update 类型和 subtype 已确定，但 before/after 不可靠，保留原 Update 卡并进入同卡人工复核；不能把它改成 Fallback，也不能创建第二张卡。

### 4.5 Rate Code 和结算价

| 字段 | 控件 | 实施要求 |
|---|---|---|
| `extracted_fields.rate_code_result.rate_code` | 配置驱动 `select/lookup` | 不得硬编码旧 3.0 的 20+ code 全集；从当前 Rate 配置中心加载 |
| `rate_code_raw` | `readonly` | 原始价格/Rate marker 只读；路径未冻结时不要自行发明公开路径 |
| `settlement_price` | `number` | 单独编辑；校验币种、精度、非负和业务依赖 |
| `manual_settlement_price_required` | `readonly` | AI/规则派生，不让用户直接改成 true/false |
| `manual_price_reason_code` / `price_evidence` | `readonly` | 用于解释和审计，不是输入项 |

如果 Rate Code 无法唯一确定，用户应选择当前有效目录值或填写允许的手工结算价；不能让用户输入一个未经配置的任意 Rate Code。

### 4.6 Fix Charge

`fix_charge_items[]` 必须做成 `structured_table`，不能压成一行输入。

| 子字段 | 控件 | 当前边界 |
|---|---|---|
| `charge_type` | `select` | 使用当前契约枚举，如 `fixed_charge`；不要继续使用旧表 `additional_charge` |
| `pricing_mode` | `select` | 使用当前契约 `unit` 等已冻结值；旧 `unit_price` 需迁移 |
| `amount` / `quantity` / `total_amount` | `number` | 不把多个金额拼成文本；不得前端自行推导未经契约支持的总价 |
| `currency` | `select` 或配置值 | 以当前系统货币目录为准 |
| `unit_basis` | `select` 或 `text` | 若枚举未冻结，先只读或容错，不猜选项 |
| `raw_text` / `evidence_source` | `readonly` | 保留原文和证据 |
| `requires_followup_tool` / `followup_tool_name` | `readonly` | 前端不得自行调用工具 |
| `additional_operations[]` | `readonly` / pending badge | 只展示待处理意图，不执行实际写入 |

### 4.7 Cancel

| 字段 | 控件 | 实施要求 |
|---|---|---|
| `cancel_object_type` | 默认 `readonly` | Cancel Booking 只显示 FIT/Group；Allotment 使用独立 Cancel Allotment 卡 |
| `cancel_scope` | 默认 `readonly` | 不允许自由文本；部分配额维护当前不支持 |
| `requested_cancel_effective_date` | `date` | 只有 `missing_fields[]` 指定时启用 |
| `cancellation_note` | `textarea` | 允许覆盖时必须保留原始邮件证据并记录 field override |

### 4.8 Voucher、Payment 和 Invoice

| 字段 | 控件 | 实施要求 |
|---|---|---|
| `voucher_attachment` / `file_reference` | `readonly` 文件展示 | 不允许改写输入文件引用 |
| `voucher_subtype` | `readonly` | Credit Voucher 与 Payment Evidence 分开路由 |
| `department_routing[]` | `multiselect` 或只读 | 当前路径仍需以实际 schema 为准；默认 Finance/pending 只展示，不执行确认 |
| `post_confirmation_intent` | `readonly` | 只表示待确认后的意图，不表示已确认或已执行 |
| Invoice 专属字段 | 默认 `readonly` | 当前详细 item schema 尚未完全冻结，不要自造输入字段 |

### 4.9 Trace、Parent 和关系字段

| 字段 | 控件 | 实施要求 |
|---|---|---|
| `extracted_fields.trace_text` | `readonly` | 保留完整原文，不允许直接编辑 |
| `trace_items[].category` | 固定枚举 `select` | 仅在明确 pointer/权限允许时修正 |
| `trace_items[].text_raw` | `readonly` | 原始补充信息不可改 |
| `trace_items[].service_date` | `date` | 只有需要且 pointer 明确时编辑 |
| `trace_items[].pax` | `number` | 缺失时可为空；不因缺失自动人工复核 |
| `trace_items[].notify_departments[]` | `multiselect` | 已知时可选 FO/HSK；不清楚时允许空数组 |
| `related_source_event_index` | `readonly` | 单一关系索引，只用于本次结果内部关联 |
| `related_source_event_indices[]` | `readonly` | Parent 或跨 Child Trace 的完整关系；禁止用户编辑索引 |
| `relationship_type` / `related_event_type` | `readonly` | 关系类型不选择任务卡 subtype |
| `requires_downstream_hard_validation` | `readonly` badge | 只展示系统硬校验要求 |

完整 Parent split 的全部 Child 补充请求仍使用现有 Trace 卡，通过 `related_source_event_indices[]` 展示全部 Child；不能只绑定 E1，也不能新增一个 Trace 路由。

### 4.10 Rooming List 和 TA Recorder

| 字段 | 控件 | 实施要求 |
|---|---|---|
| Rooming List target | `lookup` | 以通用 `case_keys` 为主；多个目标分开处理 |
| `list_evidence_type` | 默认只读 | 由证据识别，不允许任意切换卡型 |
| TA Recorder `group_code` | `lookup` / `text` | 只有缺失且 pointer 明确时编辑 |
| `ta_recorder_status` | `readonly` / `workflow_state` | 由信息系统后续状态更新，不是 AI 字段输入 |
| `source_rooming_list_task_id` | `readonly` 或隐藏 | 仅作 linked task 上下文 |

### 4.11 Manual Review 和系统字段

| 字段 | 控件 | 实施要求 |
|---|---|---|
| `manual_review.reason_code` | `readonly` badge | 不能由用户随意改原因 |
| `manual_review.visible_reason` | `readonly` | 只读说明 |
| `manual_review.blocking_points` | `readonly` list | 只读说明 |
| `manual_review.conflicting_points` | `readonly` list | 只读说明 |
| `manual_review.suggested_human_actions` | `readonly` list | 可转成页面操作提示，但不能直接当字段输入 |
| `manual_review.evidence_to_check` | `readonly` list | 引导查看证据 |
| `manual_review.known_fields` | `readonly` | 不直接编辑对象文本 |
| `manual_review.missing_fields[]` | 内部 pointer | 驱动控件，不作为普通输入框展示 |
| `review_status` | `workflow_state` | `pending → resolved`；只能通过完成字段校验后 Resolve |
| `review_resolution` | 系统生成、只读审计 | 保存 field overrides、用户和时间，不允许页面直接覆盖历史记录 |

### 4.12 只读字段

以下字段不得提供普通编辑控件：

- `source_message`、`source_message_id`、邮件主题、发件人、接收时间。
- `message_events[].event_type`、`event_role`、`current_or_history`、`source_event_index`。
- `attachments[]`、`file_references[]`、`context_used`、QBD sheet/row/highlight/raw evidence。
- `relevant_message_excerpt`、`text_raw`、`room_type_raw`、价格 raw marker。
- `unhandled_current_intents[]` 的原文和可见说明。
- S10、S99 和 `infrastructure_input_error` 的 route/status/error 字段。

---

## 5. 必须修正的旧 3.0 字段/枚举

请不要直接复制旧 Excel 的以下定义：

1. `Cancel Booking.cancel_object_type` 不再包含 `allotment_control_block`；整块 Parent/Allotment 取消使用 `Cancel Allotment`。
2. `Voucher Received.voucher_subtype` 不再包含 `bank_transfer_slip`；银行/现金/交易回执使用 `Payment Evidence`。
3. `Update Booking.extracted_fields.update_subtypes[]` 的旧长下拉不再作为路由选择；当前 Update 统一为 `update_booking_amendment`，动作只展示为结果标签。
4. `room_type` 不可作为自由修改后的唯一值；必须保留 raw，并用 PMS 目录选择 `pms_room_type_code`。
5. Rate Code 不得硬编码旧表中的完整 code 列表。
6. `Trace Text` 不得直接编辑原文。
7. Fix Charge 的旧 `additional_charge / unit_price` 与当前 `fixed_charge / unit` 语义不一致，必须以当前契约和实际 schema 为准。
8. `target_key`、`parent_source_event_index`、`post_confirm_action` 是旧字段/旧命名，需迁移到当前 `case_keys`、`related_source_event_index(es)` 和 `post_confirmation_intent`。
9. 不得继续生成或路由 `Note`、`Allotment Maintenance`、`Cancel Booking + linked_parent_release_after_child_split`。

---

## 6. 必须通过的验收用例

至少增加或复用以下测试：

| 编号 | 场景 | 必须验证 |
|---|---|---|
| UI-01 | generic `SUITE` 房型 | raw 只读；PMS code 使用当前目录下拉；未选时保留 manual review |
| UI-02 | 入住/离店日期修改 | 日期控件有效；`nights` 自动重算；非法日期阻止 Resolve |
| UI-03 | Rate Code | 不读取旧硬编码全集；使用配置目录；手工价独立数字输入 |
| UI-04 | Fix Charge | `fixed_charge/unit` 枚举正确；金额/数量为数字；raw/evidence 只读 |
| UI-05 | Cancel 路由 | `Cancel Booking` 不出现 Allotment；Allotment 使用 Cancel Allotment |
| UI-06 | Voucher/Payment | bank slip 不可从 Voucher 卡下拉选择；Payment Evidence 单独显示 |
| UI-07 | Update | 不允许用 `update_subtypes` 下拉切换业务卡型；before/after 结构化展示 |
| UI-08 | Parent key | Parent `group_code=block_code`；用户不能单独改 block_code |
| UI-09 | Parent split 房量差异 | Parent/Child 数量不等不自动显示冲突或人工复核 |
| UI-10 | 全 Child Trace | 使用现有 Trace 卡；展示完整 `related_source_event_indices[]`；不压缩到 E1 |
| UI-11 | raw evidence | 用户编辑后 raw 原文、附件引用和原 Agent payload 不变 |
| UI-12 | 同卡解阻 | 只创建一张卡；`pending → resolved → Preflight`；不创建第二张 normal task |
| UI-13 | 未知字段路径 | pointer 无法映射时 fail closed，不能临时创建任意输入控件 |
| UI-14 | S10/S99/基础设施错误 | 全部只读，不显示业务编辑控件 |

---

## 7. 交付要求

完成后请报告：

1. 实际修改的 Adapter/Frontend 文件。
2. 新增或更新的字段注册表及控件类型。
3. `missing_fields[] → control → field_overrides[]` 的实现位置。
4. 日期、房型、Rate Code、Fix Charge、Parent/Trace 关系校验位置。
5. 测试命令和测试结果。
6. 是否保持公开 JSON、40 路由和 MCP mapping 不变。
7. 未实现字段、路径不确定项和需要产品/业务确认的事项。

如果发现当前字段路径、item schema 或 Rate/Fix Charge 枚举仍未冻结，请保留只读/容错策略并报告，不要在前端自行发明新的公开字段。

---

## 最终边界

本任务的正确结果是：

```text
信息系统可以正确展示当前业务结果
信息系统只允许修改被 manual_review pointer 指定的业务字段
用户修改可审计、可校验、可回退到同一业务卡
原始 Agent 结果和证据不被覆盖
不新增业务路由、不改变 Prompt/Skill/MCP 契约
```
