# Workflow Kernel

`kernel/` 是放在 HDLKiosk 目录内的无 UI 运行内核。它不依赖 `HDLKioskHost`、海底捞流程、支付模型、React、BigSale 或 SalesSDK，`dependencyBoundary.test.ts` 会检查这个约束。

## 开发一套 kiosk 时使用什么

业务开发者主要使用相邻 `../app/` 层的四类 API：

```ts
const identity = defineSlice({
  id: 'identity',
  surface: { id: 'identity' },
  resolutions: {
    complete: perform(identifyCustomer),
    omit: accept(),
  },
  commands: {
    requestSmsCode,
  },
});

const activeOrderExitPolicy = defineExitPolicy({
  id: 'active-order',
  evaluate: ({ intent }) =>
    intent.kind === 'userRequest'
      ? { type: 'challenge', challenge: { kind: 'discardActiveOrder' } }
      : { type: 'allow' },
});

const order = defineWorkflow({
  id: 'merchant.order',
  exitPolicy: 'active-order',
  steps: [identity, catalog, { slice: result, isTerminal: true }],
});

const application = defineApplication({
  id: 'merchant-kiosk',
  slices: [identity, catalog, result],
  workflows: { order },
  predicates: [cartNotEmpty],
  navigationGuards: [],
  exitPolicies: [activeOrderExitPolicy],
});

// React View 在具体应用展示层按 Activity 单独注册，不进入 Kernel/Slice。
const views = {
  identity: IdentityView,
  catalog: CatalogView,
  result: ResultView,
};
```

- `defineSlice`：把业务 Activity、Screen 描述、语义出口、Screen 内 Command 和 Resolution Acceptance 放在一起；
- `accept()`：直接接受 Resolution；
- `require(predicate)`：Predicate 满足后接受 Resolution；
- `perform(operation, { require })`：Predicate 满足且 Operation 成功后接受 Resolution；
- `defineWorkflow`：数组表达默认前进顺序，`on` 只处理跳跃、分支、合流和有界回路；Back 由独立 Navigation 和页面历史处理；
- `defineApplication`：汇总 Slice、Workflow、Operation、Predicate、Navigation Guard 与 Exit Policy，并持有完整的只读应用定义。
- `createApplicationWorkflowSession`：完成 Workflow 编译、Execution Binding 与 Actor 创建；
- `createApplicationAcceptanceRunner`：统一执行 Requirement、Operation 与 epoch 校验，业务只解释 OperationResult；

Slice 的 `resolutions` 是业务活动离开 Step 时提交的结果，不是按钮或 DOM 事件。Back 使用独立 Navigation；不会离开 Screen 的动作放进 `commands`。支付门禁、设备监听、购物车写入验证等商家规则不进入 Kernel。

Slice `id` 是 Workflow 引用的业务 Activity；可选 `surface.id` 是由外层解释的稳定展示键；React View 由具体 Presentation 按 Activity 单独注册。Kernel 只复制 `surfaceId`，不理解页面类别。

Compiler 只把 `surface.id` 复制为节点的 `surfaceId`。Renderer 再按节点的 Activity 查询 Presentation View 注册表。因此远端 Workflow 只能编排 Slice，不能替换本地页面实现；Kernel 也不依赖 React。

## 目录职责

| 目录 | 负责 | 由应用注入 |
| --- | --- | --- |
| `workflow/` | 结构编译、Actor mailbox、节点提交、有界循环 | Application Workflow Environment、Transition Runner、Context Reducer |
| `application/session.ts` | 通用 Session 创建与 Acceptance 执行骨架 | Runtime Binding、OperationResult Policy、Projection、Lifecycle |
| `operations/` | 排队、冲突仲裁、intent 去重、timeout、Abort、session epoch | Context factory、错误分类、冲突规则、业务 Policy、观察器 |
| `lifecycle.ts` | 组合 Actor 提交后的只读观察器 | telemetry、审计或持久化观察器 |

Kernel Operation 只认识泛型 `Context / Error / Scope`。通用 Application 定义与运行时位于
`../app/`；HDLKiosk 再在外层 `domain/operations/types.ts` 与
`domain/operations/coordinator.ts` 注入 `HDLKioskHost`、冲突矩阵、支付冻结和遥测。

## 从定义到运行

```text
Slice/Workflow/Policy ─ defineApplication ─ Manifest ─ Workflow Environment
                                                    │
                                                ▼
                                    Structural Compiler ─ Actor
                                                │
Screen Command ───────────────────── Operation Coordinator
Step Resolution ─ Transition Runner ────────────┘
```

当前会话只在内存中运行，不包含 checkpoint 或恢复策略。需要恢复时，由应用层读取 OS 事实和持久化证据，形成 Actor 初始化输入；Kernel 只保留 Lifecycle 和初始化参数这些扩展点。

## 不要放进 Kernel 的内容

- 商家 Slice、具体 Workflow 和 Screen；
- Host Port、Sales Projection、ProductData；
- 支付 token、称重商品规则；
- BigSale Adapter、插件检测、兼容开关；
- UI 文案、错误展示和远端配置拉取。

最小独立定义见 `../app/application.test.ts`。该测试不导入任何 HDLKiosk 业务模块，并完成 Slice 收集、Operation 自动注册和 Workflow 编译。
