# dsh-isolation-box 原理说明（PRINCIPLE.md）

> 一句话：**隔离箱不修 bug，它保证「调试 bug 的过程」不把宿主炸掉、不把正式环境搞坏。**

---

## 一、要解决的问题

调试 DSH 插件时，插件崩溃/试运行验证，最怕三件事：

1. **宿主被带崩**：插件异常/死循环/吃光内存 → 拖垮 DSH 本体 → 你连界面都打不开
2. **坏代码污染正式区**：没验证过的代码写进正式插件目录，重启后全环境崩
3. **验证 ≠ 生产**：测试环境通过、实际安装却崩（依赖缺失/命名错误/App 对账）——信息不对等

## 二、核心洞察（凭什么成立）

在一台**无法使用内核沙箱**的受限容器环境上（unshare/chroot/docker 全被系统禁），仍然可以做到**崩溃隔离**，因为：

> **崩溃本质是「进程属性」，不是「环境属性」**：实例进程崩了/挂了/被 OOM，信号传播天然不跨进程——不需要 namespace，只要**实例是独立进程**，宿主就安然无恙。

配套三类原语（全部实测可用）：
- **rlimit 硬上限**（内存/CPU/核数）——资源失控被约束在实例内
- **心跳 + 看门狗**——死循环/挂死由宿主定时器强杀（进程组 SIGKILL）
- **指数退避重启 + 熔断**——崩了自动试，连崩 3 次止损等人工

## 三、架构

```
┌─ 宿主 supervisor（独立进程，永不崩）────────────────┐
│  spawn(实例, rlimit注入) · 心跳看门狗 · 进程组强杀     │
│  退避重启 · 熔断 · 崩溃取证(stderr+退出码+状态文件)    │
└─────┬──────────────┬──────────────┬────────────┘
      ▼              ▼              ▼
  实例 A           实例 B           实例 C     ← 崩了只死自己，看门狗重启
  每实例独立目录：work/ task.json state.json stderr.log result.json
```

**通信零依赖**：文件 + 信号（心跳=时间戳，任务=文件，唤醒=SIGUSR1）——不依赖任何 API/网络服务。

## 四、为什么会比「一次性试跑」强

| 机制 | 原理 | 防什么 |
|---|---|---|
| 进程隔离 | 信号/资源不跨进程 | 宿主永不随插件崩 |
| 看门狗+熔断 | 心跳超时→强杀；连崩3次→停 | 死循环/内存泄漏/重启风暴 |
| 冒烟验收（approve） | 在实例中模拟加载+初始化 | 坏插件进不了正式区 |
| 快照注入 | 聊天记录/思考链按需注入 | 上下文等价 + 可回放 |
| 环境等价 | 实例与宿主同文件系统/运行时（实测 diff 一致） | 试跑结果可信 |

## 五、发布预检（为什么「验证通过=生产稳」）

实战教训（cosmokit 依赖崩、命名错乱、产物忘换）转化为**五道强制预检**，内嵌在发布唯一入口 `dsh_tool.py publish`：

```
① 顶层目录名 == 包名        ← App 按顶层目录名注册
② 依赖闭包（实体文件在包内） ← App 解压后无软链依赖
③ dsh.bundle.patch 声明完整
④ 客户端产物指纹（目标特征）
⑤ 动态 boot 预演           ← 模拟 App 解压语义 → 真实 boot → 就绪检测
```

**任何一道不过 = 禁发**；全部通过才产出可导入包。加上测试实例实测（真机 UI 验证），把「导入后才发现问题」提前到发布前。

## 六、诚实边界

- **防 bug，不防恶意**：**可以测试陌生人代码**——实例是独立进程，崩溃/死循环不跨进程传染；但实例与宿主同 uid 0（无权限隔离，系统实测），恶意代码理论可越界读写全盘，测不可信代码请自行评估风险
- **App 私有清单**：DSHA 应用是主实例插件唯一权威（导入注册在它手里），导入那一步不可被任何工具替代——但我们保证「导入前」所有炸弹已拆完
- **验证深度**：静态检查 + boot 预演 + 实例实测 + **真机交互验证**（点开菜单/拖动等）缺一不可——只看「界面正常」会漏

## 七、一句话总结

> **隔离箱 = 用「进程边界」接住调试的崩溃，用「五道预检」拦住生产的错误，用「熔断与回滚」兜住所有的意外——宿主永远先活着，插件永远轻装出发。**
