引入上下文片段、固定槽与投影排序,并完善机遇裁定与游玩期 UI。

把创作产物收敛为可挂载片段与 play_slots/context_order,同步修订世界模拟器模块与运行时拼装。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 01:36:32 +08:00
parent 00dfcb6615
commit 94f67fa744
69 changed files with 7786 additions and 1283 deletions

View File

@@ -0,0 +1,127 @@
# 真值变量 · Data · Progressive设计方法
> 给作者与世界模拟器技能用。运行内核细节见 `design-orchestrator-guide.md` §5、`src/blackboard/table-side-effects.ts`。
> 借鉴对照非耦合SillyTavern 世界书条目的 data / progressive 去向、evented「派生不落盘」。
## 1. 要解决什么
把「好感变了性格就变」「等级到了推进大纲」「场景切换」「程序抽事件」做成**可设计、可程序门控**的能力,而不是:
- 靠模型自觉「记得改性格」;
- 为每张表拆一个执行单元;
- 把大段设定整坨塞进每轮 prompt。
## 2. 三层分工
```text
真值变量state 好、等级、章节、场景 id、任务进度、已触发集合、seed…
│ 程序比较 / 边沿检测tables.side_effects
Data分档·大纲·场景·事件池 事先写好的大表;按真值查档,不整表常驻
│ 命中后 write_tag / replace_tag / queue_worker
Progressive 投影 本轮主世界层只看见「当前档」;未解锁不进上下文
```
| 层 | 存什么 | 谁改 | 例子 |
|----|--------|------|------|
| **真值** | 少数字段,跨轮必须记住 | 见 §3 | `好感=37``章节=2``地点=旧港` |
| **Data** | 阈值→切片、章→细纲、场景包、事件池 | 创作期钉死;游玩期通常只读 | 好感分档性格表、章大纲表 |
| **Progressive** | 当前应注入的上下文 tag | **程序**按边沿写入 | `上下文.角色态度``大纲.当前章` |
**派生不落盘:** 「当前性格长文」是 `f(好感)`,不要再设一个可写变量「当前性格」让模型去改。真值变了,副作用重写投影 tag 即可。
## 3. 变量如何维护(三种写入源)
存储:黑板表 tag `变量.当前`(字段格 + `rev`);开局可与 `运行.初始变量` 对齐。合并规则:`src/blackboard/table-cells.ts`**用户手改默认不被执行单元覆盖**)。
| 来源 | 怎么发生 | 适用 |
|------|----------|------|
| **执行单元LLM** | 某执行单元 `outputs``变量.当前` / `运行.本轮.变量变更`,经 Runtime 合并 | 叙事后果导致的增量(送礼→好感+…);规则须在规格里写清 |
| **用户手动** | UI/检查器改字段格;`source=user`,高 `rev` | 导演改档、纠错、助手流填表驱动 |
| **程序(副作用)** | 真值边沿触发 `tables.side_effects``write_tag` / `replace_tag` / `queue_worker` | **按某值切换投影**、once 解锁、插队某执行单元 |
当前副作用**直接改的是投影 tag / 队列**,不是再写一格「派生真值」。若要用程序把 A 映射成 B 真值,优先:
1. 仍用 A 做真值B 做成 data 投影;或
2. 在更新规则里写明「仅程序/仅用户可写 B」由后续 Runtime 扩展 `set_field` 类 action未实现前不要假装已有
### 3.1 「根据某个值设置」= Progressive不是第二真值
```text
好感 >= 60mode: once
→ replace_tag 上下文.角色态度 =「恋爱档:……」
章节 changed 且 章节 == 2或 eq
→ replace_tag 大纲.当前章 =「第二章细纲……」
场景 id 边沿
→ replace_tag 上下文.当前场景包 =「……」
```
规格形状见 `design-orchestrator-guide.md` §5.5`fired``运行.表副作用.fired`
### 3.2 程序「随机」事件
不要靠模型「感觉该来点意外」:
1. Data事件池id、权重、前置条件、正文/指令)。
2. 真值:可选 `seed` / 回合计数 / 场景权重档。
3. 程序:在边沿或回合结算时抽一条 → 写入 `运行.事件流` 或投影 tag主世界层只演绎已抽中的条目。
4. once / fired同一事件 id 不重复(除非规则允许)。
(真随机:启用 `play_slots.chance`,由按需执行单元 `chance` 程序掷骰/抽签/比点,结果在 `运行.本轮.机遇`;主世界层只演绎已出的结果。事件池权重抽签也可走 chance.pick。
## 4. 哪些需要变量(判定)
只问:**下游要不要可靠查询、门控或防重复?**
| 做成真值变量 | 做成 Data / Progressive | 留散文即可 |
|--------------|-------------------------|------------|
| 好感、等级、章节、场景 id、任务阶段 | 分档性格、章细纲、场景描写包 | 纯氛围、一次性修辞 |
| 已初吻 / 已背叛once 门) | 门触发后的态度切片 | — |
| 已触发事件 id 集合 | 事件池正文 | — |
| 已揭示秘密集合 | 秘密正文(揭示前勿进主上下文) | — |
| 程序随机用 seed / 权重档 | 事件池 | 「今天好像该有事」 |
承重优先:满屏状态栏不如少量真值 + 若干分档表。
## 5. 游玩拓扑:主世界层 + 可选旁观(勿盲目拆执行单元)
内部仍叫 **执行单元Worker**——一次 `run_worker` 的调度单位,这个词准确。
易混的是**职责命名**:多数世界模拟局应是:
```text
用户输入
→ 主世界层(世界推演):读变量 + 已投影 data交事件/改真值(按规则)
→(可选)旁观审计:只出意见,不写 canon
→(可选)叙事转述:把裁决写成用户可见正文
→ 用户看到的终稿通常来自「呈现/叙事」执行单元,或主世界层兼呈现(规格决定)
```
| 内容 | 给谁 | 不要做成 |
|------|------|----------|
| 世界观、地点、势力百科 | 主世界层 + 常驻/查表 | 「世界观执行单元」 |
| 好感与分档性格 | 真值 + Progressive 投影 | 「性格执行单元」 |
| 大纲按章推进 | 真值 `章节` + 章表投影 | 每章一个执行单元 |
| 知密视角 / 强信息隔离 | 才考虑额外执行单元 | 为「更聪明」而拆 |
| 长跑漂移检查 | 旁观审计(只读建议) | 第三个创作主笔 |
用户可见名:`ui-glossary.md`(世界推演、叙事转述…)。作者文档可称 **主世界层 / 旁观**,与酒馆「主 GM + auditor」同构**不要**对用户改称整套系统为「GM 框架」而废弃「执行单元」。
## 6. 世界模拟器技能落点
| 技能 | 钉什么 |
|------|--------|
| **变量设计与更新规则** | 真值;**维护语句**形状settlement / 隐藏段);**Data 映射索引**(指向生成规则+具体实例);`side_effects` |
| **变量控制上下文** | 各槽视野;**旁观汇总**(当前档摘要,非整表);剧透边界 |
| **生成规则 / 具体实例** | 分档表 schema 与行数据(如好感→性格);生成后由变量设计索引 |
| **正文组成** | 隐藏段定界(供解析维护语句);用户可见块序 |
| **设计监控栏** | 用户可见的会变字段子集 |
| **开场白与开场变量** | 开场正文(守版式)+ 与开场同真相的初值 |
| **游玩拓扑 / 上下文投影排序 / 细化终稿** | 固定槽扁平投影序tables 收成 |
**维护路径(不是 chance toolcall**:主世界层输出可解析变更 → Runtime 合并 `变量.当前``side_effects` 换投影chance 只负责骰子/抽签。
编排口诀:体验与机制 → 要不要真值 → 映射表用生成规则/实例 → 维护语句与旁观汇总 → 开场同真相 → 收成。