# Shared Module Rules

## 范围与职责

适用于 `src/host/shared/`。

为 Host 半区与 Client 半区提供**同一份**契约来源：

- 共享的形状（图模型、持久化文档、模板、元参数）；
- 共享的跨层常量（端点名、工具名与可见性、状态枚举、口径常量）。

判断归属：该修改是否同时约束 Host 与 Client 两端的契约？只影响一端的实现细节，应放到对应半区，而不是共享层。

## 纯度契约

共享层必须保持「可被两端零风险引用」：

- **禁止运行时 import**：不得引入任何模块的运行时值（避免双 tsconfig 的 Context augmentation 相互污染）；
- **允许 `import type`**：类型引用编译期完全擦除，不构成运行时依赖；
- **形状文件不得定义运行时值**：运行时值只允许出现在协议常量文件中，并必须是无运行时依赖的字面量常量；
- 不得在共享层定义全局可变状态、单例、副作用或环境依赖。

## 契约一致性

- 协议层枚举/取值域与类型层联合必须**双向穷尽**：任一侧增删取值时两侧同步，并由编译期断言锁定（类型 ⊆ 常量 ∧ 常量 ⊆ 类型）。
- **禁止用固定长度或固定列表断言代替穷尽断言**：固定列表会把漂移锁死，而不是发现漂移。
- 形状必须与真实写入/读取对齐：持久化层或客户端实际写入的字段（如时间戳）必须在本层声明，不得依赖调用方 `as` 断言补形状。

## 契约路径稳定

- 对外契约的 import 说明符属于公共契约：内部按职责拆分时，必须保留既有路径（通过 type-only barrel 再导出），不得要求调用方改 import。
- 新增契约优先落在语义最贴近的现有职责文件；仅为「文件数好看」新增聚合文件是被禁止的。

## 兼容性

- 字段增删必须说明旧数据与旧客户端的读取行为：新增字段默认可选，删除/改义必须给出兼容路径。
- 已退役字段只保留**读取兼容**语义，禁止新增写入，也必须说明何时被剥除。

## 核心原则
1. 契约单一来源，禁止双份维护。
2. 形状与逻辑分离，共享层不含行为。
3. 零运行时依赖；`import type` 优先。
4. 枚举双向穷尽，禁止固定列表断言。
5. 契约路径稳定，内部拆分不外溢。
6. 兼容优先于整洁，退役字段只读。
