Files
writing-agent/docs/briefs/dictate-only-creation.md
T

892 lines
48 KiB
Markdown
Raw 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.
# 对话落盘单一化 · 执行蓝图
> 状态:核心方向已确认,按本文依赖顺序实施;非工具节点仍须逐项审阅提示词。
> 修订:2026-09-30。
> 相关:`docs/play-presentation-shells.md`、`docs/context-fragment-design.md`、`docs/world-simulator-modules.md`。
## 执行状态(2026-09-28)
- [x] 基线扫尾:删除新建作品选配方的过时提示。
- [x] 工作包 A:本局创作方案、两态注入、能力覆盖校验、旧配方案例化。
- [x] 工作包 B:`read_module`、`read_library_entry`、提示版本门禁、按需读取库。
- [ ] 工作包 C(进行中):内容节点、普通呈现链和 0 层呈现链均已迁移;`user-requirements` 经审阅决定删除;四个共用运行步骤已确认为自动工具节点,尚待补齐完整确定性编译。
- [ ] 工作包 D:游玩投影与维护合同编译,未开始。
- [ ] 工作包 E(进行中):楼层/0 层双呈现节点与数据合同已建立;壳参考库已按 7 种区、5 只壳写入 `shell-refs/`;隔离 iframe、持久槽位运行时和重 roll 尚未实现。
- [ ] 工作包 F:库条目 schema、本局化与提示归属,部分完成;偏好/文风库按需读取;仓库 `seeds/libraries/*.json` 可 git 备份并 `npm run libraries:restore` 恢复。
- [ ] 工作包 G:长程记忆、表维护与固定输入语法,未开始。
## 0. 已确认结论
1. 新建作品只填写名称并直接进入对话落盘。这部分已经完成,不再列为工作包;旧工序编排书和后端 DAG 暂留兼容。
2. 创作入口与设计清单合并为一份中间产物「本局创作方案」。它根据自然语言生成本局方法(下文称“本局配方”),并给全部能力分档。
3. 旧配方不再供用户手动选择。修订后作为本局创作方案的参考案例,不作为固定路径。
4. 不写死“先美学、再清单、再逐节点”的统一工作流。本局创作方案描述依赖与重要程度,模型根据当前材料灵活推进,并可在用户改口后整份重写。
5. 创作对话保留一次用户输入触发多次 `insert` 的能力。逐节点审阅只约束本次程序改造:修改每份非工具节点提示词前必须给用户过目,不限制产品运行时一次只能写一个产物。
6. 壳最终仍是正文组成节点读取的参考库。否定的是当前七个外观壳及其按产品原型换皮的分类,不是否定参考库本身。
7. 正文前端采用隔离 iframe。它是显示容器,不提供 `action` 回传;用户仍从主输入框输入。
8. 创作源产物、创作交互与评分、游玩投影分开。开玩时不得再把全部 `设计.*` 原样挂给主世界层。
9. 长程记忆采用“写大总结”和“清空旧楼层”两个独立操作,不在大总结成功后自动删除历史。
10. 输入语法写死:裸写表示上帝视角,单井号包裹的 `#内容#` 表示角色行动,引号包裹的内容表示角色说话。
11. 新增“0 层卡”呈现模式:开场白所在气泡是持久前端;正文、指令、表盘、地图等都是其中的槽位,每轮就地更新,不继续向下叠加可见助手楼层。
12. 普通楼层与 0 层卡不共用呈现节点;现已复制 `回复呈现`、`正文组成`、`开场白与开场变量` 三个显示强相关节点,其它内容能力继续共用。
13. 0 层模式在“更多操作”中提供“重 roll 本轮”,复用本轮消息前 checkpoint;暂不提供任意历史回退。
## 1. 当前基线
以下内容已经落地,不再实施:
- 新建作品弹窗只保留作品名称。
- 新建作品固定 `creationMode: "dictate"`。
- 新会话默认进入对话落盘。
- 旧工序编排书仍可打开,DAG 后端和旧前端仅作兼容。
扫尾项(已完成):
- [x] 删除 `web/agent-ui.js` 中“请先在新建作品时选定配方”的过时提示;旧书展示所需的「工序编排」标签可保留。
现有但尚未达到本文目标的基础设施:
- 文风库、偏好库和库注册表已经存在,但对话落盘仍会整库注入。
- `play-bind` 已能自动装配部分运行上下文,但仍主要按 tag 分类并给主世界层全量投影。
- `auditor` 和 `maintain.v1` 已存在,但默认关闭,也没有本文所需的阻塞、总结和清空交互。
- 现有七个壳及预览器仍存在,只作为待替换旧实现。
## 2. 目标链路
```text
用户自然描述
→ 本局创作方案〔中间产物,可反复重写〕
- 生成本局配方:如何把本次需求做出来
- 给全部能力分档并说明理由、缺口和建议实例
- 只表达必要依赖,不生成固定流水线
→ 按当前材料灵活推进
- 写某能力前 read_module
- 需要库条目时 read_library_entry
- 同轮只连续写入这句话已经说清的能力,通常 2~3 个
- 每份写入携带独立 self_score
→ 回复呈现
→ 正文组成读取壳参考库,生成本局模板与数据契约
→ 开场白按数据契约生成 present.v1
→ 开玩时把源产物编译成各 Worker 的游玩投影
```
这不是硬编码流程:
- 用户这句话已经说清的能力,同轮可以读取并连续 `insert`,通常 2~3 个。没提到的「必须」和「有必要」按已有材料给 2~3 个选项询问,选定后再写。写开场前用未落项问用户哪些还没设计。
- 能力之间只有真实语义依赖。例如正文组成需要知道要呈现什么,开场白通常靠近创作收束;不能因此把所有作品强制塞进同一节点序列。
- 文本创作、世界模拟、短局、长局、数据化跑团等只是本局配方案例,不是程序分支。
- 用户改变目标时,先更新本局创作方案,再按新方案增删或改写产物。
## 3. 工作包 A · 本局创作方案〔已完成〕
### 3.1 能力与产物
新增 `modules/creation-plan/prompt.md`,目录登记:
```yaml
- id: creation-plan
name: 本局创作方案
layer: intermediate
artifact: 设计.本局创作方案
```
该产物同时承担原“创作入口”和“本局设计清单”的职责:
```json
{
"schema": "creation-plan.v1",
"技能": "本局创作方案",
"brief": "一句话说明本局靠什么兑现体验",
"recipe": {
"primary": "主要创作方法",
"secondary_traits": ["可混合的次要体验特征"],
"method": ["针对本局的做法,不是固定节点顺序"],
"references": ["采用或改造过的旧配方案例 id"]
},
"items": [
{
"module_id": "variable-design",
"tier": "必须",
"why": "任务时限与暴露度必须跨轮保存",
"missing": "暴露度达到哪一档会被识破尚未确定",
"instances": []
}
]
}
```
`items` 覆盖对话落盘可见的全部内容能力,但排除:
- 本局创作方案自身。
- 变量声明、变量映射、上下文排序等机械工具节点。
- 只供旧工序编排使用的节点。
四档含义:
| 档位 | 含义 | 默认行为 |
| ----- | -------------- | --------------- |
| 必须 | 缺少后无法运行或核心体验会崩 | 收口前问清。用户没提到时给 2~3 个选项,选定后再写 |
| 有必要 | 缺少仍可运行,但体验明显受损 | 同样先问再写;用户明确不要时可降档 |
| 有一定效果 | 有了更好 | 用户提及时做;可顺带询问一次 |
| 没有意义 | 本局用不上 | 不主动推进 |
四档是收口前的核对清单,不是本轮待办,也不是 DAG。程序不按照数组顺序强制执行节点。本轮通常只写用户这句话已经说清的 2~3 个能力。
### 3.2 旧配方改为案例
- 删除新建阶段和创作页中的手动配方选择。
- 修订现有对话落盘配方,只保留各自有辨识度的方法、适用信号和能力档位倾向。
- 本局创作方案可以引用、混合或改写多个案例;引用结果写入 `recipe.references`。
- 案例不能复制总提示的公共规则,也不能恢复成隐藏的固定工作流。
### 3.3 注入
`buildDictateSystemPrompt` 分两态:
- 没有方案:提供能力目录的短声明、使用边界和配方案例目录,要求根据用户当前材料形成方案。
- 已有方案:注入完整本局配方;能力按档分组,显示已落/未落和最低自评分。前三档附带该能力的何时用 / 何时不用(方案改写或补全后仍保留;可反复能力已落一条也保留),供本轮选型。不附带执行规格。「没有意义」只列名称。
用户改口、新增方向,或现有方案明显不再成立时,允许覆盖 `设计.本局创作方案`。
### 3.4 程序约束与验收
- 写入方案时校验能力覆盖;漏项则拒绝并列出 id。
- 插入开场白时,如仍有“必须”项未落,只提醒,不拒绝。
- 不要求体验锚定达到固定计数,也不要求先经过美学节点。
- 方案落盘后系统提示应明显短于全目录注入。
- 测试:`tests/creation-plan.test.ts`。
## 4. 工作包 B · 写产物前读取能力与参考〔已完成〕
### 4.1 `read_module`
`src/dictate/tools.ts` 新增:##
```json
{
"name": "read_module",
"parameters": {
"module_id": "能力 id,也接受中文名",
"reason": "可选,一句话"
}
}
```
返回该能力的:
1. `task`、`principles`、`output`、`score`。
2. 绑定库的条目目录与短说明,不返回整库正文。
3. 正文组成所需的壳参考目录、正文安全子集和 iframe 数据契约说明。
4. 该能力适用的程序约束。
会话记录已读取的能力及其提示版本。写某能力产物前未读该版本时,`insert` 拒绝并提示调用 `read_module`。同轮可以先读用户这句已经说清的能力(通常 2~3 个),再连续执行这些 `insert`。还没提到的先问,不先读后写。
机械工具产物不受此限制。
### 4.2 `read_library_entry`
仅返回库目录不足以完成选择,因此新增独立工具:
```json
{
"name": "read_library_entry",
"parameters": {
"library_id": "库 id",
"entry_ids": ["本轮选中的 1~2 个条目 id"]
}
}
```
约束:
- 只能读取当前能力绑定库中的条目。
- 默认最多读取两个;确需更多时必须给出原因。
- 本局源产物记录条目引用和本局微调;未选条目不进入后续提示。
- 用户提出库外新取向时,可先形成本局临时条目;是否回写全局库另行确认。
### 4.3 验收
- 未读取能力就写对应产物会被拒绝。
- 读取正文组成时能看到壳目录和 iframe 契约。
- 对话落盘不再默认注入文风库、偏好库全文。
- 测试:`tests/dictate-read-module.test.ts`、`tests/dictate-read-library-entry.test.ts`。
## 5. 工作包 C · 产物分层、评分与自然回复〔进行中〕
### 5.1 四类数据
1. **中间产物**:只服务创作决策,不进游玩。目前包括 `设计.本局创作方案`,以及 `lifecycle_intent = seed_only` 的生成规则。
2. **源产物**:能力形成的完整定稿,保留在黑板供编辑、验收和重新编译。
3. **游玩投影**:从源产物确定性提取、按 Worker 分发的运行时内容。
4. **创作交互与评分元数据**:回应、评价、启发、追问、缺口和分数;留在消息或元数据,不进入游玩投影。
`DictateProduct` 和黑板元数据新增 `layer`。目录的 `layer` 是默认值;生成规则根据产物中的 `lifecycle_intent` 覆盖默认值。
### 5.2 自评分
每个能力 `prompt.md` 新增 `score` fence,每个维度给出 5 / 3 / 1 分锚点。`insert` 新增:
```json
{
"self_score": {
"dims": [
{
"name": "维度名",
"score": 3,
"gap": "当前缺口",
"options": ["涉及用户偏好时提供的具体选项"]
}
]
}
}
```
- 分数为 1~5。
- `score <= 3` 必须写 `gap`;涉及用户选择时给 2~3 个 `options`。
- 维度名必须与该能力 `score` fence 一致。
- 分数存入黑板元数据,不再写进产物正文。
- `追问`、`开放问题`、完备度诊断同样不进入游玩投影。
迁移按 §9 逐节点审阅进行。过渡期兼容规则:
- 已有 `score` fence 的能力使用新参数并严格校验。
- 尚未迁移的能力继续接受旧 `output` 形状,不因缺少 `score` fence 阻塞写入。
- 全部内容节点迁移完成后,统一删除旧自评解析和兼容分支。
### 5.3 用户可见回复
回复不使用固定标题、固定句数或逐模块仪式。按当轮内容自然覆盖:
1. 回应用户输入中的有效判断、矛盾或值得保留之处。
2. 说明本轮形成或改写了什么;完整 JSON 由产物卡展示。
3. 用户没提到的「必须」或「有必要」,给 2~3 个根据原话推出的选项来问。这句话已经说清并写入的,不再强行追问。
4. 简短说明强项和缺口。
写开场或结束创作前,用仍未落的「必须」和「有必要」问用户哪些还没设计。同轮写入多个已说清产物时综合回应整轮,不逐模块重复模板。
写正文组成或 0 层正文组成时,回复里直接给出一份隔离内容供预览:与本局前端同一套骨架,示例已经写进去。完整 JSON 仍由产物卡展示。
## 6. 工作包 D · 游玩投影编译〔未开始〕
“游玩投影”指:创作时保存的完整产物不能直接塞进模型;开玩时先抽出每个 Worker 真正需要的字段,再分别装配。
### 6.1 编译入口
在 `src/dictate/play-bind.ts` 增加明确的编译阶段:
```text
黑板源产物
→ resolve module / layer
→ intermediate 与 seed_only 跳过
→ compileDictateProjection
→ 按 mount 分发给 world-simulator / narrator / auditor
→ 各自按 context_order 装配
```
不要再用 tag 正则把几乎全部 `设计.*` 挂给主世界层。
### 6.2 投影契约
能力目录声明默认 `mount`;每个最终能力提供确定性的投影器或字段允许列表:
- 主世界层:事实推进、角色扮演、输入解释、权限边界。
- 转述:本局选中的文风、呈现规则、正文数据契约。
- 副 Worker:表结构、当前值、维护规则及人物一致性所需的少量设定。
所有投影统一剥离:
- 创作期回应与评价。
- `self_score`、追问、开放问题、完备度和诊断依据。
- 本局创作方案状态。
- 不属于目标 Worker 的字段。
纯模型阅读内容优先生成有身份标题的 Markdown;变量、映射、数据契约和 `present.v1` 保持结构化。
这解决两个具体问题:
1. `layer` 只回答“整份产物是否进入游玩”,不足以回答最终产物中哪些字段能进入。
2. `mount` 只回答“给谁”,不足以回答“给这个 Worker 看哪些字段”。因此必须同时有分层、投影和分发。
### 6.3 验收
- 本局创作方案和 `seed_only` 规则不出现在游玩请求中。
- 主世界层、转述、副 Worker 得到不同且最小的投影。
- 请求日志中不存在创作回应、评分、追问和诊断字段。
- 具体实例暂时全量稳定注入,不引入关键词检索或 RAG。
- 扩展 `tests/dictate-play-bind.test.ts`,覆盖分层、字段剥离和按 Worker 分发。
### 6.4 维护方式分流与条件式编译工具节点
维护不固定走副 LLM。创作收口时先按复杂度选择一种运行策略:
1. `none`:没有跨轮可变内容,不挂维护能力。
2. `inline_tool`:只有 1~2 个简单独立变量,或少量可由主世界层明确决定的标量更新。给主世界层挂原生 `update_state` tool call;正文仍输出普通 Markdown。
3. `inline_structured`:模型不支持工具调用时,用 `{ body, state_ops }` 结构化整包,程序只显示 `body`。这会牺牲自然流式体验,因此不是首选。
4. `auditor_bundle`:变量较多、存在交叉依赖,或同时维护拓扑、补实例、其它备忘录时,运行 `maintenance-compile` 并启用统一维护副 Worker。
数量不是唯一判据:一个带扩展规则的关系图也应走 `auditor_bundle`;三个彼此独立、更新完全确定的计数器仍可走程序或 tool call。
`update_state` 只接受设计阶段声明过的变量、操作和 revision。主世界层先决定本轮事实并调用工具,程序校验、提交并返回结果,再输出用户可见正文。相比正文隐藏标签,它能在生成过程中报告拒绝或冲突;相比把长正文包进 JSON,它保留自然文本与流式输出。当前 GM harness 已有 `chance` tool loop,可沿用同一机制。
API 能力选路复用 profile 已有探测结果,但使用独立策略:
- `tools=ok`:使用可选 tool call;不能用 `forcedTool` 强迫每轮更新,因为“本轮无变化”是正常结果。
- `strictTool=ok`:动态工具带 `strict: true`;若供应商对实际 schema 拒绝,则降为普通 tool,并继续由本地校验全部参数。
- tools 不可用而 `jsonSchema / forcedTool / jsonObject` 任一可用:通过现有 `completeStructured` 选路提交 `{ body, state_ops }`。
- 只有纯文本能力:可请求 JSON 并严格解析、失败后重试;解析失败则不写状态。新实现不使用正文隐藏标签或正则维护变量。
动态结构随请求生成,不需要向 API 预注册。`inline_tool` 只用于少量变量,因此优先为每个变量生成一个类型明确、结构简单的小工具:工具名使用稳定安全 id,description 携带该变量的更新条件,parameters 只含该类型允许的 `set / delta`、值、`expected_rev` 与简短依据。避免为所有变量动态拼一棵带大量 `oneOf` 的复杂 schema。
现有能力探测验证协议是否支持 tools、强制 tool、strict tool 与各类 JSON 输出;它不能证明供应商支持任意复杂 schema 方言。因此实现时需增加一个与状态更新工具同形的代表性探测,运行请求仍保留“strict 被拒绝 → 非 strict + 本地校验”的降级。
`maintenance-compile` 是条件式自动工具节点,不调用 LLM 创作内容。仅在策略为 `auditor_bundle` 时扫描所有最终产物,把分散的跨轮维护要求编译成一份 `设计.维护合同`:
```json
{
"schema": "maintenance-manifest.v1",
"targets": [
{
"id": "目标短 id",
"kind": "table | topology | generation | memo",
"state_ref": "变量.当前 | 运行.拓扑#id | …",
"rule_refs": ["来源产物及字段路径"],
"allowed_ops": ["set", "delta"],
"timing": "pre_narrative | post_narrative",
"writers": ["program", "gm", "auditor", "user"],
"visibility": "public | hidden",
"rules": ["给维护者执行的短规则"],
"invariants": ["不可破坏的约束"]
}
]
}
```
主要来源包括:
- `设计.变量设计与更新规则` 的真值、写入源、更新时机、钳制和 side effects。
- `设计.拓扑图谱#*` 的动态模式、允许操作、写入者和一致性约束。
- `设计.生成规则#*` 中游玩期按需补实例的触发条件。
- 后续明确声明“游玩期可修改”的其它备忘录;纯静态设定不进入维护合同。
编译规则:
- 不复制整份创作产物,只提取维护所需字段并保留来源引用。
- `none / inline_tool / inline_structured` 不生成聚合合同,也不启用 `auditor`。
- 一旦启用 `auditor`,应把本轮所有需要其判断的维护目标、当前状态和更新规则一次性投影给它,不能让它只看到变量而漏掉拓扑或补实例规则。
- `inline_tool` 只给主世界层简短工具 schema,不注入完整维护文档。
- `auditor_bundle` 下正文生成者不承担隐藏维护清单;需要从正文事实推断的更新统一由回合末 `auditor` 处理。必须在正文前完成的机械更新单列为 `pre_narrative`,由程序或专门的前置调用处理。
运行期由程序从维护合同生成精简的 `maintenance-context.v1`,只包含本轮相关目标、当前状态、用户输入和最终正文。旁观输出升级为 `maintain.v2`,至少可携带:
- `table_ops`
- `topology_patches`
- `generation_requests`
- `memo_ops`
- `notes`
旧 `maintain.v1` 继续作为仅含 `table_ops / need_generate` 的兼容输入。
验收:
- 单个“用户存款”变量只挂 `update_state`,不启动 `maintenance-compile` 或副 LLM。
- 工具调用成功后只显示正文;工具参数、结果和隐藏状态不混入气泡。
- 工具不可用时结构化整包可正确分离正文与状态;纯文本解析失败不写状态。
- 运行期变量维护不依赖正则;SillyTavern 正则只作为外部预设导入兼容能力,不能写权威状态。
- 同一局既有变量、关系图和按需实例时,旁观一次收到完整合同并可在一份维护包中分别更新。
- 主世界层提示不再塞入仅供维护使用的完整更新规则。
- 每项操作都有目标 id、来源规则和 revision;未知目标或越权操作被拒绝。
- 多数无变化回合仍可返回空维护包,不为“检查过”制造写入。
## 7. 工作包 E · 壳参考库与隔离 iframe〔未开始〕
### 7.1 壳参考库
壳是正文组成读取的参考。创作时选一只最接近的,按本局启用的区删掉多余区并重排,生成一次前端后固定。游玩只输出各区内容,由程序装配。
可见区有 6 种。隐藏的变量更新不参与分类,也不进壳。
| 区 | 里面是什么 |
| --- | --- |
| 抬头 | 页首一行短内容,例如标题、日期、天气、地点;条目一多或当前值一长,改用数据卡 |
| 正文 | 这一轮的主叙事 |
| 小故事 | 论坛上的一段,或正文地点以外其他重要角色的一小段;同一轮只写一种 |
| 数据卡 | 一组变量的卡片或表;只露出点名的列和行 |
| 结构 | 地图、关系或要对着看的长表 |
| 文字选项 | 几条下一步,只显示文字,始终直接可见,不放进标签或折叠 |
参考壳按主面来,写在 `skills/dialogue/world-simulator/shell-refs/`:
| 称呼 | id | 什么时候用 |
| --- | --- | --- |
| 阅读 | `reading` | 只有正文、页首一行和选项 |
| 正文为主 | `dual-text` | 正文占满一栏。短文、地图用标签或折叠,点开才看。选项始终直接可见 |
| 数据常驻 | `data-cards` | 数据一直铺开,不替换正文。左栏是数百字正文,右栏是另一路短内容。选项始终直接可见 |
| 成稿 | `piece` | 一页一份能单独拿走的成品。内部小节在创作时按范例重排。选项在成稿下面 |
每只壳的备注只写两类:不替换的前端结构,以及可按本局用途替换的部位。备注不点名某一种应用场景。
`alongside`、`paged` 不再单独作为参考。另一篇长文不与正文左右对半。右栏是短内容时,可以和长正文并排。
美化用配色、字体层级、边框、间距,以及 CSS 或简单内联 SVG,按本次能写稳的程度完成。
### 7.2 正文组成产物
`设计.正文组成` 保存:
```json
{
"参考壳": ["按正文体验命名的参考 id"],
"为何": "它如何服务本局的阅读体验",
"数据契约": {
"blocks": {
"body": { "类型": "markdown", "职责": "主读正文" },
"任意本局键": { "类型": "kv | list | markdown", "职责": "用途" }
}
},
"frontend": {
"html": "<div id=\"app\"></div>",
"css": "",
"js": "present.onData(render)"
},
"示例灌数": {
"schema": "present.v1",
"blocks": {}
}
}
```
- 创作期生成一次模板并固定。游玩每轮只生成内容块,由程序装配进该模板,不再生成壳。
- 美化用配色、字体层级、边框、间距,以及 CSS 或简单内联 SVG,按本次能写稳的程度完成。
- 壳只包含本局实际启用的区。参考壳多出来的区在创作时删掉并重排,不留到游玩再空着。
- `blocks` 允许自定义键,前后端 normalization 不再吞掉未知键。
- `html + css + js` 合计上限 60 KB。
### 7.3 最小隔离
新增 `web/present-frame.js`:
- 使用 `<iframe sandbox="allow-scripts">`,不加 `allow-same-origin`。
- 禁止网络、表单、弹窗和顶层导航。
- 只提供 `present.onData(cb)`、安全 Markdown 渲染和自动高度回报。
- 不提供 `present.action`,也没有“直接发送”设置。
- 模板报错或 3 秒内未 ready 时,回退为安全的纯文本/基础块渲染;不回退到已否决的旧七壳。
这里是低成本故障隔离,不把自创模板当作敌对第三方脚本设计复杂权限系统。
### 7.4 接入与验收
- 游玩终稿、开场候选、正文组成预览接入 iframe。
- `SessionView` 下发 `presentationFrontend`。
- 流式期间先显示纯文本,完成后灌入 iframe。
- chat 型与长文阅读型参考必须肉眼显著不同。
- 模板损坏时消息仍可读。
- 测试:`tests/present-frame.test.ts`,覆盖 srcdoc、消息来源、ready/错误回退和自定义 blocks。
### 7.5 双呈现链
内容节点继续共用;只复制与显示形态直接耦合的三个节点:
- `回复呈现`:普通楼层版继续定义每轮消息区域;0 层版定义持久卡槽位及各槽内容规则。
- `正文组成`:普通楼层版生成每条消息的前端;0 层版生成开场时一次建立的持久前端、Tab 与槽位渲染器。
- `开场白与开场变量`:普通楼层版生成第一条消息;0 层版同时初始化持久前端和全部槽位初值。
当前实现:
- 已建立 `zero-layer-status / 设计.0层回复呈现`、`zero-layer-reply-format / 设计.0层正文组成`、`zero-layer-opening-setup / 设计.0层开场白与初态`。
- `本局创作方案.presentation_mode` 必须在 `message / zero_layer` 中选一种;`items` 只包含所选模式的三项呈现能力,不把另一套写成“没有意义”占位。
- 0 层更新合同使用 `zero-layer.card.v1` 与 `zero-layer.update.v1`;更新方式为 `replace / append / data`,并以 `base_revision` 原子提交。
- 主世界层与转述不复制能力节点,只按呈现模式切换最终输出合同。
### 7.6 0 层卡、槽位更新与重 roll
0 层卡是开场白所在气泡内的持久前端,不是额外的上下文深度:
- 正文也是一个槽位,可与“公司指令”“监控表盘”“地图”等槽位并列。
- 每轮助手结果仍写入内部对话历史,但前端不新增可见助手楼层;程序把本轮更新应用到 0 层卡。
- 槽位声明更新方式:`replace`(整块替换)、`append`(受上限约束的槽内日志)、`data`(结构化数据驱动渲染)。
- 0 层初始状态与每轮槽位更新均持久化;刷新、续作、run 快照和重 roll 后可恢复。
- 规范路径使用结构化 `slot_updates`;新增受限正则提取/替换兼容层,用于导入 SillyTavern 标签和显式声明的 `<公司指令>…</公司指令>` 一类输出,不以任意正则直接修改权威状态。
- iframe 只接收规范化后的槽位数据;LLM 不直接生成或修改运行中的 DOM。
“更多操作”菜单新增:
- **重 roll 本轮**:恢复最新一轮助手输出前的 checkpoint,重新生成该轮并重新应用槽位更新。
- 暂不提供任意历史回退:缺少稳定用户锚点前,不暴露多步撤销。
- 既有消息分支 / swipe 数据仍保留;0 层前端只显示当前活动分支重放后的状态。
验收:
- 连续多轮后仍只有一个可见 0 层前端,正文与其它槽位按合同更新。
- 重 roll 不残留被废弃版本写入的槽位值。
- 模板损坏时可查看本轮纯文本与结构化槽位数据。
- 正则适配器失败不修改权威槽位状态。
## 8. 工作包 F · 库、本局化与提示归属〔部分完成〕
### 8.1 偏好库与文风库
- 偏好库:输入用法、推进节奏、是否代演玩家、停笔方式、常用禁区。
- 文风库:遣词、段落节奏、笔墨焦点、写法档和示范片段。
- 故事推进和叙事指南改为“选择 + 本局化”节点,各读取最相关的 1~2 项,解决冲突并记录微调。
- 未选条目不进入后续提示。
### 8.2 规则归属
- 公共运行原则放总提示。
- 配方案例只写有辨识度的方法和档位倾向。
- 能力提示写使用边界、产物规格和评分。
- 可程序校验的格式与依赖只在程序实现。
- 删除面向用户的“落盘、收口、下一刀、模块”等内部流程腔。
- 重复长例只留在一个权威位置,其余位置引用。
## 9. 非工具节点逐项审阅
本节只约束实施改造,不约束创作运行时的 `insert` 次数。
每份非工具节点提示词按以下流程处理:
1. 一次讨论一个节点。
2. 修改前完整展示审阅表。
3. 用户批准后才修改该节点的 `prompt.md`、直接关联目录声明和测试。
4. 修改后展示实际变化与验收结果,再进入下一节点。
审阅表:
| 项 | 内容 |
| ------ | --------------------- |
| 节点 | id / 中文名 |
| 产物层 | intermediate / final |
| 本局职责 | 为什么存在,服务创作还是游玩 |
| 当前问题 | 现有提示、产物或消费链路的问题 |
| 使用边界 | 何时有用、何时没有意义、与相邻能力如何分工 |
| 产物形状 | 保留、删除、新增哪些字段 |
| 评分规则 | 维度及 5 / 3 / 1 锚点 |
| 用户可见交互 | 如何确认,何时根据缺口询问 |
| 程序消费 | 谁读取,怎样投影,是否进入游玩 |
| 待用户决定 | 尚有分歧的选项 |
| 审阅结论 | 未审 / 批准 / 修改后再审 / 否决 |
机械工具节点可以集中修改和测试,但不能借此改变内容节点的职责、语义或评分标准。
## 10. 工作包 G · 长程记忆、表维护与输入通道〔未开始〕
### 10.1 上下文拼装顺序
为尽量保留稳定前缀缓存,顺序调整为:
```text
稳定系统提示
→ 静态游玩投影
→ 本局数据契约与工具说明
→ 可变记忆表 / 变量当前值 / 最新总结
→ 清空后保留的最近对话楼层
→ 当前用户输入
```
静态内容在前,可变表和对话放后。表格每轮变化时只破坏其后的缓存,不让整个稳定前缀失效。
### 10.2 副 Worker 维护
```text
主世界层写出事实正文
→ 转述 / 呈现(若启用)
→ 副 Worker 根据已发生事实维护变量与记忆表
→ 维护完成后允许下一轮用户输入
```
- 默认启用独立副 Worker;多数轮允许空操作。
- 更新期间禁用发送,在输入区显示“正在更新记忆表…”。
- 成功后恢复输入;失败时保留旧表并提供重试,不让半成品进入下一轮。
- 表很少且规则简单时,未来可显式选择主世界层隐藏维护段;本阶段不做自动阈值切换。
- 正文组成只决定如何显示,不修改变量和记忆。
### 10.3 动态二维表
按本局需要建立少而承重的表:
- 事件账本:时间、地点、人物、事件、直接后果。
- 承诺与债务:双方、内容、状态、到期或触发条件。
- 人物关系:当前态度、公开关系、关键变化。
- 线索与未决事项:内容、来源、可信度、解决状态。
- 阶段事实:位置、目标、重要资源。
本局创作方案和变量设计决定需要哪些表,不要求每局全建。
### 10.4 大总结与清空
在输入框左侧“更多”菜单增加两个独立按钮:
**写大总结**
- 总结 Worker 读取当前保留历史和记忆表。
- 把仍有后续价值的事实更新进动态表。
- 在消息流最新处插入一层用户可见的总结层。
- 不删除任何旧楼层。
- 总结期间与表维护一样阻止发送;失败时不插入总结层,也不修改表。
**清空旧楼层**
- 只保留最新三层游玩消息,通常是最近用户输入、助手输出和总结层。
- 不要求这三层具有固定角色;按时间保留最后三层。
- 不删除动态表、源产物、静态游玩投影、开场实例或已保存快照。
- 属于显式不可逆操作,执行前显示将删除的楼层范围并二次确认。
用户通常先写大总结、确认内容,再手动清空。两步不做自动绑定,允许少量信息重复。
### 10.5 固定输入语法
输入语法固定,不放进偏好库,也不允许按局反转:
- 裸写表示上帝视角,用于提出推进、镜头、节奏和改写要求。
- 单井号成对包裹的 `#内容#` 表示角色行动。
- 中文或英文引号包裹的内容表示角色说话。
- 同一条输入可以混合三种内容。
示例:
```text
下一段加快节奏。#我推门进去#“你们在谈什么?”
```
程序拆成:
1. 上帝视角:`下一段加快节奏。`
2. 角色行动:`我推门进去`
3. 角色说话:`你们在谈什么?`
只有首尾配对的单井号才构成行动标记;未配对井号按普通裸写处理。`()`、`()`、`[]`、`【】` 不承担系统语义。
### 10.6 动态拓扑状态
`拓扑图谱` 用于“只生成一个、但普通无规则实例不足以表达”的结构对象,例如一张迷宫地图、一所学校的固定空间、一棵升级树或一条人物关系链。
它不是 0 层卡专属产物,而是开场后仍可修改的运行备忘录。普通楼层和 0 层卡共享同一份权威拓扑状态,只采用不同的显示入口。
创作期:
- 每个 `设计.拓扑图谱#id` 只定义一张图;能力可反复建立不同图。
- 产物定义节点/连接字段、初始结构、扩展规则,以及 `static | record | expand` 动态模式。
- 图数据与显示分离:拓扑节点只管权威结构,不要求提前实现渲染;是否显示、显示在哪里及采用何种形式,全部留给后续「正文组成」决定。
游玩期:
- 从设计图初始化 `运行.拓扑#id`,保存节点、连接、当前位置/当前焦点、发现状态与 `revision`。
- 新增 `topology.patch.v1`:支持增改删节点与连接、移动当前位置、揭示隐藏内容;带 `base_revision`,整批原子校验,禁止悬空连接。
- 设计产物声明允许的写入者和可编辑字段;程序、维护副 Worker 或用户都必须通过同一 patch 与 revision 冲突检查修改,不能直接覆盖整张图。
- 主世界层负责写正文事实,不在用户可见正文中夹带拓扑维护块。由正文事实产生的探索、关系等变化,在回合末交给统一维护副 Worker 记录。
- 确实必须先改状态再写正文的机械操作标为 `pre_narrative`;其余默认 `post_narrative`,不得为了拓扑一律增加前置调用。
- 语义位置属于图真相;纯显示坐标、缩放和折叠状态另存 `运行.拓扑布局#id`。
- 若「正文组成」决定展示,渲染器与壳一样在创作期生成一次并固定。游玩只把 `运行.拓扑` 的节点与连接灌入该渲染器出图。模型不输出 SVG,壳也不写死一份地点名单。普通楼层放在辅助区或标签页,0 层卡投影到 `data` 槽。未决定展示时只保存备忘录。
当前已有的“表格”只支持 `变量.当前` 的扁平键值格和逐格 revision,不支持多张任意表、节点/连接或拓扑 patch。因此不能直接把现有表格当成拓扑实现;可复用其 revision、用户编辑和冲突保护思路,但只先新增独立的拓扑存储与更新接口。显示入口等「正文组成」实际选用后再实现。
验收:
- 已访问节点和连接跨轮、刷新与 run 快照保持稳定。
- 返回旧地点时只能沿已持久化连接,不重新生成冲突结构。
- 旧 revision patch 被拒绝;非法 patch 不产生半次更新。
- 固定学校地图保持稳定相对位置;动态迷宫只追加已探索部分。
- 是否展示不影响存储;切换呈现模式不迁移或复制图数据。
### 10.7 随机数就是隐藏变量
随机数不另建表,也不另做协议。它是现有 `变量.当前` 里的行,玩家默认不可见,行名用「名称.随机数」,例如 `敏捷.随机数`、`攻击.随机数`。
这一行的值是还没用的数字。用掉第一个,就改写这一行;只剩 1 个时补到预备个数。程序出数,模型不编。重 roll 跟着这张表现有的检查点恢复。
与呈现模式的关系:
- **0 层卡**:创作与开场不写依赖随机数才能成立的玩法。开场落库时不应出现「没有随机数可用」的阻塞。
- **普通楼层**:随机行在第一次正式游玩回复前由程序按合同填入;若开场未预填,第一次回复也会正常补齐,不要求开场模型写出具体骰面。
## 11. 能力提示同步清单
| 文件 | 改动 |
| --------------------------------------- | -------------------------------------------------- |
| `modules/catalog.yaml` | 新增 `creation-plan`;增加默认 `layer`、`mount`;绑定库保持目录级声明 |
| `modules/creation-plan/prompt.md` | 新建本局配方 + 能力分档产物 |
| `modules/reply-format/prompt.md` | 读取新壳参考,生成前端与数据契约;删除渲染字段默认空 |
| `modules/opening-setup/prompt.md` | 按正文组成的数据契约输出 `present.v1` |
| `modules/narrative-guide/prompt.md` | 从文风库选 1~2 项并本局化 |
| `modules/story-progression/prompt.md` | 从偏好库选 1~2 项,钉输入用法与停笔边界 |
| `modules/variable-design/prompt.md` | 增加按需建立记忆表及维护方式 |
| `modules/*/prompt.md` | 按 §9 逐节点确认,迁移 `score` fence |
| `src/dictate/prompt.ts` | 方案驱动、读取工具、自然回复,删除固定路径与重复禁令 |
| `src/dictate/insert-feedback.ts` | 只提供关注点、缺口和启发,不生成固定回复模板 |
| 旧对话落盘配方 | 修订为本局创作方案可读取的案例 |
| `src/dictate/play-bind.ts` | 编译游玩投影,跳过中间层,按 Worker 分发 |
| `worker-templates/world-simulator.yaml` | 按固定输入语法解释裸写、`#行动#` 与引号;只读取自己的投影 |
| `worker-templates/narrator.yaml` | 按数据契约输出各块,只读本局文风选择 |
| `worker-templates/auditor.yaml` | 按统一维护合同处理变量、拓扑、补实例与可变备忘录;默认空操作 |
写提示词时遵循 `prompt-writing` 技能口径。
## 12. 实施顺序
```text
扫尾旧配方提示
→ 本局创作方案 + 旧配方案例化
→ read_module / read_library_entry
→ layer / self_score / 自然回复
→ 剩余非工具节点逐项审阅
→ 按复杂度选择维护策略;仅 auditor_bundle 运行 maintenance-compile
→ 游玩投影编译
正文体验分类讨论
→ 壳参考库重建
→ 源「回复呈现 / 正文组成 / 开场白」审阅完成
→ 复制 0 层呈现链
→ iframe、普通 present.v1 与 0 层 slot_updates
→ 0 层卡持久化、正则兼容层与“重 roll 本轮”
动态表规格
→ topology.patch.v1 与运行拓扑
→ 副 Worker 默认维护与输入阻塞
→ 上下文顺序调整
→ 大总结 / 清空旧楼层
→ 固定输入语法解析
```
实施约束:
- 非工具节点严格执行 §9;程序基础设施可以按工作包集中实现。
- 先完成游玩投影再允许新产物直接开玩,避免继续污染运行上下文。
- 具体实例当前保持全量注入;本阶段不做 RAG。
- 旧七壳在新参考库和安全回退渲染就绪后删除。
## 13. 决策状态
- [x] 本局创作方案引用 4 份已修订案例:快穿短局、数据化跑团体验、文本生成器、交互式长文生成器;删除“正文组成”案例。
- [x] 删除独立的“用户需求”节点;偏好库、文风库改由相关节点绑定并通过 `read_library_entry` 按需读取。
- [x] 生成规则:名称/用途→字段→池或提示→填写工作流;两份以上,或一份但字段多、需要先审字段与工作流时使用;一条字段很少的具名内容通常不建规则也不落实例;一产物一条规则;`只预生成` 为中间层。不因开场后是否继续生成而改道。
- [x] 具体实例:按规则填一条记录,一份产物一条;写入多条时程序按记录拆开。无规则只留下用户点名的一条字段很少的内容。给人读的键和专名用中文,英文专名音译。
- [x] 叙事指南:读文风库 1~2(最多 3)并本局化;产物用风格推荐与要求,少禁多做;推进仍归故事推进+偏好库。
- [x] 故事推进:全局唯一输入用法;一次输出单轮目标字数及扩写/续写定义、占比和字数预算;含 OOC 处理策略;其它节点不重复定义篇幅。
- [x] 实现机制:一个产物可含多条共同作用的稳定因果;用于推演事件与人物反应;缺失后果只作内部移除检验。
- [x] 库种子:`seeds/libraries/*.json` 进 git;`libraries:restore` / `libraries:export`。
- [x] 0 层卡:开场气泡内的持久前端;正文也是槽位,每轮就地更新;内部历史仍逐轮保存。
- [x] 双呈现链:所有源节点审阅完成后,只复制 `回复呈现 / 正文组成 / 开场白与开场变量`;内容能力共用。
- [x] 动态拓扑方向:一产物一张图,运行期用版本化 patch 持久扩展;它是呈现无关的可变备忘录,是否渲染完全由正文组成决定;节点提示已迁移。
- [x] 维护分流:简单状态优先原生 `update_state` tool call;工具不可用时按 profile 能力走结构化整包;运行期变量维护不依赖正则;复杂维护才编译合同并启用副 LLM。
- [x] 普通回复呈现:只定义实际启用的语义区域、出现条件、权威来源与内容要求;内联变量更新作为隐藏语义区,具体投递由 API 能力选路;篇幅只归故事推进。
- [x] 随机数:现有变量表里的隐藏行,行名为「名称.随机数」;用掉一个就改行,只剩 1 个时补。
- [x] 普通正文组成:把回复呈现的可见区域落成完整 HTML/CSS/JS、`present.v1` 数据契约和区域渲染;隐藏维护区不进 DOM,权威数据只由程序投影。
- [x] 普通开场白:默认 1 条(用户要求时 2~3);全部保存,默认条开玩;每条自带初态与可选角色;不写随机数具体值。
- [x] 0 层与随机:0 层不写依赖随机的玩法;随机行在第一次正式回复时由程序补齐。
- [x] 0 层“重 roll 本轮”复用消息前 checkpoint;暂不实现任意历史回退。
- [x] 壳按展示的区分类。参考壳三种称呼:阅读、正文为主、数据常驻。正文为主把短文和地图收进标签或折叠;数据常驻把数据一直摊开。选项始终直接可见。隐藏变量更新不进壳。
- [ ] 各最终能力的 `mount` 和字段投影允许列表。
- [ ] 文风库、偏好库条目 schema,以及临时条目回写全局库的权限。
- [ ] “清空旧楼层”是否提供快照恢复;当前方案按不可逆二次确认处理。
- [ ] 生图任务的独立输出契约和插入时机;不纳入本轮执行范围。
## 14. 剩余执行清单
按依赖顺序继续:
1. **完成内容节点审阅与迁移**
- [x] `topology`:一产物一张图、扩展合同和五维评分。
- [x] `variable-design`:真值、更新规则与维护复杂度判据。
- [x] `status-bar`:普通楼层版语义区域、权威来源与隐藏更新区。
- [x] `random-range`:变量表隐藏随机行、预备个数与补数规则。
- [x] `reply-format`:普通楼层版前端、区域落点与数据契约。
- [x] `opening-setup`:普通楼层开场候选、初态、角色与收口。
2. **完成共用运行工具审阅**
- 运行时固定顺序:用户需要填写的内容节点全部完成 → 单独调用 `prepare_opening` → 信息可见范围 → 游玩执行方式 → 上下文排序 → 运行配置组装 → 下一步才生成并写入开场白。开场候选选定后只落初态并重投影,不首次创建运行配置。
- [x] `variable-context / 信息可见范围`:程序从上游公开性、秘密与揭示声明编译谁能看到什么;不另造状态摘要。
- [x] `worker-spec / 游玩执行方式`:程序整理前面已经确认的独立转述、复杂维护、秘密隔离或写手路径需求,只选择固定执行单元。
- [x] `context-order / 上下文排序`:程序先按变化频率分组,再在同组内按重要性排列;稳定前缀在前,历史居中,当前状态与本轮输入靠后。
- [x] `refine / 运行配置组装`:把执行方式、上下文排序、变量表与所选呈现合同打包成运行期读取的 `设计.worker集`;不承担正文润色。
- [x] `narrative` 仅服务旧工序编排,不属于本轮对话落盘迁移。
3. **完成 0 层呈现链**
- [x] 为 `回复呈现 / 正文组成 / 开场白与开场变量` 建 0 层版本,确定 id、artifact tag、目录声明和测试。
- [x] 扩展本局创作方案,使普通楼层与 0 层卡互斥选型。
- [x] 定义 `zero-layer.card.v1`、`zero-layer.update.v1`、`slot_updates`、三种更新方式和初始槽位状态。
4. **实现游玩投影与运行合同**
- [ ] 把四个共用运行工具全部改为确定性程序调用;旧工序路径不得再用 LLM 猜执行槽、上下文顺序或最终运行配置。
- [ ] 实现 `none / inline_tool / inline_structured / auditor_bundle` 维护策略选择,并复用 profile 能力探测。
- [ ] 扩展代表性状态工具探测;实际 strict schema 被拒绝时降级为非 strict tool + 本地校验。
- [ ] 为简单变量新增受白名单、操作范围和 revision 约束的 `update_state` GM tool。
- [ ] 新增条件式 `maintenance-compile`,只为 `auditor_bundle` 产出 `maintenance-manifest.v1`。
- [ ] 编译最终产物的字段白名单和 Worker 分发,剥离评分、追问与中间层。
- [ ] 运行期生成精简 `maintenance-context.v1`,扩展 `maintain.v2` 的表、拓扑、补实例和备忘录操作。
- [ ] 普通楼层输出 `present.v1`;0 层模式输出槽位更新。
- [ ] 保持旧书、旧多规则产物和旧呈现数据可读。
5. **实现动态拓扑**
- [ ] `topology.v1`、`topology.patch.v1`、revision 与原子校验。
- [ ] 运行图、写入者权限、用户编辑,以及默认由回合末副 Worker 维护。
- [ ] 本阶段不预做图谱 UI;后续正文组成选择展示时,再实现所需入口和渲染器。
6. **实现前端与重 roll**
- [x] 重建壳参考库:`shell-refs/` 五只壳供正文组成与 0 层正文组成读取。隔离 iframe 与自定义 blocks 运行时尚未接入。
- [ ] 0 层持久前端、Tab、槽位重放与正则兼容适配器。
- [ ] “更多操作”增加“重 roll 本轮”;恢复 checkpoint 后重新生成,不提供任意历史回退。
- [ ] 新前端和安全回退就绪后删除旧七壳。
7. **实现长程运行能力**
- [ ] 动态二维表与副 Worker 维护阻塞。
- [ ] 随机数行:在 `变量.当前` 增加「名称.随机数」隐藏行;用掉队首就改行;只剩 1 个时补数。
- [ ] 稳定前缀、可变表和对话的上下文顺序。
- [ ] 写大总结、清空旧楼层及二次确认。
- [ ] 固定输入解析:裸写 OOC / 上帝视角、`#行动#`、引号对话。
8. **最终验收**
- [ ] 普通楼层与 0 层模式端到端测试。
- [ ] 重 roll、续作、run 快照、分支和拓扑持久化测试。
- [ ] 全量测试、lint、构建基线与迁移文档。