# Session-first 长会话研究路线

> 状态：设计基线 / 研究路线。除标注“已实现”的部分外，本文不表示功能已经可用。

## 1. 已确定的设计基线

pi-roleplay 后续研究与改进统一采用以下模型：

```text
Current Character View
  = Initial Definition
  + Current State
  + Relevant Events
  + Retrieved Memories
  + Lazy World Context
```

五层含义：

1. **Initial Definition**：角色卡、对话示例、世界核心和世界条目；Markdown canon，只读。
2. **Current State**：当前位置、关系、持有物、伤势、任务状态等当前事实；结构化快照。
3. **Event Log**：剧情中已发生的客观事件；追加式记录。
4. **Memories**：角色对事件的主观记忆、印象和情绪解释；按需检索。
5. **Lazy World Context**：由世界书关键词和预算系统在本轮动态选择的世界知识。

必须始终区分四种数据边界：

| 边界 | 用途 | 典型内容 |
|---|---|---|
| Markdown assets | 初始创作定义 | `CHARACTER.md`、`WORLD.md` |
| Pi session entries | 可恢复、可分支的剧情状态 | selection、state、event、memory |
| Runtime hooks | 本轮上下文组装 | system、动态世界书、记忆检索 |
| Provider payload | 模型最终看到的数据 | serialized messages、tools、模型适配 |

## 2. Pi Session 是系统事实来源

长期状态以 Pi 当前 branch 为准，而不是单独维护一个可变的 `state.json`：

```text
session JSONL entry tree
  └─ current branch
      ├─ pi-roleplay-selection
      ├─ pi-roleplay-current-state
      ├─ pi-roleplay-event ...
      └─ pi-roleplay-memory ...
```

原因：

- `/tree` 后两个剧情分支需要不同状态；
- `/fork` 和 `/clone` 需要继承所选节点以前的状态；
- session 恢复必须能重建插件内存；
- compaction 不应破坏结构化剧情事实；
- 不能直接修改 JSONL 文件，应通过 Pi API 追加 entry。

读取原则：

```ts
ctx.sessionManager.getBranch()
```

而不是：

```text
读取整个文件最后一行
读取全局 current-state.json
```

历史操作进一步遵循 **Tree-first** 语义：

```text
回到过去并改写剧情  → Pi /tree
从旧节点独立分叉    → Pi /fork 或 /clone
当前时间线纠正字段  → 追加 Correction Commit（已实现：/rp state correct）
```

不得用插件自己的 inverse Commit 模拟 `/tree`。详细边界、fork 继承、branch summary 非 canon 规则和 E2E 矩阵见 [`SESSION-TREE-INTEGRATION.md`](SESSION-TREE-INTEGRATION.md)。

## 3. 计划中的 Entry Schema

Entry 名称先作为研究约定；实现前需要版本化 schema、迁移策略和测试。

> **注意：本节是研究稿，不是已实现的 schema。** 实际落地时采用了 Commit 模型而不是这里的
> `pi-roleplay-current-state` / `-event` / `-memory` 三件套。当前真正写入 session 的 8 种 custom entry
> 是：`pi-roleplay-state`、`-commit`、`-review-decision`、`-review-amendment`、`-turn-status`、
> `-repair`、`-checkpoint`、`-archive`，另加 `roleplay_finalize_turn` 的
> `toolResult.details.roleplayCommit`。以实现为准的说明见
> [`RUNTIME-AND-SESSION.md`](RUNTIME-AND-SESSION.md) §2.2 与 §7。

### 3.1 Selection / Session Role Identity

```json
{
  "customType": "pi-roleplay-selection",
  "data": {
    "schemaVersion": 1,
    "characterId": "alice",
    "worldIds": ["astra"]
  }
}
```

当前插件已经用旧名称 `pi-roleplay-state` 保存 `characterId`。正式迁移时必须兼容旧 session。

当前单角色架构将其解释为 **Session Role Identity**，而不是可任意切换的运行模式：

- 角色是显式 opt-in：只有 `--role <id>`、`/rp use <id>`，或分支上已有的选择记录 / 结构化状态记录
  才会启用角色。资产目录里有角色卡不构成启用意图，纯编码会话不注入任何角色扮演内容；
- `/rp off` 追加一条带 `disabled: true` 的 `pi-roleplay-state` entry 停用当前分支的角色，
  `--no-role` 在本次启动强制不激活；两者都不删除 entry，绑定与剧情记录原样保留；
- `/rp use <id>` 只允许在首次角色回复和首个结构化状态记录之前使用；
- 一旦 branch 出现角色回复、Commit、Checkpoint、Review 或 Turn Status，角色身份锁定；
- `/rp use other` 与恢复旧 Session 时的 `--role other` 不得覆盖已锁定身份；
- `/tree` 回到锁定点以前时，该 branch 可以重新选择；导航到首条角色记录之前的节点时，若当前
  会话已处于角色模式则保持激活，不因路径上缺少记录而失去人格（`/rp off` 与 `--no-role` 仍优先）；
- legacy cross-character entry 仍保留供审计，但 reducer 按绑定角色过滤，不能共享 state/revision；
- 多角色共享时间线与 `statesByCharacter` 属于未来多 Agent 设计，不在当前范围。

当前模型工具输入使用 schema v2 的枚举判别 target，而不是自由字符串路径：

```json
{
  "schemaVersion": 2,
  "stateChanges": [
    {
      "op": "replace",
      "target": { "domain": "appearance", "field": "hair.length" },
      "value": "耳下短发",
      "durability": "persistent",
      "confidence": 1,
      "evidence": [{ "source": "assistant", "quote": "原本齐肩的黑发已经停在耳下" }]
    }
  ]
}
```

模型不能提供 `path`、`character` 或 `characters` 前缀；插件将 target 确定性编译为 `/appearance/hair/length`。Event kind、Memory valence、op、durability 和 evidence source 同样由枚举约束。旧 Session 中 v1 path 仅由兼容读取层接受，不再暴露给模型。

### 3.2 Current State

```json
{
  "customType": "pi-roleplay-current-state",
  "data": {
    "schemaVersion": 1,
    "revision": 7,
    "characterId": "alice",
    "location": "sehlen-south-gate",
    "relationship": {
      "user": {
        "stance": "cautious-cooperation",
        "trust": 22
      }
    },
    "inventory": ["sealed-letter"],
    "conditions": [],
    "questFlags": {
      "enteredCapital": true
    },
    "derivedFromEventIds": ["evt-0007"]
  }
}
```

Current State 是当前事实快照，不应修改 Initial Definition。比如角色卡中的“二十四岁”和初始外貌不会因为剧情文本自动改变。

### 3.3 Event Log

```json
{
  "customType": "pi-roleplay-event",
  "data": {
    "schemaVersion": 1,
    "eventId": "evt-0007",
    "kind": "location-entered",
    "summary": "爱丽丝与同行者抵达塞勒恩南门。",
    "participants": ["alice", "user"],
    "location": "sehlen-south-gate",
    "facts": [
      "城门附近发生未经许可的施法"
    ],
    "importance": 0.7,
    "sourceEntryIds": ["user-entry-id", "assistant-entry-id"]
  }
}
```

Event 应尽量客观、可追溯，不直接等同于角色的主观感受。

### 3.4 Memory

```json
{
  "customType": "pi-roleplay-memory",
  "data": {
    "schemaVersion": 1,
    "memoryId": "mem-0003",
    "ownerCharacterId": "alice",
    "eventIds": ["evt-0007"],
    "summary": "同行者在城门骚动中听从了我的安排。",
    "valence": "guardedly-positive",
    "importance": 0.75,
    "retrievalKeys": ["城门", "同行者", "信任"],
    "participants": ["user"]
  }
}
```

Memory 是角色主观解释，可以与客观 Event 不同，也不能凭空获得角色没有理由知道的信息。

## 4. 注入策略

默认策略仍然是混合式，而不是把全部内容写成 `custom_message`：

| 数据 | Session | Runtime 注入位置 | 原因 |
|---|---:|---|---|
| 角色选择 | `custom` | 决定 active character | 小、可分支 |
| Current State | `custom` | 动态上下文或角色视图 | 结构化、可恢复 |
| Event Log | `custom` | 只选相关事件 | 避免全量历史 |
| Memories | `custom` | 只选相关记忆 | 控制 token |
| 角色定义 | Markdown | system prompt | 保持最高层角色规则 |
| 世界正文 | Markdown | `context` 惰性注入 | 避免 session 膨胀 |
| DeepSeek 适配 | 不持久化 | provider payload | 模型特定协议 |

### 为什么默认不用 `custom_message`

`custom_message` 会持久化且进入 LLM context，适合显式归档快照，但若每轮写入世界书、状态和记忆，会导致：

- 重复 token；
- 新旧状态同时出现；
- session 快速膨胀；
- compaction 和资产升级难以处理。

未来可以研究三种可选持久化模式，但默认保持 `ephemeral`：

```text
/rp persistence ephemeral   # 动态上下文不落 session
/rp persistence session     # 仅内容变化时写隐藏 custom_message 快照
/rp persistence visible     # 快照写入且在 TUI 可见
```

启用快照时必须用 fingerprint 去重，并明确快照失效规则。

## 5. 状态更新的安全原则

不得让模型在普通自然语言回复中静默改写状态。候选方案需要比较：

### 方案 A：显式状态工具

模型调用例如：

```text
roleplay_record_event
roleplay_update_state
roleplay_create_memory
```

优势：结构化、可验证、可在 tool result `details` 中保存状态；Pi 官方也推荐有状态工具通过 tool result details 支持分支恢复。

风险：工具 schema 增加 Prompt 负担；模型可能误调用；需要审批与校验。

### 方案 B：Turn 结束后的提取器

主模型回复后，用规则或低成本模型提取候选事件，再由用户确认。

优势：不干扰角色回复。

风险：额外成本；主观推断；必须避免把错误提取直接当 canon。

### 方案 C：用户显式命令

```text
/rp event add ...
/rp state set ...
/rp memory add ...
```

优势：最确定、易审计。

风险：交互成本高。

初始研究优先级：**用户显式命令 → 受约束工具 → 可选提取器**。所有自动更新必须支持预览、拒绝和回滚。

## 6. 分阶段路线

### Phase 0 — 已实现：短会话基础

- [x] Markdown 角色和世界资产；
- [x] 角色选择以 `custom` entry 持久化；
- [x] 显式 opt-in 激活：`--role` / `/rp use` / 分支已有记录之外一律不激活；`/rp off` 与 `--no-role` 提供关闭入口；
- [x] 单角色 Session Identity：首次角色回复/状态记录后锁定，拒绝 `/rp use other` 与 `--role other`；
- [x] legacy cross-character entry 按绑定角色隔离，不共享 state/revision；
- [x] 当前 branch 恢复角色；
- [x] 角色注入 system；
- [x] 世界书临时惰性注入；
- [x] DeepSeek Provider 适配；
- [x] Telemetry + 真实 session/payload E2E。

### Phase 1 — 已实现第一纵切片：Session schema、Reducer 与 inline-tool

- [x] Event / State Change / Memory / Uncertainty 的版本化 TypeScript schema；
- [x] branch reducer 从 `getBranch()` 中的 `roleplay_finalize_turn` tool result 重建状态；
- [x] 兼容旧 `pi-roleplay-state` 角色选择；
- [x] `/rp inspect state` 显示当前 revision、state hash、events、memories、pending reviews、turn status 与 diagnostics；
- [x] evidence quote、路径白名单、confidence、revision 和 state hash 校验；
- [x] structured validation issue：schema / evidence / permission / conflict / review；
- [x] 同一 proposal 的父子路径冲突检测；
- [x] relationship / knowledge / goals / questFlags 进入 pending review；
- [x] `/rp review accept|reject` 通过 branch-local custom decision 审批；
- [x] `agent_settled` 只在 inline 与 sidecar 都失败时标记 incomplete turn；
- [x] `agent_settled` 对漏调 finalize 的回合先运行隔离 sidecar，成功则原子落盘并渲染摘要；
- [x] 手动 `/rp checkpoint`，带 state hash 验证并从最新有效快照重放；
- [x] Current State / recent events / relevant memories 动态注入；
- [x] 真实“剪发 → 恢复 Session → 短发影响后续回答”E2E。

sidecar-on-missing 及其 TUI custom-entry 摘要已完成。Correction、Review Amendment、手动 Repair
和 v1→v2 内存 migration 也已完成；其余未完成项见文末汇总。

### Phase 2 — 手动事件与状态写入（部分完成）

- [x] `/rp event add`；
- [x] `/rp state set`；
- [x] `/rp memory add`；
- [x] append-only entry，不直接编辑 JSONL；
- [x] 手动 Commit 保留 reason、commitId、eventId/memoryId 与 branch provenance；
- [ ] TUI custom-entry 状态卡片 renderer（当前使用 `/rp inspect state`）。**未被 API 阻塞**：Pi 提供 `pi.registerEntryRenderer(customType, renderer)`（`dist/core/extensions/types.d.ts`，示例 `examples/extensions/entry-renderer.ts`），0.80.10 与 0.81.1 均可用；此前记为"无注册点"是错误结论；
- [x] `/tree` 后自动恢复分支状态的真实扩展生命周期 E2E；
- [x] `/fork` before 与 `/clone` at 的状态继承和新实例 E2E；
- [x] branch summary 在角色模式下不进入 Provider context，也不得污染当前 canon。

退出条件：不调用 LLM，也能完整演示写入、恢复、分支和回滚。

### Phase 3 — Current Character View 动态注入（基本纵切片已完成）

- [x] 格式化 Current State；
- [x] Event 按 query、importance 与新近度检索，并受 `budgets.events` 限制；
- [x] Memory 按 query、importance 与新近度检索，并受 `budgets.memories` 限制；
- [x] Event 按 query、importance 与新近度相关性检索，并受独立预算限制；
- [ ] Current View 与世界书服从 `budgets.contextTotal` 统一 token budget（**只完成一半**，见下）；
- [x] 注入顺序固定为 Current View → Lazy World Context → Original User；
- [x] DeepSeek Provider 适配在最终 payload 第一条 user 追加专属后缀；
- [x] Telemetry/Provider probe 断言最终 payload 的 Current View、World Context 和 DeepSeek 后缀各恰好一份。

#### 未完成项：真正的统一 `contextTotal` 预算

当前 `context` hook 的实际行为是**非对称**的：

```text
Current View 上限 = currentState + events + memories   ← 三个子预算之和，与 contextTotal 无关
世界书上限       = contextTotal - Current View 实际用量 ← 只有它服从 contextTotal
```

因此 `contextTotal` 目前是**世界书的上限**，不是两者的统一上限。当角色卡把 `contextTotal` 配成小于三个
子预算之和时：Current View 仍可占满 4700 左右并突破总预算，世界书余额被压到 0，世界核心与命中条目
整体消失，且没有任何 diagnostics 提示。默认值（子预算合计 4700，`contextTotal` 7000）恰好不触发，
所以该问题在默认配置下不可见。

修复方向（择一，需要改代码，尚未实施）：

1. 先用 `contextTotal` 夹住 Current View 的 `totalTokens`，再把余额给世界书；
2. 或按比例缩放两侧；
3. 无论哪种，都应在 `contextTotal` 小于子预算之和时写出 diagnostics，而不是静默压缩世界书。

在修复前，文档不得把这条描述为「统一预算」。

建议顺序：

```text
system:
  Initial Character Definition
  + runtime boundary
  + Pi runtime

latest user context:
  Current State
  + Relevant Events
  + Retrieved Memories
  + Lazy World Context
  + Original User

provider adapter:
  DeepSeek-specific suffix
```

退出条件：Session 只存结构化状态，最终 payload 能观察到精简角色视图，无过期状态重复。

### Phase 4 — 受控自动更新（inline-tool 主路径已完成）

- [x] `roleplay_finalize_turn` inline-tool 提交 Event / State Change / Memory / Uncertainty；
- [x] 所有候选变更经过 schema、evidence、confidence、path、revision 和 hash 验证；
- [x] 高影响 relationship / knowledge / goals / questFlags 进入 Pending Review；
- [x] 禁止自动改写 Initial Definition、world canon、runtime boundary 和 tools；
- [x] 模型不能提供可信 revision、timestamp、正式 ID、Session ID 或 hash；
- [x] 记录接受、拒绝、issue、turn finalization 和 incomplete marker；
- [x] 当前 branch 的显式 `/rp state correct` Correction Commit，记录 `correctsCommitId` 与 reason；
- [x] Review Amendment（只允许修改 value/from/durability，同时保留原提案）；
- [x] `/rp turn repair` 修复 incomplete 与 finalized-rejected 回合，继续使用同一 evidence Validator；
- [x] finalize 被证据校验整体拒绝时主动通知用户并标记状态栏，该回合进入可修复集合；
- [x] 修复失败（没有产出任何 commit / pending review）只留审计记录，不消耗该回合的修复机会；
- [x] 只产生待审项的修复在待审项被全部拒绝后归还修复机会；
- [x] `/rp turn repair` 无参数模板的引文是占位符，原样提交必然被拒，不会把占位内容写进 canon；
- [x] 自动 `sidecar-on-missing`：复用当前模型与认证发起隔离提取，只给本轮最终
  user/assistant 原文、Current State 和 finalize schema；关闭 thinking 并强制指定唯一工具，结果继续
  经过同一 evidence Validator，以 branch-local `pi-roleplay-sidecar` 原子 entry 落盘。禁止用
  `sendUserMessage` 污染剧情；提取失败才回退到 `incomplete`；
- [ ] 通用 turn-end extraction / sidecar 模式（未来可选研究，非当前默认路径）。

退出条件：自动更新错误不会静默污染 canon 或其他分支。

#### 回合恢复链路的语义（已实现）

一轮语义变化落不了盘只有两种成因，两者都必须可以补交：

| turn status | 成因 | 用户可见信号 | 补救 |
|---|---|---|---|
| `incomplete` | 主模型没调用 finalize，且隔离 sidecar 也失败 | `agent_settled` 追加 turn-status，状态栏「剧情未同步」 | `/rp turn repair` |
| `finalized-rejected` | inline/sidecar 调用了 finalize，但所有实质变化被 evidence / confidence 校验拒绝 | 当场 warning + 状态栏「剧情记录失败」 | `/rp turn repair` |
| `repaired` | 一次产出了 commit 或 pending review 的修复 | info / warning（部分成功） | 视是否真正落盘，见下 |
| `repair-failed` | 一次什么都没产出的修复尝试 | warning，逐条列出被拒理由 | 可以再次 `/rp turn repair` |

`uncertainties` 非空单独就能让 `hasCommitContent` 成立，因此「实质变化全被拒、只剩一句 uncertainty」
会产出一个内容为空的 commit。turn status 按 commit 里的**实质内容**（events / stateChanges /
memories）判定，空 commit 记为 `finalized-rejected`，否则这一轮既丢了全部语义变化、又被关在可修复
集合之外。

关键判定是「这次修复**实际落盘了什么**」，而不是「这一轮出现过 repair 记录」：

- 已经落盘 commit → 该回合不再可修（否则重复提交同一份 proposal 会把同样的状态变化应用两遍，
  这是与「丢失」同一类的数据完整性缺陷）；
- 只产生 pending review → 提交那一刻什么都没落盘。待审或已接受的仍可能落盘，所以照样占用机会；
  但若这些待审项**全部被拒**，这一轮一个字都没写进去，机会必须还回来。判据因此要读 branch 上的
  review 决定，而不是记录上不可变的 `pendingReviews.length`；
- 一条都没产出 → 记录只作审计，回合仍停留在 `incomplete` / `finalized-rejected`。

reducer 侧的去重只看 commit：它的职责是防止状态被写第二遍，而失败记录和只产生待审项的记录都
还没改动过 state，拦下它们只会丢掉审计痕迹。

`repair-failed` 是新增的 status 字符串，不改变 `pi-roleplay-turn-status` 的 entry 结构。旧 session
里的 v1 turn-status 仍按既有 v1→v2 内存迁移读取，旧 entry 不改写；旧版本读到这个未知 status 只会
原样展示，`findRepairableTurn` 在旧版本里只认 `incomplete`，因此不会把它误判为已修复。

同一原则也修好了旧 session：照着旧文档提交空 proposal 留下的空 repair 记录不再永久锁死那一轮。

### Phase 5 — Compaction、快照、归档与迁移（已完成当前范围）

- [x] compaction 前后以 characterId、revision、state hash 三重 guard 验证状态一致；
- [x] 手动及 compaction 后自动生成 branch-local Checkpoint；
- [x] Checkpoint 无损保存完整 Event、Memory、Pending Review 和 Turn Status；
- [x] Reducer 从当前 branch 最新有效 Checkpoint 重放后续 Commit；
- [x] 真实 `/compact` 生命周期 E2E 验证 checkpoint 是 compaction entry 的后继；
- [x] 每 50 个 Commit 自动创建周期性无损 Checkpoint；
- [x] Event/Memory 按正式 ID 去重；`/rp archive` 创建显式完整归档，ID 冲突写 diagnostics；
- [x] Commit、Checkpoint、Review、Turn 的 v1→v2 内存 migration，旧 entry 不改写；
- [x] Checkpoint 保存角色与世界资产 hash，恢复时报告变化；
- [x] 1200 Commit 长期 Session 性能 E2E，覆盖多 Checkpoint、Archive、v1 migration 与全量重放。

### 未完成项汇总（单一来源）

README 与 ARCHITECTURE 不再各自维护「尚未实现」清单，一律以本表为准。

| 项目 | 状态 | 现有替代 | 是否被 Pi API 阻塞 |
|---|---|---|---|
| 真正的统一 `contextTotal` 预算 | 未完成（当前只约束世界书） | 保持默认预算即可避免 | 否，纯本包逻辑 |
| 其他 custom entry 的 TUI 卡片渲染 | 未完成（sidecar 摘要已实现） | `/rp inspect state`、footer status | **否**，见 Phase 2 |
| 纯 TUI `/tree`、`/fork` 选择器验收 | 未完成（需人工） | 自动化生命周期 E2E | 否 |
| 世界条目激活快照 | 未完成 | 无 | 否 |
| world entry `parents` / `recursiveDepth` 递归激活 | 未完成（字段已解析但未使用） | 用 `keys` / `constant` 手工组织 | 否 |
| 资产 `spec` 字段的格式版本校验 | 未完成（字段保留但零引用） | 无 | 否 |
| 酒馆卡 JSON/PNG importer | 未开始 | 手工转 Markdown | 否 |

已经完成、不应再出现在任何「待实现」清单中的项目：Correction Commit（`/rp state correct`）、
Review Amendment（`/rp review amend`）、手动 Repair（`/rp turn repair`，含被拒回合与失败重试）、
手动写入（`/rp state set`、`/rp event add`、`/rp memory add`）、v1→v2 schema migration、归档去重
（`/rp archive`）与长期性能验证。

命令参数解析保留 JSON 的原始字节（不再用 `split(/\s+/)` 折叠空白），因此 value、summary 与
evidence.quote 逐字写入；代价是 JSON 字符串里的字面换行会变成显式解析错误，命令会给出行列与
「换行写成 `\n`」的修改建议。

## 7. 研究时必须回答的问题

每个实现提案都必须给出：

1. 数据写入哪个 entry type？
2. 是否进入 LLM context？
3. 是否随 branch 正确回滚？
4. compaction 后如何恢复？
5. 如何证明它来自哪一轮对话？
6. 是否可能修改 Initial Definition？
7. 如何预算 token 和去重？
8. Telemetry 中最终 payload 应看到什么？
9. 用户如何检查、修正、拒绝和删除？
10. 旧 session 如何迁移？

## 8. 测试矩阵

| 场景 | Session 断言 | Payload 断言 |
|---|---|---|
| 新会话选择 Alice | selection entry | Alice system prompt |
| 装有角色卡但未表达意图 | 不追加 selection entry | 无角色 system prompt 与状态工具 |
| `/rp off` 后切换分支 | 停用记录仍在当前 branch | 不重新注入角色 |
| 已绑定 Alice 后 `/rp use bob` | 不追加 Bob selection | 后续仍为 Alice system prompt |
| legacy Alice → Bob → Alice | reducer 只接受绑定角色 Commit | Current View 不含其他角色状态 |
| 添加地点状态 | state revision +1 | 只有最新地点 |
| 添加事件 | event entry 可追溯 | 相关时才注入 |
| 添加主观记忆 | memory owner=alice | 只作为 Alice 记忆 |
| `/tree` 切分支 | branch reducer 不串线 | 各分支 payload 不同 |
| 工具调用续轮 | 不重复写 state | 动态上下文不重复 |
| compaction | state/event 不丢 | 摘要与结构化事实不冲突 |
| 修改 Markdown 资产 | session hash 可检测 | 按策略采用新资产或快照 |
| DeepSeek V4 | session 无专属后缀 | 第一条 user 恰有一份后缀 |
| 非 DeepSeek | session 相同 | 无 DeepSeek 后缀 |

## 9. 当前明确不做

在对应阶段完成前，不应：

- 从角色回复中静默推断并永久改变关系；
- 不得自动修改年龄等 Initial Definition；外貌 Current State 只能由 evidence-backed 结构化变化或用户显式 Correction 更新；
- 把世界书完整正文每轮写入 session；
- 用单个外部 JSON 取代 Pi branch state；
- 直接追加或修改 session JSONL 文件；
- 把 Telemetry 数据反向当成唯一状态源；
- 将未来设计描述为当前已实现功能。

## 10. 相关文档

- [`SESSION-TREE-INTEGRATION.md`](SESSION-TREE-INTEGRATION.md)：Tree-first 撤销、fork、branch summary 与 checkpoint 隔离规则；
- [`ARCHITECTURE.md`](ARCHITECTURE.md)：当前架构边界；
- [`RUNTIME-AND-SESSION.md`](RUNTIME-AND-SESSION.md)：真实 session、payload、Telemetry 证据与流程；
- [`FORMAT.md`](FORMAT.md)：Markdown 资产格式。
