Files
writing-agent/docs/progressive-data-design.md

130 lines
7.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 真值变量 · 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
用户输入
→ 旁观维护(副 LLM合同+表+本轮工单默认空操作maintain.v1
→(可选)角色视角:强信息隔离时出反应建议
→ 主世界层(世界推演):读变量 + 已投影 data + 旁观包,交事件/改真值(按规则)
→(可选)叙事转述:把裁决写成用户可见正文
→ 用户看到的终稿通常来自「呈现/叙事」执行单元,或主世界层兼呈现(规格决定)
```
| 内容 | 给谁 | 不要做成 |
|------|------|----------|
| 世界观、地点、势力百科 | 主世界层 + 常驻/查表 | 「世界观执行单元」 |
| 好感与分档性格 | 真值 + Progressive 投影 | 「性格执行单元」 |
| 大纲按章推进 | 真值 `章节` + 章表投影 | 每章一个执行单元 |
| 知密视角 / 强信息隔离 | 才考虑角色视角槽 | 为「更聪明」而拆 |
| 表字段补充 / 按需触发生成规则 | 旁观维护(默认空操作) | 第三个创作主笔 |
| 长跑漂移检查 | 旁观维护 notes | 第三个创作主笔 |
用户可见名:`ui-glossary.md`(主世界层、旁观维护、叙事转述…)。作者文档可称 **主世界层 / 旁观维护**,与酒馆「主 GM + auditor」同构**不要**对用户改称整套系统为「GM 框架」而废弃「执行单元」。
**维护路径(不是 chance toolcall**:主世界层输出 settlement.v1 → Runtime 合并 `variable_changes``变量.当前``side_effects` 换投影;旁观维护输出 maintain.v1 → Runtime 按需合并 `table_ops`chance 只负责骰子/抽签。
## 6. 世界模拟器技能落点
| 技能 | 钉什么 |
|------|--------|
| **变量设计与更新规则** | 真值;**维护语句**形状settlement / 隐藏段);**Data 映射索引**(指向生成规则+具体实例);`side_effects` |
| **变量控制上下文** | 各槽视野;**旁观汇总**(当前档摘要,非整表);剧透边界 |
| **生成规则 / 具体实例** | 分档表 schema 与行数据(如好感→性格);生成后由变量设计索引 |
| **正文组成** | 隐藏段定界(供解析维护语句);用户可见块序 |
| **设计监控栏** | 用户可见的会变字段子集 |
| **开场白与开场变量** | 开场正文(守版式)+ 与开场同真相的初值 |
| **游玩拓扑 / 上下文投影排序 / 细化终稿** | 固定槽扁平投影序tables 收成 |
编排口诀:体验与机制 → 要不要真值 → 映射表用生成规则/实例 → 维护语句与旁观汇总 → 开场同真相 → 收成。