ek-ui 0.9.27

ek 生态常驻主界面(egui/eframe):插件即界面——观测页 + 日志页,车头与 UI 同插件
Documentation
# 插件即 App(每插件自带配置与界面)——方案 · 分解 · 测试 · 验收

**底本**(2026-10-28 定):Python 版形态 = 每个 app 有 `engine.py`(功能码)+ `ui/widget.py`
(自带配置/操作界面),全局配置住在 `trader/setting.py` 读一份 `setting.toml`
(mode / dev / prod 密钥面 / 风控 / 品种时段)。跑无界面 = 只起 engine;跑有界面 = 按 app 挂 widget。

**我们的对应**:插件 = App;档案 = 唯一持久源(`%APPDATA%\ek\cfg\<ns>.ini`,
ek-cfg 单源 + 受理面显形);有界面时 ek-ui 把**已装配插件**的自带面挂出来;
无界面时那些界面码**根本不进进程**(feature 门控,零依赖零开销)。

---

## 1. 盘点(参数在哪、受理面有没有、界面有没有)

| 插件 | 参数面(现值) | `Configurable` 受理面 | 自带界面 | 本轮动作 |
|---|---|---|---|---|
| ek-ctp | `ctp.<网关>` 段(前置/账号/AppID/授权码/密库引用/收录面) | ✅ v0.10 起 | ✅ 账户面板(**先例**) | 并入统一挂载表,逻辑零改 |
| ek-oms | `oms` 段:`seed_cadence_ms` / `valid_for_ms` / `parent_cap` | ✅ | ❌ | 补界面(参数 + 管线状态读数) |
| ek-tq | `tq` 段:桥参数 / 账号 / 节流 / 收录范围 / 心跳 | ✅ | ❌ | 补界面(桥状态 + 启停 + 节流 + 收录范围) |
| ek-dm | 构造期 `DmConfig{intervals:[60], size:Option}` —— **现在改不了** | ❌ | ❌ | 补受理面(ns `dm`)+ 界面(周期表/数组长度 + symbols/reload) |
| ek-risk | 装配期 `RiskLimits{单笔/单合约净持仓/价格带/合约预检/名义额}` —— **现在改不了** | ❌ | ❌ | 补受理面(ns `risk`)+ 限额可变面 + 界面(五限额 + 跳过计数) |
| ek-converter | 纯库(住在 oms 管线里的成员对象),**无插件身份** | n/a | n/a | 参数归 `oms` 段(拆单/冻结口径),不单开插件面 |
| ek-ui | `ui` 段:theme + `auto_connect.<网关>` 勾 | 自持(唯一写手) | ✅ | 不动 |

关键可行性核过:
- **回灌不用改 station**:`cfgload` 遍历 `plugin.as_configurable()` → dm/risk 一旦实现
  `Configurable`,boot 与 svctl.start 两条路**自动吃到**(既有判据 `t1..t8` 钉着这条机制)。
- **界面码进插件不产生依赖环**:界面 fn 签名 `render(ctx: &egui::Context, 实例, host: &dyn CfgHost)`,
  `CfgHost` 契约放 **ek-core**(object-safe、零 egui 依赖,只有 ask/save/log 三件),
  ek-ui 实现它 → 依赖方向 ek-ui→插件→ek-core,无环。
- **发布包零膨胀**:插件的 `ui` 特性缺省关,默认面不依赖 egui(ek-dm/ek-risk/ek-tq/ek-oms 保持纯逻辑)。
- **限额/周期改在运行期**:ek-risk 的 `RiskLimits` 进 `Arc<RwLock<_>>`(每次 check 读锁,
  微秒级);ek-dm 的 intervals 变更 = 订阅表重建(`ReloadReq`/`SymbolsReq` 服务已在,Python 版 widget 的 reload 钮同形)。

## 2. 分解(六段,每段有门禁与判据)

**P1 ek-core 0.5.1(契约加项,全体 additive)**
- `cfg_face::CfgHost`:`ask_cfg_save(ns,map)` / `ask_cfg_list()` / `log(line)` / `ask_service(target,payload)`;
- `ConfigSchema` 元数据:`{key, kind(int|float|bool|text|csv|secret), label, unit, range, default, 可改性}`;
  `Configurable::config_schema()` 缺省空;`config_view()`(当前值 + 档位);
- 判据:schema 形态钉 + 缺省空 + 老插件零负担(缺省走 `vec![]`)。

**P2 受理面补齐**
- `ek-dm`:ns `dm`(`intervals` 逗号秒表 / `size` 0=不限)+ 校验(周期必须正、去重、上限)+ `dm.symbols` 只读口;
- `ek-risk`:ns `risk`(五限额 + `require_contract`/`price_band` 开关)+ 限额运行期可改 + 受理显形拒(负数/NaN);
- 判据:apply/dump 往返、坏值拒、`config_schema` 与字段表一致、回灌链(station 侧新钉:dm/risk 段在 → 装配后读数变)。

**P3 插件自带界面(feature `ui` 门控,逐插件)**
- `ek-dm::ui`:周期表(增删)+ 数组长度 + 当前订阅/窗读数 + 『符号表』『重载』钮(走服务);
- `ek-risk::ui`:五限额编辑 + 闸开关 + 逐闸跳过/拒绝计数;
- `ek-oms::ui`:三参数 + 管线状态口读数(复用 `SVC_PIPELINE_STATUS`);
- `ek-tq::ui`:桥参数 + 心跳/节流 + 收录范围(`include_products`/`exclude_warehouses`)+ 桥启停;
- 判据:kittest 逐面(语义树在场/编辑/保存后临时根里段可见/坏值显形拒),假 host 写临时根,**绝不碰真库**。

**P4 ek-ui 挂载与档案包**
- `ui_kinds` 表:工厂名 → 自带面;菜单「插件配置」逐项开窗(**按已装配清单**,没装的插件不开窗);
- 账户面板并入同一挂载表(ek-ctp 面即账户面板,先例改口径不改逻辑);
- **导出档案包** = cfg 目录 + 校验清单(逐段带 ns/rev/键数,密码值不在包里,只有引用行);
  **导入** = 逐段过受理面(坏段显形拒,不静默覆盖)+ 引导「密码走 `ekapp add-account`」;
- 判据:挂载表判据(无 ui 特性时 ek-ui 编译面零变化)、导出/导入往返钉、导入坏段拒钉。

**P5 链上出版波**:ek-core 0.5.1 → ek-dm/ek-risk/ek-oms/ek-tq/ek-ctp 随链同抬 →
ek-station 0.4.x → ek-ui 0.9.x → 台表 + pin 波 + 装版面 + 安装器重出 + SHA256。

**P6 两面综合实测(您定的口径)**
- **时段选具**:交易时段吃**在交易的品种**(日盘 09:00–15:00 / 夜盘 21:00–02:30 活跃品种),
  非交易时段吃 **24 小时那套**(SimNow 全时段);柜台前置吃 `ek-ctp/config/simnow.local.env`;
- **无界面跑**(`ek-station.exe`):守护复原按勾自动连 + 参数从档案回灌 + 无界面码零存在
  (进程里不编译界面码);
- **有界面跑**(`ekapp.exe`):启动清点 → 手点连接 → 插件参数改 → 持久 → **重启读回**
  → 自动连接勾 → 守护接手;
- 每项逐判据(柜台回报到没到手、读数变化、段变化、重启读回);实连判据走
  `#[ignore]` + 双闩纪律(配置 `*.live=true` AND 环境变量 + 账号到货)。

## 3. 验收标准(做没做成,看这些)

1. 五段判据全绿(各仓 gate.ps1 strict + 新判据),链上出版成功,装版面(patch 撤 → 发布面)构建通过;
2. 装机面:`ek-station-app-setup-<ver>.exe` 装 → 起 → 五面配置可见可改 → 重启读回 → 卸载不删档案;
3. 两面实测记录(无界面/有界面各一份,含时段选具说明与逐项判据结果);
4. 参数改了**不重启也生效**(risk 限额 / dm 周期 / oms 节流 / tq 收录范围)——显形证据行;
5. 终审报告:实现面 + 判据面 + 遗漏/重复/多余/逻辑问题 + 是否动了不该动的 + DESIGN/CHANGELOG 记档。

## 4. 风险与对策

| 风险 | 对策 |
|---|---|
| ek-risk 限额运行期改 → 与在途委托的一致性 | 受理即生效只作用于**新委托**(在途单不回改,报告里写明这条口径) |
| dm intervals 改 → 订阅表重建瞬间丢帧 | 走 `ReloadReq` 服务(Python 版 reload 同形),重建期读数显形「重载中」 |
| 界面码进插件 → 依赖膨胀 | `ui` 特性缺省关;发布包判据钉:默认面 `cargo tree` 无 egui |
| 两份 ek-core = 运行时静默断(老判据) | 整链同抬波 + 链上台表逐字钉 |
| 无界面机没密码 | 档案只有引用行;密码必须走该机 `ekapp add-account`(密库跟机器走)——首启说明已写 |