# HDLKiosk 架构设计

> 文档角色：HDLKiosk 架构方向的唯一总览。  
> 当前阶段：运行 Kernel 与海底捞业务层边界已建立；真实设备和支付仍需验收。
> 更新日期：2026-08-18

## 1. 背景

`/Users/arthur/WorkSpaceV2/kiosk` 是海底捞交互原型，不是正式代码。正式实现位于：

- 独立物料：`packages/private-materials/src/components/HDLKiosk`；
- BigSale 接入：`packages/private-materials/src/components/bigSale/templates/HDLKiosk`。

HDLKiosk 是海底捞专属物料，不天然寄生于 BigSale；但生产交易需要消费 BigSale/SalesSDK/PisellOS 的商品、订单、会员、设备和支付能力。

“独立”的目的，是控制代码耦合、运行时能力边界和测试成本，不是复制 OS 或承诺脱离 Host 独立交易。

## 2. 目标与非目标

目标：

- Quick、Barcode、Scale 三种编排复用本地 Activity Contract 和业务 Command；
- Core 不依赖 BigSale/SalesSDK 类型；
- BigSale 通过薄 Adapter 注入 Host；
- 订单业务事实始终来自 OS Projection；
- 本地处理并发、去重、迟到结果和 unknown；
- Fake Host 可确定性验证核心流程；
- 海底捞 UI 和业务变化限制在独立目录。

非目标：

- 不重构 PisellOS/SalesSDK；
- 不创建第二套订单、金额、优惠或支付 Store；
- 不建设通用 BPMN/低代码平台；
- 不支持远端 JavaScript/动态组件；
- 不用本地 fingerprint 冒充 OS revision；
- 当前不做包根导出、metadata 或跨品牌平台。

## 3. 总体架构

```mermaid
flowchart TB
  OS["PisellOS / Backend / Payment"] <--> SDK["BigSaleContext / SalesSDK / Plugins"]
  SDK <--> ADAPTER["BigSale HDLKiosk Adapter"]
  DEVICE["Scanner / Scale"] --> ADAPTER
  FAKE["Fake Host"] --> HOST
  ADAPTER --> HOST["HDLKioskHost Ports"]

  subgraph CORE["Independent HDLKiosk Material"]
    PROJ["Observed Projection"]
    CONTROLLER["Session / Device / Customer Controllers"]
    SLICE["Slices<br/>Business Contract / Private UI"]
    APP["Application Manifest"]
    DEF["Workflow<br/>Ordered Slice Array"]
    subgraph KERNEL["Headless Kernel"]
      COMPILER["Structural Workflow Compiler"]
      ACTOR["Workflow Actor"]
      COORD["Operation Coordinator"]
    end
    POLICY["HDLKiosk Workflow Policy"]
    RUNNER["HDLKiosk Transition Runner"]
    LIFECYCLE["Workflow Lifecycle"]
    OPS["runtime/operations<br/>Host Operation Handlers"]
    OP_POLICY["HDLKiosk Operation Policy<br/>Host Context / Conflict / Telemetry"]
    SAFETY["Checkout Safety"]
    REQUIREMENT["Checkout Requirement Registry"]
    VIEW["ui/views Registry<br/>ScreenRenderer"]
    UI["Slice Screens / Shared Components"]

    HOST --> PROJ
    HOST --> OPS
    PROJ --> CONTROLLER
    PROJ --> VIEW --> UI
    UI -->|"Step Resolution / Navigation"| VIEW
    VIEW --> ACTOR
    UI -->|"Screen Command"| VIEW
    VIEW --> COORD
    CONTROLLER -->|"create / reset session"| ACTOR
    SLICE --> APP
    DEF --> APP --> COMPILER --> POLICY --> ACTOR
    COMPILER --> COORD
    PROJ --> REQUIREMENT
    OPS --> REQUIREMENT
    ACTOR --> RUNNER
    APP --> RUNNER
    RUNNER -->|"local Exit Policy"| COORD --> OPS
    ACTOR --> LIFECYCLE --> HOST
    OP_POLICY -->|"inject policy"| COORD
    OP_POLICY --> SAFETY
  end
```

依赖方向：

```text
BigSale Adapter / Screens / Workflows / Business Operations
                         ↓
                    HDLKiosk Kernel

Kernel ✕ HDLKiosk contracts / BigSale / SalesSDK / merchant workflows / Screens
```

## 4. 核心分层

| 层                      | 责任                                                                 | 不负责                                        |
| ----------------------- | -------------------------------------------------------------------- | --------------------------------------------- |
| Contracts/Ports         | HDLKiosk 自有 DTO、能力和结果语义                                    | BigSale 字段兼容                              |
| Projection              | 标准化 Host 可观察事实                                               | 发业务命令                                    |
| Slice                 | 将 Screen、合法 Resolution、局部 Command、Acceptance 和 Requirement 收敛为业务能力 | 前后节点和 Host 实现              |
| Application Definition  | 汇总 Activity、Workflow、Trigger 与 Operation Contract              | Handler、React 生命周期和订单事实              |
| Application Runtime     | Trigger 路由、Admission、Session Registry 和无头启动                | 业务方法实现和 React Presentation              |
| Structural Compiler     | Step ID、相邻导航、可达性、终点、Modal 和有界循环                    | 支付和购物车策略                              |
| HDLKiosk Policy         | 编译后检查支付来源和 Checkout Prepare 等交易约束                     | 修改节点结构                                  |
| Workflow Actor          | mailbox、step/activity 防迟到、running/blocked、节点提交和循环计数   | Host、Predicate、Operation、支付解释和持久化   |
| Transition Runner       | 求值 Predicate/执行 Exit Command，将结果归一为 advance/stay/blocked  | React、节点数组位置                           |
| Operation Bindings      | 为 Contract 注入 Host Command 和写后验证                             | Screen 导航、Workflow 拓扑                     |
| Requirement Registry    | 判断支付前业务要求对当前订单是否适用，并校验 Host Projection         | Workflow 节点编排和 UI                        |
| Kernel Coordinator      | 用应用注入的 Context/Scope/Policy 处理冲突、去重、timeout 和 epoch    | 支付含义、Host、业务错误和节点目标             |
| HDLKiosk Operation Policy | 注入 Host Context、冲突矩阵、支付 freeze、错误分类和遥测            | Screen 导航                                   |
| Workflow                | 用有序 Slice 数组表达主路径，以 `on` 描述分支、合流和受限回路      | Screen 内部动作和订单事实                      |
| Controllers             | React/设备输入与 Exit Challenge 适配                                  | 创建 Actor、拥有 Runtime Session Registry      |
| View assembly           | 把 Activity 节点和 Projection 转换为组件输入，并路由 Resolution/Navigation/Command | 决定目标节点                           |
| Screens/Dialogs/Layouts | 展示、局部输入、Screen Command、Step Resolution 和 Back Navigation           | 直接调用 Host、Actor 或 Controller     |
| BigSale Adapter         | DTO 转换、callback、插件、capability                                 | 决定流程节点                                  |

## 5. Host 契约

```ts
interface HDLKioskHost {
  sales: HDLSalesPort;
  devices: HDLDevicePort;
  telemetry: HDLTelemetryPort;
  capabilities: HDLKioskCapabilities;
}
```

- Host 是内部集成契约，不是当前包级公共 API；
- optional capability 由 capability 表达；
- Host 引用在物料生命周期内稳定；
- BigSale 晚初始化 bridge 通过 provider 动态消费；
- Fake Host 实现同一接口，但不代表真实支付安全。

详细运行机制见 [01-核心运行机制.md](./01-核心运行机制.md)，其中包含 Core 模块级代码地图和四条端到端调用链；BigSale 映射见 [02-Host 适配与业务数据.md](./02-Host适配与业务数据.md)，其中逐文件说明兼容形式、解决的旧体系痛点、原始字段转换和当前缺口。

## 6. 状态与事实所有权

```text
OS：Cart / Customer / Fulfillment / Add Product Flow / Voucher / Summary / Payment / Result
Workflow：entry / active Step / local fulfillment choice / session context
Coordinator：command / conflict / epoch / checkout freeze
Device Runtime：connection / measurement
Screen：输入和展示状态
```

如果本地状态与 OS Projection 冲突，选择 OS 事实和更保守状态。Workflow context 和 React state 均不能成为业务真相。

## 7. 全局不变量

1. Core 不 import BigSale、SalesSDK、Engine plugin 或 raw tempOrder。
2. Adapter 不决定 Workflow 目标节点。
3. Screen 不直接调用 Host；内部写操作发送 Command，离开步骤发送 Step Resolution，返回发送 Navigation。
4. Activity/Slice 是 Resolution、Command 和退出策略的业务定义；Screen 可选，Operation 只引用 Contract，Handler Registry 位于 Runtime Binding。
5. Workflow 作者只排列已注册 Slice；规范化后的运行结构不得包含 Screen、Predicate、Operation 或 failureTarget。重复 Slice 必须使用 `slice:用途` 标识每次出现。
6. 只有可被业务编排者独立排序或分支的里程碑才成为节点；Dialog 内部询问、选择和等待阶段留在 Activity 内。
7. Operation 不渲染 UI，不直接切 Screen。
8. Cart/Customer/Summary/Payment 以 Host Projection 为权威。
9. 同冲突域不并发；cart 与 customer 互斥。
10. Operation 只有在写后事实收敛后才成功。
11. partialFailure、timeout、unknown 不得伪装成失败或成功。
12. Checkout opening/pending/unknown 后冻结危险写。
13. Payment pending/unknown 时不可重付或修改订单；阻断页只允许显式 `session.reset` 恢复并返回入口。
14. Shell 登录不改变 Workflow 节点，完成后必须观察最新 customer/summary。
15. OS 加购中的额外业务弹窗属于 OS，HDLKiosk 只消费加购结果。
16. Scanner/Scale 在顶层单一接入；Entry Ingress 只负责启动会话，设备入口不是 Workflow Activity；会话内的 Screen 只消费自身所需的实时快照。
17. Workflow 当前只读取本地固定 Definition，运行中的 session 不替换 Definition。
18. 原型静态数据不能进入生产业务事实。
19. capability 变化不得销毁活跃 Workflow 或订单。
20. 临时兼容只能在装配层显式开启，并有退出条件。

## 8. 三入口与共享能力

```text
Quick ───────┐
Barcode ─────┼→ Catalog / Payment / Result
Scale ───────┘
```

入口定义不同顺序，复用 Identity、Fulfillment、Customization、Catalog、Cart、Checkout 等 Screen/Operation。会员中途登录是共享 session 行为，不复制到每个 Workflow 节点。

Barcode/Scale 是外部 ingress，不放入 Step 数组。Barcode 首码先归属并激活 Session，在 Session `readyForCommands && cartWritable` 后通过 `barcode.consume` 完成；首屏类型由 Workflow Definition 决定，Scanner 不依赖 Catalog。Scale 从 Customization 开始。业务 Step 不启用本地 `beforeEnter`；Identity 的 `complete | omit` 均使用 `resolutionRouting: 'bypass'`，会话内解决后不再进入。Actor 的 `beforeEach` 管线只处理 Step 导航。历史为空时 Back 返回 Boundary，Runtime 根据 Workflow 的 Exit Policy 发布 `pendingExit`，Shell 只负责展示 Challenge。

权威节点顺序见 [03-业务流程与交互规则.md](./03-业务流程与交互规则.md)。

## 9. 安全边界

HDLKiosk 可以保证：

- 单实例事件顺序、去重、冲突串行；
- epoch 后旧结果不污染新 session；
- checkout 前一致性和 Summary 验证；
- 结果不明确时阻止危险动作；
- 本地流程可重复测试。

HDLKiosk 无法独立保证：

- 服务端幂等和跨端互斥；
- 多个 Host 调用具备事务回滚；
- 支付 timeout 的最终结果；
- 无查询 API 时重启自动对账；
- Fake Host 等价于真实 OS。

缺少底层能力时默认 fail-closed。当前批准的 fulfillment 模拟和固定称重商品 ID 是联调策略，不是生产能力；固定 ID 的商品结构必须来自 OS query，不再使用本地商品 mock。Customization 必须通过 OS 统一加购流提交，不得直接绕过 OS 业务编排。

当前不提供 checkpoint 或跨刷新恢复。会话刷新后的订单判定与支付对账由 Host/OS 负责。Kernel 保留两类扩展位，但不包含具体恢复策略：

- `WorkflowLifecycle` 可由外层组合 telemetry、审计或持久化观察器；
- Actor 可由组合根显式传入初始节点、上下文和阻断错误。

以后加入恢复能力时，应在 Kernel 外读取 OS 事实和持久化证据、形成初始化决策，再创建 Actor；不得让 Kernel 依赖存储实现或海底捞恢复规则。

## 10. 代码结构

```text
components/HDLKiosk/
├── kernel/           # Application / Workflow / Operation 通用执行原语
├── app/              # HDLKiosk Contracts、Manifest、Workflow 与 Operation Contract
│   ├── contracts/    # DTO / Ports / Config / Result / Error
│   └── workflow/     # Quick / Barcode / Scale + registry / guards / policy
├── runtime/          # 可脱离 React 的 Host Handler、Trigger、Devices 与 Session
│   ├── operations/   # HDLKiosk 业务 Operation 与安全策略
│   ├── devices/      # Scanner/Scale ingress、去重与 Scale Store
│   └── session/      # Session / Actor / Context / Lifecycle 组合
├── ui/               # React View Registry、Entry、Controller 与订阅 hooks
├── slices/           # 业务纵向切片：slice + operation + view + Screen/Dialog
├── components/       # 只承载跨 Slice 共享 UI 与样式
│   ├── shell/        # Shell / Header / BottomBarHost / FloatingBar
│   ├── overlays/     # CartDrawer / 会话 Dialog / CompensatedPisellContainer 统一壳
│   └── common/       # 跨 Slice 视觉控件与 BlockingNotice
├── testing/         # Fake Host / Fixtures
├── types.ts         # 公共 Props、Action、ViewModel 与 Slice View Context
├── utils.ts         # 跨 Slice 共享的纯方法和错误呈现
├── index.tsx        # 物料组合根，只负责 provider/session/entry
└── index.less       # 基础作用域与组件样式的确定性聚合顺序

bigSale/templates/HDLKiosk/
├── index.tsx        # assembly
├── constants.ts     # explicit temporary switches
└── adapter/         # Host implementation and plugin bridges
```

`HDLKioskBottomBarHost` 是 Shell 内唯一的底部操作区挂载点。当前 Screen
根据自己的实时状态声明 `leading / summary / trailing`，Host 负责替换声明并统一
渲染 `HDLKioskFloatingBar`；没有声明时不展示底栏，不再存在 `hdl-shell__footer`
回退。`HDLKioskOrderSummary` 将购物车数量、Host 确认金额和 Drawer 入口收敛为可组合的
`summary` slot，Screen 按当前订单事实决定是否展示，而不依赖节点在 Workflow 中的固定位置。
CartDrawer 同样由该 Host 挂载，内容只消费标准订单投影，因此不会让 Shell 依赖 Catalog、称重或
BigSale 的业务结构。

生命周期边界由 Runtime Exit Protocol 持有。Payment Completed 在 Checkout Screen 内展示支付结果并于 10 秒后调用 `completeOrder`；订单清理、安全校验和 session epoch 由 HDLKiosk Runtime 与 Session 持有。

## 11. 反过度设计边界

当前不增加：

- 通用事件总线；
- 通用 Modal 编排 DSL；
- 通用插件发现系统；
- 新状态管理库或 XState；
- 远端 Workflow/动态 Screen；
- 本地 pricing/discount engine；
- 前端事务补偿框架。

只有出现至少三个稳定复用场景、当前抽象已造成明确维护成本时，才扩展通用机制。

## 12. 变更控制

以下变化先改本文再改代码：

- 改变 Core/Adapter 依赖方向；
- 新增 Port、业务事实或 conflict scope；
- 修改 Checkout/Payment 安全语义；
- 改变 Kernel 依赖边界或生命周期扩展方式；
- 修改三入口共享边界；
- 开启远端 Workflow；
- 引入新的状态或工作流库；
- 新增包根导出、metadata 或跨品牌能力。

普通业务页面、文案和视觉变化更新对应主题文档即可。

## 13. 后续开发入口

- 当前状态：[实施进度.md](./实施进度.md)
- 业务和 UI：[03-业务流程与交互规则.md](./03-业务流程与交互规则.md)
- 交易安全：[05-交易安全.md](./05-交易安全.md)
- 质量门禁：[06-测试与验收.md](./06-测试与验收.md)
- 未完成事项：[07-后续工作.md](./07-后续工作.md)
