状态与历史
状态:今天已在线上运行。世界状态(
R-WSTATE-*)与世界历史(R-WHIST-*)是 Realm 的两个表面,分工不同、互相补充。
一个世界在 Realm 里留着两份持久的记录:状态,也就是此刻为真的样子;和历史,也就是发生过的事。它们不是一回事,谁也不能替代谁;一个事件会改动哪一份,由明确的规则决定。
状态是什么
| 属性 | 值 |
|---|---|
| 权威 | realm/kernel/world-state-contract.md (R-WSTATE-*) |
| 目的 | 世界的共享当前状态 |
| 范围 | 仅限持久共享范围:WORLD, ENTITY, RELATION |
| 变更方法 | 显式提交信封 |
| 故事本地控制变量 | 不在领域内 —— 它们保持在外 |
状态表达的是此刻共享的事实:一个角色在这个位置,一段关系处于这个阶段,一个实体有这些属性。状态只能通过提交信封(commit envelope)来改变。
历史是什么
| 属性 | 值 |
|---|---|
| 权威 | realm/kernel/world-history-contract.md (R-WHIST-*) |
| 目的 | 规范的事实记录 |
| 追加姿态 | 显式追加 |
| 故事追踪/原始回合日志/应用私有存档 | 不在领域历史中 |
| 每个事件的来源 | appId, sessionId, actorRefs, reason, evidenceRefs, 相关的状态/真相锚点 |
| 变更 | 仅追加;通过取代或无效化进行修正;无静默硬删除 |
历史保存的是已经发生、得到公认的记录:这一轮提交了这项变更,这个事件由这个 App 在这种运行模式下写入。它不是每个模型 token 的流水账,而是平台认可的事件的正式记录。
effectClass 决定更新哪个表面
每个提交信封声明一个 effectClass:
effectClass | 状态写入 | 历史追加 |
|---|---|---|
NONE | 否 | 否 |
STATE_ONLY | 是 | 否 |
STATE_AND_HISTORY | 是 | 是 |
客户端不能自己发明新的变更类别。这个封闭枚举本身就是约定。
运行模式授权
状态写入需要显式的 App 授权,按一张 (appId, schemaId, schemaVersion, effectClass) -> runMode 矩阵核对,并经过严格的 schema 校验。缺 schema 字段、不认识的 scope、无法验证的来源、未授权的运行模式,都会让这次提交被拒绝。
历史追加约束:
| 规则 | 值 |
|---|---|
REPLAY 运行不得追加共享世界历史 | R-WHIST-004 |
只有由矩阵授权的 CANON_MUTATION 行可以追加 | R-WHIST-004 |
| 应用私有叙述存档 | 应用所有,不是领域历史 (R-WHIST-006) |
为什么要有两个表面
如果状态吞掉历史:
- “这个实体以前到过别的位置吗?”将无法回答
- 审计、重放、重建都做不到
- 用静默覆盖来修正,等于开后门丢掉真相
如果历史吞掉状态:
- “这个实体现在在哪?”每次读取都要从过去的事件流里重建
- App 每次读取都要付出没有上限的代价
- 并发追加相互竞争时,“现在”会变得含糊
两份表面,一套真相模型。每个事件都通过 effectClass 显式声明自己影响哪一份。
读者场景:一个 STATE_ONLY 变更
一个应用写入了一个没有历史意义的瞬态世界状态更新。
- 提交信封。 应用提交
effectClass: STATE_ONLY。 - 领域验证。 模式、来源、运行模式授权都通过。
- 状态更新。 世界当前状态反映了变化。
- 历史不变。 没有追加历史行;变更是状态性的但不是历史性的。
读者场景:一个 STATE_AND_HISTORY 变更
一个应用写入了一个具有规范意义的变更。
- 提交信封。
effectClass: STATE_AND_HISTORY。 - 领域验证。 同样的检查;此外还检查运行模式是否授权历史追加 (
CANON_MUTATION)。 - 状态更新。 世界当前状态反映了变化。
- 历史追加。 一个新的带有完整来源的历史行被追加。
- 未来的重放或修正可以引用这一行。
读者场景:一个修正
一个较早的历史行需要被修正。
- 无静默硬删除。 原始行保留;修正是通过取代或无效化事件建模的。
- 追加一个修正事件。 新事件引用先前的行并解释取代。
- 历史保持仅追加。 审查者可以看到原始行和修正行;真相链保持完整。
仅追加不变性使得历史成为一个可靠的多年审计表面。
读者场景:一个重放 consumer 尝试写入历史
一个重放 consumer 试图在重放期间追加历史。
- 重放执行。 在
REPLAY模式下重新推导变更。 - 追加被阻止。 根据
R-WHIST-004,REPLAY运行不得追加共享历史。 - 状态写入可以继续 如果运行模式授权(根据矩阵);历史不会被复制。
- 审计反映 重放路径;领域历史保持不变。
读者场景:一个应用需要自己的叙述存档
一个应用需要其自己的每会话叙述日志。
- 领域历史不是存放的地方。 领域历史只存储规范的事实。
- 应用自有存档。 应用在其自己的所有权下存储叙述存档 (
R-WHIST-006)。 - 不作为领域历史表示。 应用不将其存档呈现为领域的规范世界历史。
状态和历史不做的事情
- 它们不会静默合并:状态不是历史;历史不是状态。
effectClass不接受额外的值。- 领域不优先考虑显式提交信封之外的隐藏写入路径。
REPLAY运行不会静默获得历史追加。- 应用私有存档不会成为领域的规范真相。
- 历史行不会被静默硬删除。
边界总结
| 关注点 | 所有者 |
|---|---|
| 共享当前状态 | 领域 (R-WSTATE-*) |
| 规范的事实 | 领域 (R-WHIST-*) |
| 提交信封权威 | 领域 (R-WSTATE-002) |
| 运行模式授权矩阵 | 领域 (R-WSTATE-005) |
effectClass 封闭枚举 | 领域 (R-WSTATE-004) |