diff --git a/docs/architecture.md b/docs/architecture.md index 07868b7..c57b008 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -249,11 +249,11 @@ Context Trace 是排查泄漏的主工具(契约已定,实现渐进)。 | 运行内核 | `runtime-state-machine.md`、`tool-contracts.md`、`context-assembly.md`、`tag-blackboard.md` | | 持久化 | `book-storage.md`、`run-snapshot.md` | | UI | `ui-design.md`、`ui-glossary.md` | -| 实现顺序 | `implementation-guide.md` | +| 写代码规则 / 文档地图 | `implementation-guide.md` | | **产品体验路线** | **`px-roadmap.md`**(PX0–PX5 交付与 DoD) | | **日常场景 → P0** | **`daily-use-p0.md`**(场景、功能表、P0 工作包) | | 外部参考 | `references.md` | -| **工作流计划 / 创作方法(非系统架构)** | `design-orchestrator-guide.md`、`creation-playbook.md`、`world-simulator-modules.md` | +| **工作流计划 / 创作方法(非系统架构)** | `design-orchestrator-guide.md`、`creation-playbook.md`、`world-simulator-modules.md`、`progressive-data-design.md`、`context-fragment-design.md`、`play-presentation-shells.md`、`play-dm-auditor.md` | | **Skill 包格式(非系统架构)** | `skill-format.md`、`orchestrator-skill-format.md`、`worker-skill-format.md`、`skill-design-guide.md`、`preset-format.md` | | **技能撰写交接** | `briefs/capability-authoring-brief.md` | diff --git a/docs/briefs/capability-authoring-brief.md b/docs/briefs/capability-authoring-brief.md index 7f96bb5..50685c1 100644 --- a/docs/briefs/capability-authoring-brief.md +++ b/docs/briefs/capability-authoring-brief.md @@ -191,13 +191,13 @@ catalog 登记(短声明给编排看;可选 repeatable) | 交付物 | 路径 | 给谁看 | |--------|------|--------| | 目录行 | `modules/catalog.yaml` 一行 | 索引、`repeatable`、编排 `params` | -| 方法全文 | `modules/{id}/prompt.md` | 执行该步的 LLM + 程序切割;**编排读 `meta` 的 when/when_not/boundary** | +| 方法全文 | `modules/{id}/prompt.md` | **规划**读 `meta`(declaration / when / when_not / boundary);**执行**读切割后的 task/opening/output | 编排时注入能力 **meta 选型字段**(非全文 prompt);执行时才注入切割后的方法块。 ## 3.4 能力之间如何相处 -- **正推**:需要 [体验/产物] → 才纳入某技能;勿默认全选池内能力。 +- **正推**:需要 [体验/产物] → 才纳入某技能;勿默认全选池内能力。调用条件写在该技能 `when` / `when_not`,不要写进规划 SKILL 或配方 process。 - **边界**:每个能力在 `meta.boundary` 写清「本步定什么 / 不定什么 / 交给谁」。 - **依赖**:由工作流计划 `depends_on` 声明;执行期程序注入对应产物。 - **合并**:询问主题高度重叠 → 合成一个能力(如美学+交互)。 @@ -206,7 +206,7 @@ catalog 登记(短声明给编排看;可选 repeatable) ## 3.5 方法层硬禁止(写任何能力都适用) - 题材 → 固定执行单元清单。 -- 否定式路由(「因为是 X 所以不需要 Y」);应写「需要 A 体验 → 用 B 手段」。 +- 否定式路由(「因为是丧尸题材所以不需要舞台骨架」);应写「需要 A 体验 → 用 B 手段」。技能 `when_not` 指向另一个技能或「不排」不算否定式路由。 - 把「世界模拟」当成一切开场的默认答案。 - 为排版/格式单独发明执行单元;能程序拼则程序拼。 - 临时发明 tool。 @@ -305,14 +305,34 @@ boundary: | ## 4.3 `meta` 字段 -| 字段 | 含义 | -|------|------| -| `name` | 固定中文名(= 流程 `steps[].name`) | -| `id` | 英文 id(= 目录名) | -| `artifact` | 本步写入的黑板 tag | -| `declaration` | 给编排看的短声明(不是全文) | -| `when` / `when_not` | 何时该/不该入选工作流计划 | -| `boundary` | 与邻接能力的分工 | +`meta` 是 **规划 LLM** 选型用的短文;执行 LLM 看不到这段当任务说明书(它读 `task` / `opening` / `output`)。 + +| 字段 | 含义 | 怎么写 | +|------|------|--------| +| `name` | 固定中文名(= 流程 `steps[].name`) | 与 catalog 完全一致 | +| `id` | 英文 id(= 目录名) | kebab-case | +| `artifact` | 本步写入的黑板 tag | | +| `declaration` | 规划扫描池时的第一眼 | 解决什么缺口;不要写产物 JSON 形状 | +| `when` | **现在**要不要进近期 DAG | 对照用户话、已验收步骤、已有产物就能判定的信号。例:还不能回答哪三句;已有哪份产物仍缺什么 | +| `when_not` | 不该进图 | 每条指向另一个技能或「不排」。缺替代去向的「不要」规划用不上 | +| `boundary` | 与邻接能力的分工 | 本步定什么 / 不定什么 / 交给谁 | + +**错(规划无法判定,几乎任何局都会排):** + +```text +when: 已有美学纲领,需要把感觉落成可执行的写法与推进时。 +``` + +**对:** + +```text +when: | + 已有美学纲领,但转述仍会不知道遣词/笔墨落点/绝对禁忌/故事靠场面还是等用户时才排。 +when_not: | + 用户只要感觉不要文风细则 → 不排,沿用美学。 +``` + +不要把 `task` 的执行顺序写进 `when`。配方 `process` 不要再抄一份调用条件。 ## 4.4 `catalog.yaml` 一行 @@ -418,7 +438,7 @@ task 必须写:禁止重复同一开场;在首答上补洞。 # 第五部分:撰写任一能力时的工作步骤 -1. **定身份**:中文名、id、artifact;写清 when / when_not / boundary。 +1. **定身份**:中文名、id、artifact;按规划视角写 when / when_not / boundary(可判定信号,不是执行细则)。 2. **看邻接**:上/下游能力各定什么;禁止重叠问卷。 3. **定产物形状**:先定 `output` JSON(中段须含 §4.9 公共头),再写 task/probe 如何填满它。 4. **定 opening**:需要程序先问再 LLM → 写 opening;否则留空。 diff --git a/docs/briefs/design-flow-prompt-review.md b/docs/briefs/design-flow-prompt-review.md new file mode 100644 index 0000000..e6c3b47 --- /dev/null +++ b/docs/briefs/design-flow-prompt-review.md @@ -0,0 +1,900 @@ +# design-flow 提示词人工审查 + +规划 LLM(`design-flow`)一次请求里会拼上:**本 worker 的 SKILL 正文** + **程序注入的固定句** + **已选配方** + **全部技能 meta**。 +本文把这些静态提示词收齐,供你逐段审查。改源文件后请同步改本文,或重新生成。 + +用法:每条把 `☐ 未审查` 改成 `☑ 已审查`(可在后面加日期/一句批注)。 +不含:`design-step` 执行全文、`opening`/`task`/`output`、游玩模板、编排器 `orchestrator.md`(那是另一颗 LLM)。 + +权威路径以各节「源文件」为准。`feeds` 写在 meta 里,但 **不会** 注入 design-flow。 + +--- + +## 总表 + +| # | 条目 | 源文件 | 人工审查 | +|---|------|--------|----------| +| 1 | design-flow SKILL 正文 | `skills/dialogue/world-simulator/workers/design-flow/SKILL.md` | ☑ 已审查 2026-09-06:用户会在意美学卡哪几处 → 节点与 suggestion;同一题材换核换图 | +| 2 | 上下文块标题(contextSegments.label) | `skills/dialogue/world-simulator/workers/design-flow/SKILL.md` frontmatter | ☑ 已审查 2026-09-06:【开头节点】按用户会在意的部分选节点;已验收=id 清单 | +| 3 | 【流程进度】固定句 | `src/skills/creation-flow.ts` → `formatFlowProgressForAgent` | ☑ 已审查 2026-09-06:改成清单怎么用;禁止句改成要干嘛;与 SKILL 对齐 | +| 4 | 【用户已选配方】外壳 | `src/skills/creation-flow.ts` → `formatSelectedRecipeForAgent` | ☑ 已审查 2026-09-06:去掉只排近期;对照美学卡承诺增删;换配方改成要干嘛 | +| 5 | 未选配方时的三句 | (已删)`src/skills/creation-flow.ts` → `formatDesignFlowContentBlocks` | ☑ 已删除 2026-09-06:开局必选配方,不再注入问选用兜底 | +| 6 | 【能力 · 可选工序】外壳 | `src/skills/creation-flow.ts` → `formatModuleCatalogForAgent` | ☑ 已审查 2026-09-06:只收集各节点 meta;调用条件不在外壳 | +| 7 | 配方目录短声明 | `skills/dialogue/world-simulator/recipes/catalog.yaml` | ⏭ 跳过:人工手选列表,不进规划提示词 | +| 8 | 配方 · 世界模拟器 | `skills/dialogue/world-simulator/recipes/world-simulator/recipe.yaml` | ☑ 已审查 2026-09-06:怎么排跟 SKILL;去掉 1~4;禁止句改成要干嘛 | +| 9 | 配方 · 扩写助手 | `skills/dialogue/world-simulator/recipes/expand-assistant/recipe.yaml` | ⏭ 跳过 | +| 10 | 技能 meta · 美学纲领与交互范式 | `skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md`(meta) | ☑ 已审查 2026-09-06:声明改成体验承诺;when 去掉近期/可玩套话 | +| 11 | 技能 meta · 实现机制 | `skills/dialogue/world-simulator/modules/mechanism/prompt.md`(meta) | ☑ 已审查 2026-09-06:第一初设定;无特殊变造才不排 | +| 12 | 技能 meta · 舞台骨架 | `skills/dialogue/world-simulator/modules/world-blueprint/prompt.md`(meta) | ☑ 已审查 2026-09-06:会换区才备案;代入后几乎不移动(网聊/门卫室)不排 | +| 13 | 技能 meta · 生成规则 | `skills/dialogue/world-simulator/modules/generation-rules/prompt.md`(meta) | ☑ 已审查 2026-09-06:时机 a 精准格式或时机 b 原创会雾且还要生成,满足一条就排 | +| 14 | 技能 meta · 具体实例 | `skills/dialogue/world-simulator/modules/concrete-instances/prompt.md`(meta) | ☑ 已审查 2026-09-06:用户确认基本没问题;已有预生成规则才排,不改合同 | +| 15 | 技能 meta · 叙事指南与故事推进 | `skills/dialogue/world-simulator/modules/narrative/prompt.md`(meta) | ☑ 已审查 2026-09-06:用户确认基本可以 | +| 16 | 技能 meta · 拓扑图谱 | `skills/dialogue/world-simulator/modules/topology/prompt.md`(meta) | ☑ 已审查 2026-09-06:必须生成且不适合走生成规则→实例;用拓扑结构描述 | +| 17 | 技能 meta · 变量设计与更新规则 | `skills/dialogue/world-simulator/modules/variable-design/prompt.md`(meta) | ☑ 已审查 2026-09-06:用户确认完成 | +| 18 | 技能 meta · 变量控制上下文 | `skills/dialogue/world-simulator/modules/variable-context/prompt.md`(meta) | ☑ 已审查 2026-09-06:用户确认完成 | +| 19 | 技能 meta · 正文组成 | `skills/dialogue/world-simulator/modules/reply-format/prompt.md`(meta) | ☑ 已审查 2026-09-06:展示回复呈现清单;选壳+美化,可写 CSS/HTML/JS | +| 20 | 技能 meta · 回复呈现 | `skills/dialogue/world-simulator/modules/status-bar/prompt.md`(meta) | ☑ 已审查 2026-09-06:必选/可选区域 + 各区简单内容规则(含选项组成) | +| 21 | 技能 meta · 游玩拓扑 | `skills/dialogue/world-simulator/modules/worker-spec/prompt.md`(meta) | ☑ 已审查 2026-09-07:主世界必要;有变量开旁观;取消机遇槽→随机范围整理 | +| 22 | 技能 meta · 上下文投影排序 | `skills/dialogue/world-simulator/modules/context-order/prompt.md`(meta) | ☑ 已审查 2026-09-07:用户确认;已去机遇槽残留 | +| 23 | 技能 meta · 细化终稿 | `skills/dialogue/world-simulator/modules/refine/prompt.md`(meta) | ☐ 未审查 | +| 24 | 技能 meta · 开场白与开场变量 | `skills/dialogue/world-simulator/modules/opening-setup/prompt.md`(meta) | ☐ 未审查 | +| 25 | 技能 meta · 随机范围整理 | `skills/dialogue/world-simulator/modules/random-range/prompt.md`(meta) | ☑ 已写入 2026-09-07:正文组成前汇总随机项与范围;待你过目可再改 | + +--- + +## 一、design-flow worker + +### 1. SKILL 全文 + +人工审查:☑ 已审查 2026-09-06:怎么排=用户会在意美学卡哪几处 → 哪些节点/suggestion 兑现;同一题材换核换图 + +源:`skills/dialogue/world-simulator/workers/design-flow/SKILL.md` + +~~~~ +--- +id: design-flow +skill: world-simulator +name: 创作 · 流程编排 +description: >- + 【编排】从美学卡上用户会在意的部分推出要哪些节点、节点建议写什么;对照已完成 id。 + 产出工作流计划 DAG。用户在图上点选执行顺序。本步不写各技能正文。 +version: 1 +stage: design +inputTags: + - "用户.需求" + - "book.brief" + - "用户.最新输入" + - "用户.worker答复" + - "用户.修订说明" + - "设计.美学纲领与交互范式" + - "设计.创作流程" + - "创作.选用配方" + - "创作.已验收单位" +outputTags: + - "设计.创作流程" +inputMerge: latest +contextSegments: + - id: opening-aesthetics + tier: static + tags: ["设计.美学纲领与交互范式"] + label: "## 【开头节点 · 美学纲领】用户会在意这张卡的哪几处?用那些承诺选节点(无则先排本步)" + - id: accepted-units + tier: static + tags: ["创作.已验收单位"] + label: "## 【已验收步骤】已完成节点的 id 清单(只作覆盖标记,不是各步正文)" + - id: prior-flow + tier: static + tags: ["设计.创作流程"] + label: "## 【已有工作流计划】在其上修订;无则新建" + - id: selected-recipe + tier: static + tags: ["创作.选用配方"] + label: "## 【用户已选配方】只读引用" + - id: user-demand + tier: dynamic + tags: ["用户.需求", "book.brief", "用户.worker答复"] + label: "## 用户表述" +--- + + + +# 创作 · 流程编排 + +读【开头节点 · 美学纲领】里**用户会在意的部分**,推出要哪些节点、节点建议写什么;对照【已验收步骤】标记,从【能力 · 可选工序】排出一份 **工作流计划 DAG**,写入 tag `设计.创作流程`。无美学卡时用【用户要求】当种子。 + +产出:节点 + `depends_on` +(〔可反复〕)原型槽位与 `suggestion` + 可选顶层 `suggestions`。用户在图上点选下一步;你给出依赖与建议阅读序。 + +先读【流程进度】(已完成 / 草案已有 / 尚未编入)、【用户已选配方】、【能力 · 可选工序】,再排。要求按先后都有效,冲突时以较新的为准。 + +## 怎么排 + +先当用户看这张美学卡:**我会在意哪几处?** 那几处是本局要兑现的承诺。再问:兑现每一处,要哪些技能节点、节点里建议写什么?已完成 id 表示那一处已经有槽。 + +同一题材,卡上在意的东西不同,图和 suggestion 就不同。例如都是丧尸末日: + +- 核是异能觉醒、升级、对抗(网文)→ 生成规则写异能/等级合同,变量盯等级与觉醒,叙事管打脸与对抗节奏 +- 核是人与人背刺(美式)→ 具体实例锚定开局几个人,叙事管背叛与信任,变量控制管信任度和资源缺口;舞台可以很薄 +- 核是砍砍砍(B 级片)→ 生成规则写可砍的尸群,叙事管血腥动作笔墨;等级、背刺、复杂社会可以不排,反倒是武器生成规则需要仔细斟酌 + +题材名(丧尸、都市、宫廷)本身不决定套件。用户会反复感到的那几处才决定。 + +无美学卡:体验尚未钉清,先排「美学纲领与交互范式」;其余只排此刻能从【用户要求】看出用户在意什么。美学已验收之后,按这些承诺把该排的节点写进 `steps`——需要几步排几步。 + +选定节点时对照【能力 · 可选工序】的何时用 / 何时不用 / 边界:这份承诺该由哪个技能兑现。配方 `core` / `process` / `principles` 给方法顺序(默认槽、收成链),不代替「用户在意什么」。含糊或可跳过则不排。已在草案里的 `name` 保留,一次性技能不写第二份。能力池里兑不了那处承诺:不发明新 `name`,askUser 问用户改体验还是放弃那一处。 + +用户要补节点:插在未验收步之前、收口之前,`status: "open"`。新 `name` 只从【流程进度】「尚未编入、仍可调用」里选。 + +〔可反复〕的 `suggestion` 必须点名这局在意的对象(异能合同 / 开局背刺对象 / 可砍尸群),不要写成空泛的「NPC 与物资」。本局还可能用到、但暂时不写进 `steps` 的:写入顶层 `suggestions`。已在 `steps` 里的不重复。暂时不必则省略。 + +## 节点怎么写 + + +| 类型 | JSON | 进入执行 | +| ---- | ----------------------------------------- | ---------------------------------- | +| 普通一步 | 无 role | 用户点上 → design-step | +| 原型槽位 | `"role": "prototype"` + `suggestion` | 用户点上 → 程序增殖 instance → design-step | +| 实例 | `"role": "instance"`, `"from": "<原型 id>"` | 仅程序增殖 | + + +〔可反复〕(生成规则、具体实例等):`steps` 里写一条原型即可(id 通常与 name 相同,如 `"生成规则"`),并写 `suggestion`(建议这条原型将来生成什么)。原型只带 `suggestion`;「写什么」在用户点原型后的实例步内钉。 + +已完成节点要改:用户在图上点该节点重进。编排只追加未验收步、改未验收依赖;已验收 id 原样留在 `steps`。 + +〔收口〕「开场白与开场变量」排在 `steps` 最后。选定开场前若要补前序节点,插在收口之前,保持收口为最后一步,`status` 仍为 `"open"`。 + +askUser 只问排布(补哪个原型、改依赖)。用户谈到体验正文:当作编排线索;体验细节留到对应技能步。排布已能写清则直接产出。 + +## 产出 + +根对象就是下面这份 JSON(必须含 `steps`)。 + +```json +{ + "brief": "代入觉醒者,反复感到升级碾压与对抗", + "status": "open", + "suggestions": [ + { + "name": "具体实例", + "suggestion": "开局 1 个对照用的未觉醒同伴", + "depends_on": ["生成规则"] + } + ], + "steps": [ + { "id": "美学纲领与交互范式", "name": "美学纲领与交互范式", "depends_on": [] }, + { + "id": "生成规则", + "name": "生成规则", + "role": "prototype", + "suggestion": "异能觉醒与升级合同", + "depends_on": ["美学纲领与交互范式"] + }, + { + "id": "变量设计与更新规则", + "name": "变量设计与更新规则", + "depends_on": ["美学纲领与交互范式"] + }, + { + "id": "叙事指南与故事推进", + "name": "叙事指南与故事推进", + "depends_on": ["美学纲领与交互范式"] + }, + { + "id": "细化终稿", + "name": "细化终稿", + "depends_on": ["生成规则", "变量设计与更新规则", "叙事指南与故事推进"] + }, + { + "id": "开场白与开场变量", + "name": "开场白与开场变量", + "depends_on": ["细化终稿"] + } + ] +} +``` + +1. `steps` 顺序 = 建议阅读顺序;`depends_on` 指向更前步骤 id +2. `name` = 能力池固定中文名 +3. `id` 本局唯一;原型 id 稳定(如 `生成规则`);实例 id 由程序增殖(`生成规则#1`…) +4. 具体实例原型依赖生成规则原型(至少一条规则实例验收后才可增殖) +5. `summary`:`流程 · N 步 · open|closed · …` + + + +## 自检 + +- 节点和 `suggestion` 是否兑现卡上用户会在意的那几处(同一题材换核会换图),而不是题材默认套件? +- 已验收 id 是否都在 `steps` 里? +- 〔可反复〕是否都是 `role=prototype` + suggestion? +- 尚未编入里本局还可能用到的〔可反复〕是否进了 `suggestions`? +- 收口是否在最后?`depends_on` 是否合法? +~~~~ + +### 2. 上下文块标题 + +人工审查:☑ 已审查 2026-09-06:【开头节点】按用户会在意的部分选节点;已验收=id 清单;工作流计划 + +拼进 prompt 的 Markdown 标题(frontmatter `contextSegments.label`)。后面跟黑板 tag 正文,不在此审查。 + +~~~~ +## 【开头节点 · 美学纲领】用户会在意这张卡的哪几处?用那些承诺选节点(无则先排本步) +## 【已验收步骤】已完成节点的 id 清单(只作覆盖标记,不是各步正文) +## 【已有工作流计划】在其上修订;无则新建 +## 【用户已选配方】只读引用 +## 用户表述 +~~~~ + +--- + +## 二、程序注入(固定句) + +源:`src/skills/creation-flow.ts`。带 `{…}` 的是按现场填的,审查时看固定句。 + +### 3. 【流程进度】 + +人工审查:☑ 已审查 2026-09-06:清单怎么用;禁止句改成要干嘛;与 SKILL 对齐 + +~~~~ +【流程进度】程序按现场列出:已完成、草案已有、原型槽位、尚未编入。编排以这份清单为准。 +已完成 = 覆盖标记(原 id 留在 steps);草案已有 = 保留原 id,在其上追加或改未验收依赖;尚未编入 = 新 name 只从这里选。 +〔可反复〕在 steps 里写一条 role=prototype,带 suggestion(点名这局在意的对象)。「写什么」在用户点原型后的实例步里钉。 +一次性技能已覆盖的那一面:要改则用户点该节点重进。要改已有实例:用户点该实例重进。点原型增殖 = 全新 instance(role=instance,from=原型 id)。 + +(以下段落按现场拼装,审查固定句即可) +草案已有〔收口〕「…」但尚未选定。用户要补节点时:把新步插在收口之前,保持收口为最后一步,并将 status 改回 open。收口已排入仍可在它前面加步。 + +已完成:尚无已验收步骤。草案里的开局步是配方预置起点,保留原 id。 +已完成: +- {name}(id: …) · 已验收|产物已在黑板 〔可反复:… / 一次性:这一面已覆盖;要改则用户点该节点重进〕 + +草案已有、尚未验收(保留原 id): +- {name}(id: …) · 已在草案,保留原 id + +原型槽位(保留;用户点增殖): +- {name}(id: …,role=prototype) · 建议:… · 保留;用户点此槽增殖 instance + +建议追加的原型(可编入 steps 为 role=prototype): +- {name} · {suggestion} · 依赖 … + +尚未编入、仍可调用(新 name 只从这里选): +- {name}〔可反复〕〔收口〕:{declaration} +尚未编入、仍可调用:无。用户只能点图上已有节点,或对〔可反复〕原型增殖。 + +目录〔可反复〕:生成规则、具体实例(排骨架时用 role=prototype) +目录〔可反复〕:以能力目录为准。 +~~~~ + +### 4. 【用户已选配方】外壳 + +人工审查:☑ 已审查 2026-09-06:去掉只排近期;对照美学卡承诺增删;换配方改成要干嘛 + +配方 `when` / `core` / `process` / `principles` / `steps` 插在此后,见第 8、9 条。 + +~~~~ +【用户已选配方 · {name}】 +这是用户手动选定的设计方法。步骤名从【能力】选。 +对照美学卡上用户会在意的部分与配方方法论,增删改未验收步骤与依赖;已验收步保留。 +能力「何时用 / 何时不用」以【能力 · 可选工序】为准;本配方不重复罗列各能力调用条件。 +用户要换配方:等用户在界面重新选定后再编排。 +简介:… +适用:… +核心思路: +… +设计流程: +- … +原则: +- … +开局 steps(配方预置起点,可按美学卡上的承诺增删): +```json +{ brief, status, steps } +``` +~~~~ + +### 5. 未选配方 + +人工审查:☑ 已删除 2026-09-06:开局必选配方,这段不再注入。 + +(原三句「用户尚未手动选择 / 禁止自行猜测 / 请 askUser 选配方」已从 `formatDesignFlowContentBlocks` 去掉。无已选配方时只不注入第 4 条外壳,不再让规划 LLM 问选用。) + +### 6. 【能力 · 可选工序】外壳 + +人工审查:☑ 已审查 2026-09-06:只收集各节点 meta;调用条件不在外壳。固定句暂留(标记怎么读)。 + +~~~~ +【能力 · 可选工序】 +按需选用,勿默认全选;步骤名只能从这里选;标〔可反复〕的可多次编入;标〔收口〕的是终节点:排在细化终稿之后作最后一步;尚未选定开场前,用户要补前序节点(如 NPC)时插在收口之前,勿以「收口已排入」拒绝追加;选定后才结束创作并保存;标〔程序步〕的确认编排后直接执行(不抛默认问题、不经同意并开始),产物仍验收。 +标〔先验产物〕(生成规则、具体实例):编排层只排 role=prototype 槽位 + suggestion;禁止在原型写 params、禁止预排 instance。「写什么」在用户点原型增殖后的实例步内钉。 +其它有「编排参数」的步骤:确认开干前写齐必填 params;缺参时用 askUser 选项+其它。 +选型依据是下方「何时用 / 何时不用 / 边界」(来自各能力 meta)。对照用户表述与已验收产物判定:该排才排;可跳过或条件含糊则不排。不要用执行细则补脑。 +〔可反复〕再编入新 id = 彻底新建一条。已完成节点要改:禁止排 mode=revise 新步;用户会在图上点该节点重进。禁止把改旧稿写成又一条 fresh。 +不要把能力执行全文塞进本步;执行由 design-step 注入。 + +(下方逐条拼接各技能 declaration / when / when_not / boundary / params;全文见第三节) +~~~~ + +--- + +## 三、配方 + +### 7. 配方目录 + +人工审查:⏭ 跳过:人工手选列表,不进规划提示词 + +源:`skills/dialogue/world-simulator/recipes/catalog.yaml` +(用户选型列表;选定后才注入第 4 条外壳 + 对应 recipe.yaml。) + +~~~~ +# 导演选项目录(用户在新建作品时手动选择;对用户称「导演」/「配方」) +# id = recipes/{id}/ 文件夹 +# name = 固定中文名(下拉展示) +# declaration = 给人看的短说明 +# 内部仍叫 recipe;勿对用户再说「配方」作第二层选项 +# recipe.yaml 写方法论:when / core / process / principles + 近期 steps +# 步骤 name 必须 ∈ modules/catalog.yaml(【能力】) +# 选定后写入黑板 tag 创作.选用配方 + +recipes: + - id: world-simulator + name: 世界模拟器 + declaration: 回合互动、世界推进、角色扮演类体验的设计方法 + + - id: expand-assistant + name: 扩写助手 + declaration: 大纲/分段写作、写手统筹、成稿向助手类体验的设计方法 +~~~~ + +### 8. 世界模拟器 + +人工审查:☑ 已审查 2026-09-06:怎么排跟 SKILL;去掉 1~4;禁止句改成要干嘛 + +源:`skills/dialogue/world-simulator/recipes/world-simulator/recipe.yaml` + +~~~~ +# 世界模拟器 · 配方 +# 写方法论:适用、核心思路、设计流程、原则。 +# 各技能何时用 / 不用 → 读技能 meta(编排器会注入),勿在此重复。 +# steps = 开局起点;选中本配方时程序写入「设计.创作流程」,开局即坐在第一步。 + +when: 回合互动、世界推进、角色扮演、沉浸推演类体验 + +core: >- + 先钉清用户如何参与、正文如何呈现、核心体验与禁忌(美学卡上用户会在意的部分); + 再按那些承诺选出要兑现的上下文技能,并标明挂哪些固定槽(默认:主世界层裁决 + 叙事转述); + 挂载归属可早定,插入顺序必须晚定——收成前用「上下文投影排序」按各块概括排出数字序与双锚点投影; + 再细化终稿收成运行规格。执行单元只用固定槽(主世界层 / 叙事转述 / 可选角色视角 / 可选机遇裁定),不为表/百科再拆槽。 + +process: + - 开始通常先做「美学纲领与交互范式」。 + - 读美学卡上用户会在意的部分,对照【能力 · 可选工序】的何时用 / 何时不用,把兑现那些承诺所需的节点写进 steps(需要几步排几步)。各技能调用条件以 meta 为准,本表不重复。 + - 世界模拟默认槽:旁观维护 + 主世界层 + 叙事转述(视角关、机遇关)。能吃默认则不必排「游玩拓扑」。 + - 中段按承诺写上下文;每块只标挂谁(mount)与稳/变,order 留给「上下文投影排序」。挂载归属:世界/机制/生成 → 主世界层;叙事指南 → 叙事转述(推进兼挂主世界层);美学进常驻。 + - 「回复呈现」几乎都排:先钉每轮看什么;「正文组成」在其后把清单展示出来(选壳、美化,可写 CSS/HTML/JS),开场白之前。 + - 收成链顺序固定:上游上下文大致齐 →「回复呈现」→「正文组成」→「上下文投影排序」→「细化终稿」→ 需要开场则「开场白与开场变量」(〔收口〕)。选定开场后结束创作并保存。 + +principles: + - 正推:美学卡上用户会在意的部分 → 缺口 → 技能。同一题材换核就换图,不按题材套世界模拟全套。 + - 技能选型以技能 meta 为准;本配方不代替各技能写调用条件。 + - 执行单元只用固定槽(主世界层 / 叙事转述 / 可选角色视角 / 可选机遇裁定)。 + - 默认少槽:主世界层 + 叙事转述;仅强信息隔离才开角色视角;骰子/抽签/比点开机遇裁定(按需程序工具,不进每轮)。 + - 挂谁可早、排第几须晚:插入序与投影位只由「上下文投影排序」产出;中段技能写 mount 与稳/变。 + - 投影序扁平:「对话.历史」按 projection 动态裁剪;少变靠前、易变靠后是软规则,不是硬分区。 + - 真值 / Data / Progressive 三分;派生性格与章细纲不落可写真值。 + - 有编排参数的步骤:进执行前钉齐 params(askUser 选项+其它);缺参时先问再进 design-step。 + - 〔可反复〕可再追加(彻底新建);已验收 id 留在 steps。 + - 舞台骨架通常都排(备案,只分详细度);代入后几乎不移动、只在一处待着则不排。实现机制对照其 meta。 + - 百科与查表归主世界层;裁决归主世界层、可见正文归叙事转述。 + +brief: 世界模拟类:美学卡上在意的部分→挂槽写上下文→晚排序投影→收成运行规格 + +steps: + - id: 美学纲领与交互范式 + name: 美学纲领与交互范式 + depends_on: [] +~~~~ + +### 9. 扩写助手 + +人工审查:⏭ 跳过(本轮先不改) + +源:`skills/dialogue/world-simulator/recipes/expand-assistant/recipe.yaml` + +~~~~ +# 扩写助手 · 配方 +# 写方法论:适用、核心思路、设计流程、原则。 +# 各能力何时用 / 不用 → 读能力 meta(编排器会注入),勿在此重复。 +# steps = 近期起点;选中本配方时程序写入「设计.创作流程」,开局即坐在第一步(不是固定全程 DAG)。 + +when: 大纲/分段扩写、写手统筹、先纲后章、成稿向助手、长文/爽文类体验 + +core: >- + 先钉清写手/统筹站位、分段轮转、爽点与禁忌; + 再落到「谁写大纲、谁写正文」的可执行规格; + 世界舞台与状态机仅在体验真需要时才引入,默认不做世界模拟全套。 + +process: + - 开始通常先做「美学纲领与交互范式」。 + - 对照【能力 · 可选工序】的「何时用 / 何时不用」选型;调用条件以技能 meta 为准。 + - 收成前若不能吃写手默认槽(大纲+章节),再排「游玩拓扑」勾选 →「细化终稿」并 closed。 + - 舞台、机制、变量、监控栏等:仅当对应技能「何时用」成立时再选,勿套世界模拟全套。 + +principles: + - 正推写手体验,勿默认套「世界模拟」全套能力。 + - 能力选型以能力 meta 为准;本配方不代替各能力写调用条件。 + - 禁止自由发明执行单元;写手路径只用 outline + chapter-writer 固定槽。 + - 有编排参数的步骤须在进执行前钉齐 params;禁止空壳进 design-step。 + - 同能力可反复编入;已验收步骤不得删除。 + - 收成前 status: closed,产物进运行规格而非散文说明书。 + +brief: 扩写/写手类:先定站位与轮转,再落到大纲→分段写文规格 + +steps: + - id: 美学纲领与交互范式 + name: 美学纲领与交互范式 + depends_on: [] +~~~~ + +--- + +## 四、技能 meta(注入【能力 · 可选工序】) + +规划只看见 `declaration` / `when` / `when_not` / `boundary` 和 catalog 标记(〔可反复〕〔收口〕〔程序步〕〔先验产物〕)及 params。 +`feeds` 与执行块不进 design-flow。 + +### 10. 美学纲领与交互范式(`aesthetics-interaction`) + +人工审查:☑ 已审查 2026-09-06:声明改成体验承诺;when 去掉近期/可玩套话 + +源:`skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md` + +~~~~ +name: 美学纲领与交互范式 +id: aesthetics-interaction +artifact: 设计.美学纲领与交互范式 +declaration: > + 钉清用户会在意的体验承诺:站位、反复感到什么、轮转何时停。询问相近故合为一步。 +when: | + 还不能回答这三件:代入还是旁观?最想反复感到什么?轮转到哪必须停等用户? + 无上游,通常作第一步。 +when_not: | + 这三件已有等价定稿、用户未要求重谈 → 不重复排入。 + 只改文风 → 「叙事指南与故事推进」;只改版式/监控 → 「正文组成」/「设计监控栏」。 + 只改舞台、规则、真值、槽位 → 对应下游技能。与「给玩家什么体验」无关 → 不排。 +boundary: | + 本技能:体验是什么、怎么发生在用户身上、轮转怎么停。产出供后续编排阅读的开头节点。 + 叙事指南与故事推进:把感觉落成遣词/笔墨/禁忌与推进——本步只钉感觉与轮转。 + 舞台骨架 / 具体实例 / 生成规则:舞台与可执行规则——本步不定。 + 实现机制 / 变量* / 监控栏 / 正文组成 / 游玩拓扑 / 上下文投影排序 / 细化终稿:落到可运行结构——本步不定。 +feeds: design_only +~~~~ + +### 11. 实现机制(`mechanism`) + +人工审查:☑ 已审查 2026-09-06:第一初设定;无特殊变造才不排 + +源:`skills/dialogue/world-simulator/modules/mechanism/prompt.md` + +~~~~ +name: 实现机制 +id: mechanism +artifact: 设计.实现机制 +declaration: > + 整体感觉已钉,故事里有必须当作既成事实的变造法则(科幻意义上的第一初设定)时:点出它们如何约束故事,不解释为何存在 +when: | + 已有「美学纲领与交互范式」或等价整体感觉,且用户表述或美学卡里有必须当作既成事实的变造法则。 + 例:现代都市但已繁荣一统、存在修炼体系;三体黑暗森林;机器人三定律。 + 特征:故事不必纠结它为什么存在,拿掉则故事骨架会换。 +when_not: | + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 没有特殊变造,或「特殊」只是身份/开场处境、能被「舞台骨架」「具体实例」「开场白与开场变量」覆盖(如现实世界模拟普通大学生)→ 不排。 +boundary: | + 本技能:点名故事当作既成事实的变造法则,写清如何约束后续;不补起源、不写舞台百科、不写人物名片。 + 美学纲领与交互范式:体验与轮转——本步不重定。 + 舞台骨架:环境与社会格局。具体实例 / 开场白与开场变量:名片与第一屏(身份特殊走它们)。 + 生成规则 / 变量* / 叙事指南与故事推进:持续生成、跨轮真值、遣词推进——本步只钉前提法则。 +feeds: gm +~~~~ + +### 12. 舞台骨架(`world-blueprint`) + +人工审查:☑ 已审查 2026-09-06:会换区才备案;代入后几乎不移动(网聊/门卫室)不排 + +源:`skills/dialogue/world-simulator/modules/world-blueprint/prompt.md` + +~~~~ +name: 舞台骨架 +id: world-blueprint +artifact: 设计.舞台骨架 +declaration: > + 本局舞台备案:划出玩家实际游玩会换区活动的主要区域并写细;尺度与详细度随体验变。代入后几乎不移动、只在一处待着则不排 +when: | + 已有「美学纲领与交互范式」或等价整体感觉,且玩家实际游玩会在划分的活动区域上发生(会换区、会移动)。 + 变造世界与现实世界都要排:只是详细度有所不同。 + 玩家实际游玩过程中的主要活动区域必须写细,但如果本身世界变造不多、或特殊设定较少(如西幻就足以概括的世界),就不需要多写。 +when_not: | + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 代入后几乎不移动:玩家只会在一处待着体验,不会走到别的活动区域(如网聊、门卫室)→ 不排。 + 可点名名片 → 「具体实例」另排。持续生成合同 → 「生成规则」。 +boundary: | + 本技能:舞台备案——范围、基底+变造、主要活动区域(写细)、社会结构、世界状况。 + 美学纲领与交互范式:体验与轮转——本步不重定。 + 实现机制:既成变造法则——本步把法则落到活动区域上长什么样,不重钉法则来源。 + 具体实例 / 生成规则 / 叙事指南与故事推进:名片、生成节奏、遣词与推进——本步不定。 +feeds: gm +~~~~ + +### 13. 生成规则(`generation-rules`) + +人工审查:☑ 已审查 2026-09-06:时机 a 精准格式或时机 b 原创会雾且还要生成,满足一条就排 + +源:`skills/dialogue/world-simulator/modules/generation-rules/prompt.md` + +~~~~ +name: 生成规则 +id: generation-rules +artifact: 设计.生成规则 +declaration: > + 要精准格式,或本局原创听了会雾且故事里还要生成时:写出该对象族怎么生成(描写/格式/可选池);不填最终实例;可按对象反复 +when: | + 已有「美学纲领与交互范式」或等价整体感觉,且下面两条满足一条就排(可按对象族反复): + a. 生成物必须有精准格式。例:武功典籍要有名字、效果、阶层。 + b. 本局原创、听了会一头雾水的东西,故事里还要随机/反复生成。例:人人能绽放的「心之彩」;当成本局原创的斩魄刀。 +when_not: | + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 常识能推、也不需要精准格式(现实名车、西幻常见种族)→ 不排。 + 只要几张具名名片、不必按规则生成 → 不排;已有规则再要名片 → 「具体实例」。 + 跨轮记住什么 → 「变量设计与更新规则」。故事怎么往前写 → 「叙事指南与故事推进」。 +boundary: | + 本技能:一条规则=怎么描写/生成 + 单层 JSON 产物格式 + 可选多池(各绑一个顶层字段)。 + 具体实例:按规则填最终 records;本步不写最终实例(池条目≠实例)。 + 舞台骨架 / 实现机制:可引用,不重写百科、不重钉既成法则。 + 变量*:游玩期状态更新——本步只约束生成时的类型与合法初值范围。 + 旁观维护:可读合同(rule_id、产物格式、何时可 need_generate);不依赖整份描写长文。 +feeds: gm,auditor +~~~~ + +### 14. 具体实例(`concrete-instances`) + +人工审查:☑ 已审查 2026-09-06:用户确认基本没问题;已有预生成规则才排,不改合同 + +源:`skills/dialogue/world-simulator/modules/concrete-instances/prompt.md` + +~~~~ +name: 具体实例 +id: concrete-instances +artifact: 设计.具体实例 +declaration: > + 已有预生成规则时:按该规则原样交出 records;不设计、不改合同;可按规则/批次反复 +when: | + 「设计.生成规则」里已有 `seed_only` 或 `seed_and_runtime` 的规则,且现在需要实际名片/记录(开局 NPC、种子事件等)。 +when_not: | + 尚无规则或规则不完整 → 先「生成规则」。想改格式/方法/池 → 回「生成规则」,本步不改合同。 + 规则是 `runtime_only` → 不排,游玩期再生成。 + 只要规则不要预写实例 → 不排。 +boundary: | + 本技能只做一件事:按指定规则生成 records。规则说怎么写、什么格式、如何用池,就照做。 + 生成规则:合同制定方——本步不重论证、不修改。 +feeds: gm +~~~~ + +### 15. 叙事指南与故事推进(`narrative`) + +人工审查:☑ 已审查 2026-09-06:用户确认基本可以 + +源:`skills/dialogue/world-simulator/modules/narrative/prompt.md` + +~~~~ +name: 叙事指南与故事推进 +id: narrative +artifact: 设计.叙事指南与故事推进 +declaration: > + 美学已有方向时:把感觉落成可执行的遣词、笔墨落点、禁忌与推进方式;不重做体验问卷 +when: | + 已有美学纲领(或等价),但转述/主世界层仍会不知道这四件:遣词什么味道、笔墨落谁身上、绝对不能写什么、故事靠场面自己推还是等用户。 + 用户主动谈文风、措辞禁忌、写法档(官能/爽文/恐怖/情色等)也排。 +when_not: | + 美学未钉 → 先「美学纲领与交互范式」。 + 用户只要感觉/站位、不要文风细则 → 不排,沿用美学。 + 版式/壳/监控栏 → 「正文组成」/「设计监控栏」。 + 事件池 schema、真值增减 → 「生成规则」/「变量设计与更新规则」。 +boundary: | + 本技能:一份 context-fragment,写清怎么写 + 怎么推;不必拆技能、也不必为省 token 做精细双投影。 + 美学:感觉与轮转。生成规则/变量*:合同与表。 +feeds: narrator,gm +~~~~ + +### 16. 拓扑图谱(`topology`) + +人工审查:☑ 已审查 2026-09-06:必须生成且不适合走生成规则→实例;用拓扑结构描述 + +源:`skills/dialogue/world-simulator/modules/topology/prompt.md` + +~~~~ +name: 拓扑图谱 +id: topology +artifact: 设计.拓扑图谱 +declaration: > + 有些东西必须生成,但不需要或不适合走「生成规则→具体实例」时:用拓扑结构写出来(升级路径、地图、人物关系等) +when: | + 已有「美学纲领与交互范式」或等价整体感觉,且同时满足: + 这些东西必须生成;不需要或不适合走「生成规则→具体实例」;能用拓扑结构描述。 + 很泛:升级路径、地图、人物关系等等都可以。 +when_not: | + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 需要精准格式,或本局原创听了会雾且还要按规则生成 → 「生成规则」;已有规则再要名片 → 「具体实例」。 + 只是活动区域写细、没有拓扑可描述 → 「舞台骨架」。 + 跨轮真值 → 「变量设计与更新规则」。执行单元勾选 → 「游玩拓扑」。 + 没有必须生成的拓扑结构 → 不排。 +boundary: | + 本技能:用拓扑结构写出必须存在、又不走生成规则合同的内容(节点、连接、方向/层级)。 + 生成规则 / 具体实例:复杂合同与 records——本步不写生成格式、不填名片表。 + 舞台骨架:活动区域写细——本步不重写舞台百科。 + 游玩拓扑:固定槽勾选——本步不描述执行单元谁读谁写。 + 变量*:跨轮状态——本步不设计变量表。 +feeds: gm +~~~~ + +### 17. 变量设计与更新规则(`variable-design`) + +人工审查:☑ 已审查 2026-09-06:用户确认完成 + +源:`skills/dialogue/world-simulator/modules/variable-design/prompt.md` + +~~~~ +name: 变量设计与更新规则 +id: variable-design +artifact: 设计.变量设计与更新规则 +declaration: > + 体验必须跨轮记住少数状态时:钉真值、谁可写、如何变、维护语句,以及按值换文案的映射索引 +when: | + 体验需要跨轮记住少数状态,否则会糊:必须可查询、门控、防重复,或到某值换一套态度/文案/章纲。 + 用户点名要好感/资源/阶段数字、分档换性格、进度门控时排。 +when_not: | + 无状态纯对话,或状态只临场描写、从不程序化 → 不排。 + 只要大段设定不要门控 → 「舞台骨架」/「生成规则」。 + 只规定谁的提示词看见什么 → 「变量控制上下文」。 + 只规定用户看见哪些监控字段 → 「设计监控栏」。 +boundary: | + 本技能:真值清单、更新规则、维护语句约定、Data 映射索引、side_effects 草案。 + 分档长文/性格切片正文:由生成规则定格式、具体实例填表;本步做索引与门控,不重写整表。 + 正文组成:隐藏段定界符——本步钉「维护语句写什么」;定界样式与之对齐。 + 机遇裁定 chance:真随机 toolcall,不是变量表维护手段。 + 变量控制上下文:挂载对象与旁观汇总视野。 + 细化终稿:收成 tables.side_effects。 +feeds: gm +~~~~ + +### 18. 变量控制上下文(`variable-context`) + +人工审查:☑ 已审查 2026-09-06:用户确认完成 + +源:`skills/dialogue/world-simulator/modules/variable-context/prompt.md` + +~~~~ +name: 变量控制上下文 +id: variable-context +artifact: 设计.变量控制上下文 +declaration: > + 已有真值或映射时:钉谁看见什么(主世界层/转述/旁观)、未解锁不注入;无信息差则可不排 +when: | + 变量设计已有真值或 Data 映射,且存在信息差:玩家不该看见但主世界层/旁观要知道,或到某档才允许提起,或旁观需要「当前档摘要」。 +when_not: | + 尚无变量且无投影 → 不排。 + 仅内部记账、永不进任何提示词 → 跳过,在变量设计备注即可。 + 只改字段与更新规则 → 「变量设计与更新规则」。 + 真值对所有槽同样可见、无剧透边界 → 可不排。 +boundary: | + 本技能:挂载表、剧透边界、旁观汇总视野、与维护语句/投影 tag 对齐。 + 变量设计:字段、映射索引、维护语句形状、side_effects。 + 具体实例:表行正文——本步不重生成,只声明「旁观读当前档/哪几个摘要键」。 + 设计监控栏 / 正文组成:用户可见层;本步管提示词视野。 +feeds: gm,auditor +~~~~ + +### 19. 正文组成(`reply-format`) + +人工审查:☑ 已审查 2026-09-06:展示回复呈现清单;选壳+美化,可写 CSS/HTML/JS + +源:`skills/dialogue/world-simulator/modules/reply-format/prompt.md` + +~~~~ +name: 正文组成 +id: reply-format +artifact: 设计.正文组成 +declaration: > + 把「回复呈现」已钉的内容展示给用户:选壳、美化排版,可写 CSS/HTML/JS;排在回复呈现之后、开场白之前 +when: | + 已有「回复呈现」(或等价:每轮终稿看什么已钉)后排。几乎每局都要。 + 必须在「开场白与开场变量」之前。 +when_not: | + 还不知道每轮给用户看什么 → 先「回复呈现」。 + 不要排在开场白之后。几乎不跳过。 + 只谈文风遣词 → 「叙事指南与故事推进」。只改呈现清单(字数/变量/日期)→ 「回复呈现」。 +boundary: | + 本技能:前端展示——从【可选呈现壳】选壳、把回复呈现的各项落到区域、美化排版(可含 CSS/HTML/JS)。 + 回复呈现:看什么、正文多少字、展示哪些变量——本步不重议清单,只负责怎么显示。 + 叙事指南:文风。变量设计:真值规则。开场白:第一屏——本步先定展示。 +feeds: narrator +~~~~ + +### 20. 回复呈现(`status-bar`) + +人工审查:☑ 已审查 2026-09-06:必选/可选区域 + 各区简单内容规则(含选项组成) + +源:`skills/dialogue/world-simulator/modules/status-bar/prompt.md` + +~~~~ +name: 回复呈现 +id: status-bar +artifact: 设计.监控栏 +declaration: > + 几乎每局都要:钉每轮终稿的必选/可选区域,以及各区域的简单内容规则(字数、段落、选项怎么组成等);不排版 +when: | + 舞台/世界/变量等上游大致齐后排。几乎每局都要。 + 排在「正文组成」之前:先钉有什么区域、各区怎么写,再交给正文组成去展示。 +when_not: | + 上游还没齐 → 先那些。 + 只谈怎么排版、选壳、CSS/HTML/JS → 「正文组成」。 + 只谈文风遣词 → 「叙事指南与故事推进」。 + 变量如何增减 → 「变量设计与更新规则」(本步只定展示哪些、展示规则)。 +boundary: > + 本技能:区域清单(必选/可选)+ 各区域简单内容规则(字数、自然段、选项槽位与提示口径等)。 + 正文组成:如何把这些区域展示给用户(壳、美化、CSS/HTML/JS)——本步不定版式。 + 变量设计:真值与更新——本步可点名要展示的键与监控规则,不写增减公式。 +feeds: narrator +~~~~ + +### 21. 游玩拓扑(`worker-spec`) + +人工审查:☑ 已审查 2026-09-07:主世界必要;有变量开旁观;取消机遇槽→随机范围整理 + +源:`skills/dialogue/world-simulator/modules/worker-spec/prompt.md` + +~~~~ +name: 游玩拓扑 +id: worker-spec +artifact: 设计.worker规格 +declaration: > + 不能吃默认槽时才勾选:主世界层必开;有变量/表维护才开旁观;转述默认开;强秘密才开视角;写手则大纲+章节;禁止发明执行单元与机遇槽 +when: | + 体验契约已大致清楚,且不能吃默认槽:要关旁观、关转述、开角色视角(强秘密不能进主世界层),或走写手大纲+章节。 + 或要修订已勾选槽(开/关 auditor、perspective、narrator 等)。 +when_not: | + 体验/站位仍混沌 → 先「美学纲领与交互范式」。 + 世界模拟可吃默认(主世界层+转述+旁观;视角关)→ 可不排,「细化终稿」按默认收成。 + 只需输出完整运行规格 → 「细化终稿」(本步只交槽位勾选)。 + 检定/掷骰范围汇总 → 「随机范围整理」;不要为本步加「机遇裁定」槽。 + 不要用本步发明世界观/性格/变量专用执行单元。 +boundary: | + 本能力:输出 play_slots(及写手路径的 writing_slots),可选覆盖挂载说明;不写完整 设计.worker集。 + 主世界层(gm)几乎总要。旁观维护:有变量/表/规则要程序化盯时才开。转述默认开。 + 不再设机遇裁定(chance)槽:真随机走「随机范围整理」+ 程序插入上下文备用数。 + 细化终稿:按本步勾选展开 workers、合并常驻与 tables。 + 变量设计 / 变量控制上下文:真值与投影,不是推理槽。 + 叙事指南与故事推进:挂到转述槽(推进可兼挂主世界层);世界/机制:挂到主世界层——本步只点名槽。 +~~~~ + +### 21b. 随机范围整理(`random-range`) + +人工审查:☑ 已写入 2026-09-07:正文组成前汇总;待你过目可再改 + +源:`skills/dialogue/world-simulator/modules/random-range/prompt.md` + +~~~~ +name: 随机范围整理 +id: random-range +artifact: 设计.随机范围整理 +declaration: > + 上游已有检定/对抗/掷骰需求时:汇总全部要用的随机项与取值范围(含表达式),供程序每轮插入备用随机数;排在正文组成之前 +when: | + 机制/生成规则/变量/叙事等上游已出现需要随机数的内容(对抗、检定、抽签、伤害区间等),且尚未收成一份范围表。 + 排在「正文组成」之前(通常紧挨其前;回复呈现可并行或略前)。 +when_not: | + 全程不靠随机数推进 → 不排。 + 还在定「怎么裁定 / 公式本身」→ 先「实现机制」「生成规则」或「变量设计与更新规则」;本步只汇总已定需求。 + 只谈前端怎么藏、选壳美化 → 「正文组成」。 + 只谈每轮可见区域与字数 → 「回复呈现」。 +boundary: | + 本技能:一份清单——每项随机用途、范围或表达式(如力量*5~*10、敏捷检定 1~100)、本轮建议备用条数。 + 不写新裁定法则、不写骰子剧情;法则来自上游,此处只整理成程序可读范围。 + 游玩拓扑:不再开「机遇裁定」槽;真随机靠本表 + 程序插入上下文。 + 正文组成:负责把隐藏备用区接到壳/消息里——本步只交「要插什么数」。 +feeds: gm,narrator +~~~~ + +### 22. 上下文投影排序(`context-order`) + +人工审查:☑ 已审查 2026-09-07:用户确认;已去机遇槽残留 + +源:`skills/dialogue/world-simulator/modules/context-order/prompt.md` + +~~~~ +name: 上下文投影排序 +id: context-order +artifact: 设计.上下文投影排序 +declaration: > + 收成前给已启用槽排扁平投影序(含对话.历史);不发明槽、不重写长文、不演情节选择题 +when: | + 游玩槽已确认(或可按默认),且主要上下文块已有可摘要产物,需要决定各执行单元看见什么、以何顺序插入。 + 本步为〔程序步〕:上下文已多、即将收成时排入。 +when_not: | + 体验/站位仍混沌 → 先「美学纲领与交互范式」。 + 槽位未定且用户拒绝默认 → 先「游玩拓扑」。 + 上游上下文仍大量空洞、无法判断稳/变 → 先补缺口,勿空排。 + 只需勾选槽 → 「游玩拓扑」;上下文很少、只需合并终稿 → 「细化终稿」可按默认序退化。 +boundary: | + 本技能:抄名册 → 凭各块 brief/挂载/稳变 给每槽 inserts[]。 + 名册权威在程序(及已勾选的游玩拓扑);本步不增白名单外 id。 + 中段技能可带 mount 与稳/变;最终 order 以本步为准。 + 细化终稿:把本步排序表收进运行规格 context_order;本步不输出完整 设计.worker集。 + 禁止把依赖产物里的游玩示例(迎上去/推开/反客为主 等)当成当前要问的题。 +feeds: design_only +~~~~ + +### 23. 细化终稿(`refine`) + +人工审查:☐ 未审查 + +源:`skills/dialogue/world-simulator/modules/refine/prompt.md` + +~~~~ +name: 细化终稿 +id: refine +artifact: 设计.worker集 +declaration: > + 按已勾选槽(或默认槽)与投影排序表收成运行规格;不发明新执行单元 +when: | + 至少体验契约可引用;槽已勾选或可按默认;若上下文块已多则宜先有投影排序表。 + 需要输出「设计.worker集」才能进游玩时排;编排应将流程导向 closed。 +when_not: | + 体验站位未定 → 先「美学纲领与交互范式」。 + 不能吃默认槽且尚未勾选 → 先「游玩拓扑」。 + 上下文块已多且稳/变未排序 → 先「上下文投影排序」。 + 只要改某一块设定长文 → 回头修改对应上游节点,不要用本步重写。 +boundary: | + 本能力:合并上游 → 完整运行规格 JSON(interaction、play_slots、context_order/inserts、 + workers 由槽展开、resident_context、tables)。 + 游玩拓扑:槽位权威;上下文投影排序:插入序与投影位权威;本步不新增白名单外的 ref。 + 变量设计:side_effects / 真值吸入 tables;不创建 variable-update 执行单元。 + 进 play 由用户手动决定。 +~~~~ + +### 24. 开场白与开场变量(`opening-setup`) + +人工审查:☐ 未审查 + +源:`skills/dialogue/world-simulator/modules/opening-setup/prompt.md` + +~~~~ +name: 开场白与开场变量 +id: opening-setup +artifact: 设计.开场白与开场变量 +declaration: > + 创作终节点:写出 1~多条开场白并钉同真相初值;选定后落库、结束创作并保存定稿 +when: | + 收成链已齐(至少体验契约可引用,且「细化终稿」已产出或可立即收成运行规格),需要可开玩的第一段剧情与同真相初值。 + 排在收成之后作最后一步。用户要进游玩但还没有第一屏 → 排。 +when_not: | + 体验/呈现仍混沌 → 先「美学纲领与交互范式」与「正文组成」等。 + 只要改文风不要开场 → 「叙事指南与故事推进」。 + 只要改真值规则不要开场文 → 「变量设计与更新规则」。 + 运行规格未齐 → 先「细化终稿」。尚未选定开场前若要补前序节点(如 NPC)→ 插在本步之前,勿以「收口已排入」拒绝追加。 +boundary: | + 本技能是创作终节点:1~多条开场正文(按正文组成块序)+ 开场变量初值 + 可选监控栏初值示意。 + 必须遵守已验收的叙事指南、正文组成、监控栏、变量设计;不重做这些契约。 + 具体实例:开场可引用已有实例名片,不在本步新造百科。 + 选定后由程序写入 输出.开场白 / 运行.初始变量 / 变量.当前,关闭 DAG 并保存定稿;不要在本步之后再排其它能力。 +feeds: narrator +~~~~ + + +--- + +## 不在本文 + +| 提示词 | 原因 | +|--------|------| +| `skills/dialogue/world-simulator/workers/design-step/SKILL.md` 与各技能 `task`/`opening`/`output` | 执行 LLM,规划看不见 | +| `skills/dialogue/world-simulator/workers/opening-generator/SKILL.md` | 创作末尾兜底,不是 design-flow | +| `skills/dialogue/world-simulator/orchestrator.md` / `uiPrompt` | 总管 LLM | +| `skills/dialogue/world-simulator/worker-templates/*.yaml` `prompt_excerpt` | 游玩人设 | + +执行全文审查可另开文档;选型口径见 `docs/briefs/prompt-revision-inventory.md`。 diff --git a/docs/briefs/prompt-revision-inventory.md b/docs/briefs/prompt-revision-inventory.md index 3477e31..6095587 100644 --- a/docs/briefs/prompt-revision-inventory.md +++ b/docs/briefs/prompt-revision-inventory.md @@ -1,57 +1,52 @@ -# 提示词 / 能力文档修订清单(待你改) +# 提示词修订清单 -> 程序侧已落地:`play_slots`、`settlement.v1`、模板默认契约、前端友好渲染雏形。 -> **本清单只整理「可能需要你改的提示词/能力文」——此处不改正文,等你确认后再动。** - -权威方法:`docs/progressive-data-design.md`、`docs/ui-glossary.md` §5.1。 +> 规划 LLM **不**靠加长 `design-flow` SKILL 学会选型。 +> 选型权威在各技能 `prompt.md` 的 **`meta.when` / `when_not` / `boundary` / `declaration`**。 +> 写法:`docs/world-simulator-modules.md`(写给规划,不是写给执行)、`docs/briefs/capability-authoring-brief.md` §4.3。 +> **人工审查工作簿(含 SKILL / 注入固定句 / 配方 / 全部 meta 全文)**:**`docs/briefs/design-flow-prompt-review.md`**。 --- -## 优先级 P0(与固定槽 + 裁决包强相关) +## 已改(规划选型) -| 文件 | 状态 | +全部 15 个技能的 `meta` 已按「对照用户话 + 已有产物就能判定」重写;`catalog.yaml` 声明已对齐;两份配方 `process` 不再抄各技能调用条件。 + +规划注入见 `formatModuleCatalogForAgent`:含糊或可跳过则不排。 + +| 技能 | 选型要点 | +|------|----------| +| 美学纲领与交互范式 | 三件还不能回答才排;已定稿不重复;产出供后续编排读的开头节点 | +| 实现机制 | 整体感觉已钉且有既成变造法则才排;无特殊设定或仅身份/开场可覆盖则不排 | +| 舞台骨架 | 会换区才备案;代入后几乎不移动、只在一处待着(网聊/门卫室)不排 | +| 生成规则 | 时机 a 精准格式或时机 b 原创会雾且还要生成,满足一条就排 | +| 具体实例 | 已有 seed 类规则才排;`runtime_only` 不排;本步不改合同(已审查,基本不动) | +| 叙事指南与故事推进 | 转述仍不知遣词/禁忌/推进才排;默认:长自然段;用户输入=大纲扩写不越界 | +| 拓扑图谱 | 必须生成且不适合走生成规则→实例;用拓扑结构描述(升级路径、地图、人物关系等) | +| 变量设计与更新规则 | 必须跨轮记住否则会糊才排(已审查,用户确认完成) | +| 变量控制上下文 | 有信息差才排;全员同可见则可不排(已审查,用户确认完成) | +| 回复呈现 | 几乎都排;必选/可选区域 + 规则;正文默认 1000~2000 字、长自然段 | +| 随机范围整理 | 有检定/对抗/掷骰才排;正文组成前汇总范围/表达式;替代机遇槽 | +| 正文组成 | 把回复呈现清单展示出来;选壳+美化;可接隐藏备用随机区;开场白之前 | +| 游玩拓扑 | **不能吃默认槽**才排;主世界必要;有变量开旁观;禁机遇槽 | +| 上下文投影排序 | 上下文已多、即将收成时排(程序步);名册无机遇;随机范围挂 gm | +| 细化终稿 | 要输出运行规格才排 | +| 开场白与开场变量 | 收成后、需要第一屏才排(收口) | + +--- + +## 尚未细调(执行全文) + +`task` / `opening` / `probe` / `output` 仍是初稿。规划看不见这些;要改产物质量再逐份动。 + +| 文件 | 备注 | |------|------| -| `modules/worker-spec/prompt.md` | **已改** → 游玩拓扑,只勾选固定槽 | -| `modules/refine/prompt.md` | **已改** → 按 `play_slots` 收成,禁发明 ref | -| `modules/catalog.yaml` / 配方 / `design-flow` | **已改**(配方含:挂谁可早、排第几须晚) | -| `modules/context-order/prompt.md` | **骨架已写**(`context-order.v1`) | -| `docs/context-fragment-design.md` | **已写**;范例技能已对齐 `context-fragment.v1` | -| 程序:片段解析 / 扁平投影序 / `对话.历史` 可投影 | **已落地**(非硬双锚) | -| `orchestrator.md` | **已改**:play 调度 gm → perspective? → narrator → auditor | +| 其余 `modules/*/prompt.md` 执行块 | 结构齐,未逐句打磨 | +| `workers/design-flow/SKILL.md` | 怎么排(美学正文 + 已完成 id → 缺口)+ DAG 写法;**不要**把各技能调用条件搬进来 | +| `worker-templates/*.yaml` `prompt_excerpt` | 游玩人设,与创作选型无关 | -## 优先级 P1(能力归属 feeds) +--- -| 文件 | 建议补什么 | -|------|------------| -| `modules/*/prompt.md` 的 `meta` | 统一加 `feeds: gm \| narrator \| runtime \| design_only \| perspective`(约定字段,程序以后可读) | -| `aesthetics-interaction` | `feeds: design_only`(再压缩进常驻);呈现要点可摘要给 narrator | -| `mechanism` | **已改** output→`context-fragment.v1`;`feeds: gm` | -| `world-blueprint` | **已改**→「舞台骨架」+ `context-fragment.v1`;`feeds: gm` | -| `generation-rules` / `concrete-instances` | **已改** fragment;生成规则 **mount/feeds 含 auditor(合同级)** | -| `narrative` | **已改**:一步两块(风格与写法|推进与决策)+ 双挂;专用 mosaic | -| `variable-design` | **已写** | -| `variable-context` | **已改**:mount 含 auditor + 旁观汇总 | -| `reply-format` / `status-bar` | 已有正文;见 artifact-card-coverage | -| `topology` | 骨架;等你定「小循环」选项后再写 | -| `worker-templates/*.yaml` | gm/narrator/auditor 已齐 | - -## 优先级 P2(文档口径) - -| 文件 | 建议 | -|------|------| -| `docs/design-orchestrator-guide.md` | § 三大步 / Worker 创造:改为固定槽 + 创作上下文映射;保留表副作用 | -| `docs/world-simulator-modules.md` | 清单状态:worker-spec→拓扑;链到本清单 | -| `docs/tag-blackboard.md` | 强调 `运行.本轮.裁决` = settlement.v1;转述少读 `变量.当前` | -| `docs/skill-design-guide.md` | 若仍教「创造 worker」,加世界模拟例外 | -| `ui-glossary.md` | §5.1 已有主世界层;可补「游玩槽位」用户可见词(可选) | - -## 明确不必改成「第三 Worker」的 - -- **变量管理**:保持 `variable-design` / `variable-context` + Runtime `side_effects`,不要新 `variable-update` 必选槽。 -- **世界观**:常驻挂 GM,不要世界观执行单元。 -- **性格分档**:Data + Progressive tag,不要性格 agent。 - -## 程序已做、提示词需跟上的契约 +## 程序契约(提示词需继续遵守) ```json // 设计.worker集(世界模拟) @@ -62,35 +57,4 @@ } ``` -```json -// 运行.本轮.裁决 -{ - "schema": "settlement.v1", - "player_action": "…", - "resolved": ["…"], - "visible_now": "…", - "npc_moves": [{ "who": "…", "move": "…" }], - "variable_changes": [{ "key": "好感", "delta": 8 }], - "do_not_say": ["好感数字"], - "tone_hint": "…" -} -``` - -```json -// 运行.本轮.旁观(多数轮空) -{ - "schema": "maintain.v1", - "need_generate": false, - "table_ops": [], - "notes": [] -} -``` - -## 建议你改的顺序 - -1. `refine` + `worker-spec`(或新拓扑技能)对齐 `play_slots` -2. `world-simulator` 配方 + `orchestrator` 调度顺序 -3. 各能力 meta 补 `feeds` -4. 骨架能力(status-bar / reply-format / topology)按需细写或降级 - -改完后告诉我,我可以按你的口径改提示词并加解析 `feeds`(若要程序注入)。 +明确不必改成「第三 Worker」的:变量管理、世界观、性格分档——见旧口径,仍有效。 diff --git a/docs/context-fragment-design.md b/docs/context-fragment-design.md index 506865f..3f3ef4a 100644 --- a/docs/context-fragment-design.md +++ b/docs/context-fragment-design.md @@ -61,8 +61,8 @@ 生成规则正文:必要性判断 + `rules[]`(生成与描写 + **单层**产物格式 + 可选多池绑顶层字段 + **数量**与**一次生成**(单条|同批,同批须钉记录间关系));自评=必要性/属性妥当/格式准确。 美学纲领自评仍为:交互范式 / 美学纲领 / 整体协调(勿与生成规则三维混用)。 叙事指南与故事推进正文:一份全文(纲领/遣词/笔墨/禁忌/推进等);**整份**双挂转述与主世界层,不为省 token 拆两套投影。artifact=`设计.叙事指南与故事推进`。 -正文组成:**基于固定呈现壳适配微调**(选 `shell_id` + 微调轴;块只挂壳已有区域);正文含 **`示例`**(`present.v1` 灌数,验收壳与美化;非正史,文笔不重要);artifact=`设计.正文组成`。见 `docs/play-presentation-shells.md`。 -设计监控栏:只监控会变字段(可含攻略目标/场景交互物);artifact=`设计.监控栏`(旧称状态栏)。 +回复呈现:每轮终稿给用户看什么(正文/字数/日期/变量);artifact=`设计.监控栏`(旧称设计监控栏/状态栏)。 +正文组成:把回复呈现清单展示给用户(选壳、美化,可写 CSS/HTML/JS);artifact=`设计.正文组成`。见 `docs/play-presentation-shells.md`。 变量设计:真值 + **维护语句** + **Data映射索引**(指向具体实例)+ side_effects。 变量控制上下文:各槽视野 + **旁观汇总**;mount 含主世界层与旁观维护。 生成规则:合同挂主世界层 + 旁观(旁观读 rule_id/格式/必要性,描写长文可 summary)。 diff --git a/docs/implementation-guide.md b/docs/implementation-guide.md index 4d4be01..83eacbd 100644 --- a/docs/implementation-guide.md +++ b/docs/implementation-guide.md @@ -5,7 +5,7 @@ ```text 1. 先读文档,再写对应文件。 2. 一次只写一个文件(或一组强绑定的 types + 实现)。 -3. 每写完一个文件,对照本文档的「文件职责」自检。 +3. 每写完一个文件,对照对应规格文档自检。 4. 文件行为与文档冲突时,先改文档,再改代码。 5. 不要跳步实现:下游文件不能先于上游文件。 ``` @@ -28,21 +28,29 @@ | UI | `ui-design.md` | 工作台布局、检查器、composer | | UI | **`ui-glossary.md`** | 用户可见中文口径;禁止裸露内部 id | | 外部参考 | `references.md` | 按层借鉴的 GitHub 仓库 | -| 本文件 | `implementation-guide.md` | 文件顺序与职责;在现有内核上补齐 | +| 本文件 | `implementation-guide.md` | 写代码规则与文档地图 | | **产品体验路线** | **`px-roadmap.md`** | PX0–PX5 交付、DoD、明确不做 | | **日常 → P0** | **`daily-use-p0.md`** | 日常场景、功能映射、P0 详细工作包 | | **剧本 / 方法(非系统架构)** | `design-orchestrator-guide.md` | 创作三大步、表/副作用、自检 | | **剧本 / 方法(非系统架构)** | `creation-playbook.md` | 创作流程概念(指向指导) | | **剧本 / 方法(非系统架构)** | `world-simulator-modules.md` | 编排器/能力清单与现行包布局 | +| **剧本 / 方法(非系统架构)** | `progressive-data-design.md` | 真值 / Data / Progressive | +| **剧本 / 方法(非系统架构)** | `context-fragment-design.md` | 上下文片段、固定槽、投影排序 | +| **剧本 / 方法(非系统架构)** | `play-presentation-shells.md` | 游玩呈现壳 | +| **剧本 / 方法(非系统架构)** | `play-dm-auditor.md` | 主世界层与旁观维护 | | **Skill 格式(非系统架构)** | `orchestrator-skill-format.md` | manifest 写法(非编排表) | | **Skill 格式(非系统架构)** | `worker-skill-format.md` | SKILL.md、contextSegments | -| **Skill 格式(非系统架构)** | `skill-format.md` | 包存储、registry(示例以 world-simulator 为准) | +| **Skill 格式(非系统架构)** | `skill-format.md` | 包存储、registry | | **Skill 格式(非系统架构)** | `skill-design-guide.md` | 包格式薄层 | | **Skill 格式(非系统架构)** | `preset-format.md` | 预设导入 | | **能力撰写** | `briefs/capability-authoring-brief.md` | 外部 AI 写 modules 交接 | 许可证占位:仓库根 `THIRD_PARTY_NOTICES.md`。 +工作簿(非规格):`briefs/prompt-revision-inventory.md`、`briefs/design-flow-prompt-review.md`、`briefs/artifact-card-coverage.md`。 + +现行唯一落地包:`skills/dialogue/world-simulator/`(见该包 README)。 + --- ## 3. 在现有内核上补齐(当前优先) @@ -61,327 +69,3 @@ | PX4 | 长文加深(P0 已含最小闭环) | — | | PX5 | 隔离 + 调试;必要时新配方包 | — | | 延后 | SQLite / 事件溯源 / Mastra·Next | — | - -历史分期 A0–E 见下节(**多数已 done,仅作文件职责索引**;进度与验收以 [`px-roadmap.md`](./px-roadmap.md) 为准,勿再按 §9「未开始」判断现状)。 - -> §3b / §9 中仍可能出现 `design-intake`、`skills/novel/`、缺失文件路径等**历史表述**;磁盘真相见 `skills/dialogue/world-simulator/README.md`。 - ---- - -## 3b. 历史实现分期(索引) - -### Phase A0 — 可运行阶段机 - -目标:**不依赖 LLM**,阶段机整体可运行、可手动驱动、可脚本跑通最小闭环。 - -| # | 文件 | 状态 | 干嘛的 | -|---|---|---|---| -| A06 | `src/types/runtime.ts` | done | 5 相位、事件、会话类型 | -| A09 | `src/runtime/phase-machine.ts` | done | 纯函数:`applyEvent`,不调 LLM | -| A20 | `src/runtime/phase-runtime.ts` | done | 运行层:处理 effects,stub worker | -| A21 | `src/cli/phase-demo.ts` | done | 交互式演示 CLI,手动发事件 | -| A22 | `tests/phase-runtime.test.ts` | done | 闭环 + worker 中途提问测试 | - -**运行方式:** -```bash -npm run phase-script # 非交互,自动跑最小闭环 -npm run phase-demo # 交互,手动 /decide /approve /worker-ask -npm run phase-demo -- --auto # worker 自动占位完成 -``` - -### Phase A1 — 编排器 LLM 接入(阶段机之上) - -目标:在 PhaseRuntime 之上接 Main Agent,不改动 phase-machine 规则。 - -| # | 文件 | 状态 | 干嘛的 | -|---|---|---|---| -| A11–A19 | blackboard、llm、main-agent、orchestrator、run.ts | done | 带 Mock/真实 LLM 的完整栈 | -| A15 | `src/main-agent/prompts.ts` | todo | prompt 拆分 | - -### Phase A2 — Skill 层(创作指南) - -目标:`skills/` 批量存储 SKILL.md;启动第一个询问是选 skill;编排器读 activeSkill。 - -| # | 文件 | 状态 | 干嘛的 | -|---|---|---|---| -| S00 | `skills/registry.yaml` | done | skill 索引 | -| S01 | `skills/novel-standard/SKILL.md` | done | 小说指南(含启动询问) | -| S02 | `skills/theater-roleplay/SKILL.md` | done | 剧场指南(含启动询问) | -| S03 | `src/skills/types.ts` | todo | ParsedSkill、SkillIndexEntry | -| S04 | `src/skills/loader.ts` | todo | 解析 SKILL.md | -| S05 | `src/skills/registry.ts` | todo | listSkills() | -| S06 | `src/skills/resolver.ts` | todo | 推断当前 stage | -| S07 | `src/main-agent/skill-context.ts` | todo | 注入编排器 prompt | -| S08 | `src/runtime/phase-machine.ts` | todo | 增加 skill_selection / skill_selected | -| S09 | `src/cli/phase-demo.ts` | todo | 启动时 /select-skill | - -详见 `docs/skill-format.md` §5。 - -### Phase B — Tool Call 化 - -目标:编排器 / worker 从 JSON 决策改为 tool call;Runtime 做 tool 校验与事件转换。 - -### Phase C — 真实 Worker - -目标:outline / drafting 等固定 worker 接真实 LLM;worker 可中途 ask_user。 - -### Phase D — 持久化 - -目标:book 存储;preset 导入。 - -### Phase E — 标签黑板迁移(当前文档已完成,代码待做) - -目标:代码与 `tag-blackboard.md` 对齐。 - -| # | 文件 | 状态 | 干嘛的 | -|---|---|---|---| -| E01 | `src/types/blackboard.ts` | done | `BlackboardItem`、按 tag 查询 | -| E02 | `src/blackboard/blackboard.ts` | done | listTagIndex、前缀匹配 | -| E03 | `src/skills/types.ts` + `loader.ts` | done | 解析 inputTags / outputTags(兼容 outputKeys) | -| E04 | `src/worker/executor.ts` | done | 按 tag 取 context,校验 outputTags | -| E05 | `src/types/runtime.ts` + `main-agent.ts` + `phase-runtime` | done | 决策去掉 keys;runtime 按 Worker Skill 执行 | -| E06 | `skills/novel/weird-rules-short/` | todo | tag 化 skill 样板 + inputTags frontmatter | -| E07 | `skills/novel/quick-write/` | todo | 简易全量 LLM skill | - -编排写在各包 `orchestrator.md`,不单独维护 execution-flow YAML。 - ---- - -## 4. Phase A 文件顺序 - -按序号逐个实现。状态列:`done` = 已有初版,`todo` = 未写或未按文档对齐。 - -### 4.1 项目配置 - -| # | 文件 | 状态 | 干嘛的 | -|---|---|---|---| -| A01 | `package.json` | done | 项目元数据、npm scripts(dev / test / demo) | -| A02 | `tsconfig.json` | done | TypeScript 编译选项 | -| A03 | `vitest.config.ts` | done | 测试入口配置 | -| A04 | `.env.example` | done | LLM API 环境变量模板,不含真实 key | -| A05 | `.gitignore` | done | 忽略 node_modules、dist、.env | - -**A01 职责:** 声明依赖(typescript、tsx、vitest)和三条命令。不含业务逻辑。 - ---- - -### 4.2 类型层(只放数据结构,不含逻辑) - -| # | 文件 | 状态 | 干嘛的 | 对应文档 | -|---|---|---|---|---| -| A06 | `src/types/runtime.ts` | done | 相位、事件、会话、产物、ResumeContext | `runtime-state-machine.md` §2–5 | -| A07 | `src/types/blackboard.ts` | done | BlackboardItem、TagIndex | `tag-blackboard.md` §2 | -| A08 | `src/types/tools.ts` | todo | 编排器 tool、worker tool 的参数与结果类型 | `tool-contracts.md` | - -**A06 职责:** -- 定义 `RuntimePhase`(5 种) -- 定义 `WaitingReason`(waiting_user 的子原因) -- 定义 `RuntimeEvent`(唯一改变相位的输入) -- 定义 `RuntimeSession`(运行时快照) -- 定义 `PhaseEffect`(阶段机产生的副作用,如 invoke_main_agent) - -**A07 职责(Phase E 迁移后):** -- 定义 `BlackboardItem`(id、tag、content、source、metadata) -- 定义 `BlackboardTagIndex`(给编排器:tag + source,无 content) -- 定义 `BlackboardWrite`(worker 写回) - -**A08 职责(Phase B 再写):** -- `MainAgentToolName`、`WorkerToolName` -- 每个 tool 的 params / result 类型 -- tool → event 映射表(类型级注释) - ---- - -### 4.3 阶段机(纯函数,不调用 LLM) - -| # | 文件 | 状态 | 干嘛的 | 对应文档 | -|---|---|---|---|---| -| A09 | `src/runtime/phase-machine.ts` | done | 5 相位阶段机:`applyEvent`、`canApplyEvent` | `runtime-state-machine.md` §6–8 | -| A10 | `src/runtime/state-machine.ts` | done | 废弃别名,re-export phase-machine | — | - -**A09 职责:** -- `createSession()` — 创建 idle 会话 -- `getAllowedEvents()` — 当前相位允许哪些事件 -- `canApplyEvent()` — 事件是否合法(含 waitingReason 校验) -- `applyEvent()` — 纯函数:session + event → 新 session + effects -- `createArtifact()` — 创建产物记录 - -**约束:** -- 不 import llm、blackboard、main-agent -- 不做 IO -- 所有相位转移必须写进 history - -**A10 职责:** 兼容旧 import 路径,后续可删。 - ---- - -### 4.4 黑板 - -| # | 文件 | 状态 | 干嘛的 | 对应文档 | -|---|---|---|---|---| -| A11 | `src/blackboard/blackboard.ts` | done | listTagIndex、queryByPatterns、write | `tag-blackboard.md` §2 | - -**A11 职责:** -- `listTagIndex()` — 给编排器 -- `queryByPatterns()` — 给 worker 注入 -- `write()` — 按 tag 写回 -- `getContentByTag()` / `getLatestByTag()` - ---- - -### 4.5 配置与 LLM - -| # | 文件 | 状态 | 干嘛的 | 对应文档 | -|---|---|---|---|---| -| A12 | `src/config/env.ts` | done | 从环境变量读 baseUrl、apiKey、model | `architecture.md` §2 config | -| A13 | `src/llm/client.ts` | done | OpenAI 兼容 API + MockLlmProvider | — | - -**A12 职责:** -- `loadLlmConfig()` — 必须有 key,否则抛错 -- `loadLlmConfigOptional()` — 无 key 返回 null,CLI 切 mock - -**A13 职责:** -- `LlmProvider` 接口:`complete(messages) → string` -- `OpenAiCompatibleProvider` — 真实 API 调用 -- `MockLlmProvider` — 测试 / demo 用预设响应 -- apiKey 不出现在 session 或项目文件里 - ---- - -### 4.6 编排器 LLM - -| # | 文件 | 状态 | 干嘛的 | 对应文档 | -|---|---|---|---|---| -| A14 | `src/main-agent/main-agent.ts` | done | 编排器:只选 worker,读 tag 索引 | `tag-blackboard.md` §6 | -| A15 | `src/main-agent/prompts.ts` | todo | 编排器 prompt 拆分 | `tag-blackboard.md` §6 | - -**A14 职责:** -- `MainAgent.decide(context)` — 调 LLM,返回 `MainAgentDecision` -- `parseMainAgentDecision(raw)` — 解析 JSON(Phase B 改为 parse tool calls) -- `buildMainAgentUserPrompt(context)` — 拼 user prompt -- `DEFAULT_WORKERS` — 第一版可用 worker 列表 - -**约束:** -- 编排器不读黑板 value -- 编排器不直接改 phase -- 不含 question-worker(提问是 worker 能力) - -**A15 职责(可选拆分):** 把 prompt 从 main-agent.ts 抽出来,方便迭代。 - ---- - -### 4.7 编排层 - -| # | 文件 | 状态 | 干嘛的 | 对应文档 | -|---|---|---|---|---| -| A16 | `src/runtime/orchestrator.ts` | deprecated | 旧入口;用 phase-runtime | `architecture.md` | - -**A16 职责:** -- `RuntimeOrchestrator` — 对外 API:start、submitUserInput、approve、accept 等 -- `dispatch(event)` — 调 `applyEvent`,处理 `PhaseEffect` -- `runMainAgent()` — phase=running 时调编排器 -- `runStubWorker()` — 第一版占位 worker(Phase C 替换) -- `resumeStubWorker()` — worker 中途提问后恢复 - -**约束:** -- 唯一调用阶段机和编排器的地方 -- user 事件(approve / accept)只从 CLI / API 进入,不从 LLM 进入 - ---- - -### 4.8 入口与测试 - -| # | 文件 | 状态 | 干嘛的 | -|---|---|---|---| -| A17 | `src/cli/run.ts` | done | 交互式 CLI:输入、/approve、/accept、/status | -| A18 | `tests/phase-machine.test.ts` | done | 阶段机单元测试 | -| A19 | `tests/orchestrator.test.ts` | done | 编排层 + Mock LLM 集成测试 | - -**A17 职责:** -- 读 stdin,转成 orchestrator 方法调用 -- 打印 `phase` + `waitingReason` -- `--mock` 或无 API key 时用 MockLlmProvider - ---- - -## 5. Phase B 文件顺序(下一步) - -| # | 文件 | 干嘛的 | -|---|---|---| -| B01 | `src/types/tools.ts` | tool 类型定义 | -| B02 | `src/runtime/tool-registry.ts` | 注册 tool、校验参数、tool → event | -| B03 | `src/main-agent/main-agent.ts` | 改为 tool calling 模式 | -| B04 | `src/runtime/tool-handlers/main-agent.ts` | 编排器 tool 处理器 | -| B05 | `src/runtime/tool-handlers/worker.ts` | worker tool 处理器(ask_user / submit) | - -**B02 职责:** -- 白名单:当前 phase + waitingReason 下允许哪些 tool -- LLM 调了不允许的 tool → 拒绝,不转事件 - ---- - -## 6. Phase C 文件顺序 - -| # | 文件 | 干嘛的 | -|---|---|---| -| C01 | `src/workers/types.ts` | WorkerDefinition、WorkerRunOutcome | -| C02 | `src/workers/base-worker.ts` | prompt 拼接、tool 执行循环 | -| C03 | `src/workers/outline-worker.ts` | 大纲 worker | -| C04 | `src/workers/drafting-worker.ts` | 正文 worker | -| C05 | `src/runtime/worker-runner.ts` | 替代 orchestrator 里的 stub | - -**WorkerRunOutcome(Phase C 核心):** - -```ts -type WorkerRunOutcome = - | { kind: "complete"; writes: BlackboardWrite[]; summary: string } - | { kind: "suspend"; questions: string[]; partialWrites?: BlackboardWrite[] } - | { kind: "fail"; reason: string }; -``` - -- `complete` → `worker_completed` 事件 -- `suspend` → `worker_needs_input` 事件 -- `fail` → `runtime_failed` 事件 - ---- - -## 7. Phase D 文件顺序 - -| # | 文件 | 干嘛的 | -|---|---|---| -| D01 | `src/flows/types.ts` | ExecutionFlow、ExecutionStep | -| D02 | `src/flows/ghostwriting-flow.ts` | 代笔 flow 配置 | -| D03 | `src/book-storage/store.ts` | Book 持久化 | -| D04 | `src/preset/importer.ts` | SillyTavern 预设导入 | - ---- - -## 8. 单文件完成检查清单 - -每写完一个文件,确认: - -```text -[ ] 文件顶部的职责是否只对应文档里的一节 -[ ] 是否 import 了不该 import 的上层模块(阶段机不应 import LLM) -[ ] 是否有对应测试(内核文件必须有) -[ ] 是否更新了本表的状态列(done / todo) -[ ] 是否在 PR / 提交说明里写「这个文件干嘛的」一句话 -``` - ---- - -## 9. 当前进度 - -```text -Phase A0(可运行阶段机) ✅ 完成 - phase-machine + phase-runtime + phase-demo + 测试 - -Phase A1(编排器 LLM) ✅ 有初版(orchestrator + run.ts) - 下一步:orchestrator 应基于 PhaseRuntime 重构 - -Phase B(tool call) 未开始 -Phase C(真实 worker) 未开始 -Phase D(flow / 存储) 未开始 -``` - -**下一个应写文件:** 让 `orchestrator.ts` 内部组合 `PhaseRuntime`,而不是重复阶段机逻辑。写之前会先说明该文件职责。 diff --git a/docs/play-presentation-shells.md b/docs/play-presentation-shells.md index 5e5cb2b..71fafe6 100644 --- a/docs/play-presentation-shells.md +++ b/docs/play-presentation-shells.md @@ -2,18 +2,19 @@ > **阶段**:P1 = 定类与契约;**P2** = 程序/样式适配与灌数。 > 上游:游玩管线 `gm → perspective? → narrator → auditor`。 -> 创作挂钩:`设计.正文组成` / `设计.监控栏`;终稿 tag 通常 `输出.用户展示`。 -> **创作定位:基于固定壳做适配微调,不是从零设计前端。** +> 创作挂钩:`设计.正文组成`(怎么展示)/ `设计.监控栏`(每轮看什么,技能名「回复呈现」);终稿 tag 通常 `输出.用户展示`。 +> 各壳介绍与规格:`skills/dialogue/world-simulator/present-shells/`(正文组成执行时动态注入)。 +> **创作定位:按回复呈现清单选壳并美化,可写 CSS/HTML/JS。** > 预览:`/shells.html` ## 1. 创作怎么做(权威口径) ```text -固定壳(本仓库预置,七种) - → 按「要同时看见什么」选 shell_id(不是按好看) +呈现壳(仓库 present-shells/,动态装载) + → 按「要同时看见什么」对照各壳介绍选 shell_id → 只改允许的微调轴 - → 禁止改分区骨架、禁止发明第八种布局 -游玩期:往壳区域灌数;正文随 500~2000 字撑高滚动 + → 禁止改分区骨架、禁止自造目录没有的壳 +游玩期:往壳区域灌数;正文随 1000~2000 字撑高滚动 ``` 选壳依据(同时可见关系): @@ -36,7 +37,7 @@ | 优先级 | 区域 | 视觉待遇 | |--------|------|----------| -| **P0** | `body` | 阅读主轴;**随字数撑高**(单轮按 500~2000 字设计),由页面/消息区滚动 | +| **P0** | `body` | 阅读主轴;**随字数撑高**(单轮按 1000~2000 字设计),由页面/消息区滚动 | | **P1** | 建议行动 | 要决策时醒目;`choice_dock` 坞 **sticky 贴底** | | **P2** | `monitor` | 芯片密排,高度固定矮 | | **P3** | `header` / `footer` / `aside` | 辅助;双栏 **aside sticky**,长文仍可对照 | @@ -84,13 +85,14 @@ ## 4. 与创作产物的映射 ```text -设计.正文组成 - 正文.呈现壳.shell_id → 七选一 + 设计.正文组成 + 正文.呈现壳.shell_id → 【可选呈现壳】中的 id 正文.呈现壳.微调 → 只填允许轴 正文.可见块[] → 挂到壳已有区域 正文.示例.灌数 → present.v1 形状预览(非正史;专供验收壳/美化) -设计.监控栏 → monitor 字段表 +设计.监控栏 → 回复呈现清单(看什么) +设计.正文组成 → 壳 + 美化(怎么展示) 运行.本轮.裁决 → body 事实;suggested_actions → 行动区 输出.用户展示 → present.v1 或纯 Markdown(→ body) ``` @@ -114,7 +116,7 @@ ## 6. 创作期只做适配 -1. **选壳**:按「主面积给谁」(§2)七选一。 +1. **选壳**:按「主面积给谁」从已装载壳里选。 2. **微调**:字段、显示名、行动开关、tone、空态。 3. **不要**:重画分区、发明区域 id、写 CSS。 @@ -131,4 +133,4 @@ --- -修订:2026-08-22 · 七壳;终稿阅读柱;单轮正文 500~2000 字。 +修订:2026-09-06 · 七壳;终稿阅读柱;单轮正文默认 1000~2000 字。 diff --git a/docs/skill-format.md b/docs/skill-format.md index 50ebcd0..37d27fe 100644 --- a/docs/skill-format.md +++ b/docs/skill-format.md @@ -2,447 +2,131 @@ > **文档层级:Skill 包格式(非系统架构)。** > 系统级模块与调度边界见 [`architecture.md`](./architecture.md)。 -> > **现行唯一落地包**:`skills/dialogue/world-simulator/`(见该包 README、`world-simulator-modules.md`)。 -> 下文部分示例仍保留历史 `novel/` / `weird-rules-short` 树形说明,**仓库内已不存在**;写新内容请以 world-simulator 为准。 -> 创作流水线现行名:`design-flow` + `design-step`(旧称 `design-intake` 已废弃)。 +> 创作流水线:`design-flow` + `design-step`。 -## 1. 定位:两层 Skill +本文只写**包怎么落盘、registry、启动时怎么绑包**。manifest 正文见 `orchestrator-skill-format.md`;磁盘 Worker 见 `worker-skill-format.md`;建包步骤见 `skill-design-guide.md`。 -本项目有 **两种 Skill 文档**,不要混在一个文件里: +--- + +## 1. 两层 Skill | 类型 | 路径 | 消费者 | 写什么 | |------|------|--------|--------| -| **编排器 Skill** | `skills/{bookKind}/{name}/orchestrator.md` | Main Agent | **何时**调哪个 worker、验收方式、启动询问 | +| **编排器 Skill** | `skills/{bookKind}/{name}/orchestrator.md` | Main Agent | **何时**调哪个 worker、验收方式、启动引导 | | **Worker Skill** | `workers/{workerId}/SKILL.md` | Worker Agent | **inputTags/outputTags**、怎么做 | -```text -选 weird-rules-short(编排器 Skill) - → 编排器:brief 齐了 → run ruleset-worker,input=[project.brief] - → Worker:读 workers/ruleset-worker/SKILL.md → 写 core / rules / commentary - → 编排器:rules accepted → run review-worker - → Worker:读 workers/review-worker/SKILL.md → 评估怎么做 -``` - -**何时评估** = 编排器 Skill 的 Worker 编排表。 -**如何评估** = review-worker 的 Worker Skill。 - -详细规范: - -- 编排器 Skill → `docs/orchestrator-skill-format.md` -- Worker Skill → `docs/worker-skill-format.md` - -旧称「Skill = 创作说明书」仍成立,但说明书 **拆成编排(编排器)与执行(worker)两份**。 - ```text 会话开始 - → 询问 1:选哪个编排器 Skill(skills/{bookKind}/{name}/orchestrator.md) - → 加载编排器 Skill - → 询问 2:读编排器 Skill「## 启动询问」 - → 之后编排器按「Worker 编排」调度;Worker 读本 skill 包内 workers/{id}/SKILL.md + → 自动绑定默认编排器包(world-simulator) + → UI 选配方(recipes/,不是再选 skill 包) + → 编排器按 tool loop 调度;Worker 读本包 workers/{id}/SKILL.md ``` +**何时评估** = 编排器 Skill。 +**如何评估** = 对应 Worker Skill(或运行规格里的声明)。 + --- ## 2. 存储位置 -Skill 以 **Skill 包(skill pack)** 为单位:一个编排器 + 其专属 workers,**同包绑定,不跨包复用 worker**。 +Skill 以 **Skill 包** 为单位:一个编排器 + 其专属 workers,**同包绑定,不跨包复用 worker**。 ```text skills/ ├── registry.yaml -├── novel/ # Book 形态 -│ ├── basic/ -│ │ └── orchestrator.md # 编排器 Skill -│ ├── weird-rules-short/ -│ │ ├── orchestrator.md # 编排器:何时调谁、黑板 key -│ │ └── workers/ # 本编排器专属,不与其他 skill 共享 -│ │ ├── write-rules/ -│ │ │ └── SKILL.md # 规则怪谈:怎么写规则+解析 -│ │ └── review/ -│ │ └── SKILL.md # 规则怪谈:怎么检查 -│ └── novel-standard/ -│ ├── orchestrator.md -│ └── workers/ -│ ├── outline/SKILL.md -│ └── drafting/SKILL.md └── dialogue/ - └── theater-roleplay/ + └── world-simulator/ ├── orchestrator.md + ├── recipes/ + ├── modules/ + ├── worker-templates/ └── workers/ - └── turn/SKILL.md + ├── design-flow/SKILL.md + ├── design-step/SKILL.md + └── opening-generator/SKILL.md ``` -规则: - ```text 第一层文件夹 = bookKind(novel | dialogue),决定 Book 存储结构 第二层文件夹 = 一个 skill 包,名与 frontmatter.name 一致 - orchestrator.md 编排器 Skill(编排、启动询问、验收) - workers/{id}/ 本包专属 worker;id 在包内唯一即可 -Worker 不复用:novel-standard 的 outline worker ≠ weird-rules-short 的任何 worker -registry.yaml 的 path 指向 orchestrator.md,如 novel/weird-rules-short/orchestrator.md + orchestrator.md 编排器 Skill + workers/{id}/ 本包专属 worker;id 在包内唯一 ``` -**为何不复用 worker:** 同一「产出形状」(如规则表)在不同编排器下的写法、Rubric、自检完全不同;共享 worker 会把体裁细节塞进编排器或搞混上下文。需要相似流程时 **复制 worker 包再改**,而不是引用全局 worker。 +loader 仍扫描 `skills/novel/` 与 `skills/dialogue/`(平铺 `.md` 或 `{name}/orchestrator.md`)。仓库里目前只有 `dialogue/world-simulator`。 -与 Cursor skill 的区别: - -| | Cursor Skill | 本项目 Skill | -|---|---|---| -| 位置 | `.cursor/skills/` | `skills/` | -| 触发 | Agent 自动或显式引用 | **会话开始必须选一个** | -| 内容 | 通用任务指南 | **创作流程 + 思维链 + 询问策略** | -| 消费者 | Cursor Agent | 编排器 LLM | +**为何不复用 worker:** 同一产出形状在不同编排器下的写法、验收完全不同;需要相似流程时复制后再改。 --- -## 3. SKILL.md 结构 +## 3. Frontmatter(编排器) -### 3.0 两层分类(重要) - -Skill 分类分**两层**,不要混为一层: - -```text -第一层:Book 形态(category / bookKind,选定后不可换) - novel 类小说存储:卷、章、大纲、正文(含各类小说子类型) - dialogue 多轮多角色对话:回合、角色、场景(roleplay / 剧场) - -第二层:具体 Skill 包(name,用户启动时选) - 每个包 = orchestrator.md + workers/,不是 category 下的平铺 .md 枚举。 -``` - -示例: - -```text -category: novel ← 第一层:Book 怎么存 -name: novel-standard ← 第二层:标准长篇流程 -name: weird-rules-short ← 第二层:规则怪谈短篇(仍是 novel Book) -name: basic ← 第二层:最小演示 - -category: dialogue -name: theater-roleplay ← 第二层:剧场式多角色互动 -``` - -**不要把「规则怪谈」做成与 novel 平级的 category。** -规则怪谈是 **novel 形态下的专精 skill**,用 `name` + `tags` 区分: - -```yaml ---- -name: weird-rules-short -description: 短篇规则怪谈:从隐含核心反推护命规则,再成章撰写。 -category: novel -bookKind: novel -tags: [novel, weird_rules, short, horror] ---- -``` - -| 层级 | 字段 | 谁选 | 例子 | -|---|---|---|---| -| Book 形态 | `category` / `bookKind` | 选 skill 时确定,之后不变 | `novel` / `dialogue` | -| 具体流程 | `name` | 启动询问 1:选哪个 SKILL.md | `weird-rules-short` | -| 体裁标签 | `tags` | 可选,供匹配与过滤 | `weird_rules`, `standard` | - -启动 UI 可以按 `category` 分组展示,组内列出多个 `name`(如「小说」下:标准长篇、规则怪谈短篇、…)。 - -参考 Cursor `SKILL.md`:YAML frontmatter + Markdown 正文。 - -```markdown ---- -name: novel-standard -description: >- - 标准长篇小说创作:先简报、再大网、事件细化、正文。 - 适用于用户要写小说、章节、大纲时使用。 -category: novel -version: 1 -defaultFlowId: ghostwriting-flow -tags: [novel, outline, draft] ---- - -# 标准小说创作 - -## 启动询问 - -(流程 2:选 skill 后向用户展示什么、必收集项、写入 book.brief) - -## 创作总纲 - -(给编排器:这类内容是什么、总体顺序、禁忌) - -## 编排器思维链 - -(每轮决策前先检查什么、如何选 worker) - -## 推荐阶段 - -(brief → outline → plotline → style → draft) - -## 询问策略 - -### 编排器应先问 -### 交给 Worker 问 - -## 推荐 Worker - -## 示例 -``` - -### 3.1 Frontmatter 字段 - -```yaml ---- -name: novel-standard # 必需,唯一 id,[a-z0-9-] -description: > # 必需,供启动时向用户展示、供编排器匹配 - 第三人称描述 WHAT + WHEN。 -category: novel # 必需:Book 形态,见 §3.0 -bookKind: novel # 建议与 category 对齐;选定后 Book 结构固定 -version: 1 -defaultFlowId: ghostwriting-flow # 可选,绑定 execution flow -defaultPresetId: writing-default # 可选 -tags: [novel, standard] # 体裁/子类型标签,如 weird_rules、short -suggestedWorkers: # 可选,本 skill 常用 worker - - outline-worker - - plotline-worker - - drafting-worker ---- -``` +loader(`src/skills/loader.ts`)从 `orchestrator.md` 解析的字段: | 字段 | 必需 | 用途 | |---|---|---| -| `name` | ✅ | skill id;通常与文件名一致(不含 .md) | -| `description` | ✅ | 启动选择列表展示;编排器判断用户描述是否匹配 | +| `name` | ✅ | skill id | +| `description` | ✅ | 列表展示、匹配 | | `category` | ✅ | 与 `bookKind` 一致:`novel` \| `dialogue` | -| `bookKind` | 建议 | 选定后 Book 结构固定;缺省时由所在文件夹推断 | -| `tags` | | 体裁细分:`weird_rules`、`standard` 等 | -| `path` | registry | 相对路径,如 `novel/weird-rules-short.md` | -| `defaultFlowId` | | 选中后默认 execution flow | -| `suggestedWorkers` | | 编排器选 worker 时的白名单提示 | +| `bookKind` | 建议 | 缺省时由所在文件夹推断 | +| `workers` | 建议 | 本包可调度的 design worker id(亦认 `suggestedWorkers`) | +| `demandTag` | | 启动写入目标;缺省 `book.brief` | +| `startupMode` | | `agent-first`(默认)或 `intake`(legacy) | +| `uiPrompt` | | agent-first 首屏引导 | +| `tags` | | 体裁细分 | +| `version` | | 数字 | -### 3.2 撰写标准:写作生命周期(推荐) - -Skill 文件本质上是**给 LLM 与 Runtime 读的字符串规格**。下面这套「触发 → 写前 → 写中 → 写后 → 质量维度」与现有阶段机、验收模式对齐,**应作为所有 skill `.md` 的撰写标准**。 - -```text -┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ -│ 触发条件 │ → │ 写作前 │ → │ 写作中 │ → │ 写作后 │ → │ 质量维度 │ -│ 何时激活 │ │ 需求分析 │ │ 分步引导 │ │ 自检润色 │ │ 可量化 Rubric│ -└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ - frontmatter 启动询问 推荐阶段 自检清单 质量评估标准 - + tags + 创作总纲 + 示例/约束 + 验收策略 + 接受度(预留) - + 询问策略 + 禁用行为 -``` - -#### 与正文章节的对应关系 - -| 生命周期 | 对应章节 | 写什么 | -|---|---|---| -| **触发条件** | frontmatter `description` + `tags` | 何时应选本 skill;用户说什么话时应匹配(如「规则怪谈」「短篇怪谈」) | -| **写作前 · 需求分析** | `## 启动询问` + `## 创作总纲` | 对象、受众、语气、目标、禁忌;**禁止直接动笔**;写入哪个 key | -| **写作中 · 分步引导** | `## 推荐阶段` + `## 示例` + `## 禁用行为` | 阶段链、每步约束、好/坏示例;对应 worker 与产出 key | -| **写作后 · 自检润色** | `## 自检清单` + `## 验收策略` | 产出前检查点;LLM 自审 vs 人工 vs 程序验收 | -| **质量评估** | `## 质量评估标准` | 可量化维度 + 各 stage 的 acceptanceMode | -| **编排** | `## 编排器思维链` + `## 询问策略` + `## 推荐 Worker` | 编排器如何调度;谁向用户提问 | - -不必每个 skill 都写独立 `# 写作前` 大标题;**用统一章节名即可**,内容覆盖上表即可。 - -#### `## 质量评估标准`(必需) - -避免只写「写得更好」。每个 skill 应列出 **可检查的质量维度**,格式建议: - -```markdown -## 质量评估标准 - -| 维度 | 说明 | 检查方式 | -|---|---|---| -| 完整性 | 是否满足启动询问中的必收集项 | programmatic / 人工 | -| 体裁符合 | 是否符合创作总纲(如规则怪谈:规则可反推危险) | LLM 自审 + 人工 | -| 一致性 | 与已 accepted 上游产物是否矛盾 | programmatic | -| **接受度** | 用户/系统是否接受该产物(预留) | user_confirmed → 记录 accept/reject | - -各 stage 默认 acceptanceMode 见「验收策略」。 -``` - -**「接受度」维度(预留):** - -- 第一版:**不强制数值打分**;用阶段机的 `user_accepted_artifact` / `reject` 记录二元结果即可。 -- 后续可在 Book / Session 元数据写入 `acceptanceScore` 或 `acceptanceNotes`(字符串或 1–5 分),与 Skill Rubric 对齐。 -- Skill 里写清楚:**接受度由验收事件沉淀,不由 LLM 自报分数代替人工。** - -#### `## 自检清单`(必需) - -写作后、提交验收前,worker 或编排器应过的检查点(字符串列表即可): - -```markdown -## 自检清单 - -### rules.draft 提交前 -- [ ] 每条规则能否对应非玄学的危险动机? -- [ ] 是否未直接写出 core.danger? -- [ ] 是否无「违反即抹杀」空规则? - -### content.chapter.* 提交前 -- [ ] 是否遵守 rules.draft 已 accepted 版本? -- [ ] … -``` - -与 `programmatic_review` 的关系:自检清单 = LLM/人读的规范;程序验收 = 可机械执行的子集。 - -#### 模板骨架(`skills/{bookKind}/{name}.md`) - -```markdown ---- -name: … -description: … # 触发条件(WHEN) -tags: … -category / bookKind: … -suggestedWorkers: … ---- - -# 标题 - -## 启动询问 # 写作前 · 需求分析 -## 创作总纲 -## 编排器思维链 -## 推荐阶段 # 写作中 · 分步引导 -## 询问策略 -## 推荐 Worker -## 示例 # 写作中 · 约束与范例 -## 禁用行为 -## 自检清单 # 写作后 -## 验收策略 # 写作后 · 与 acceptanceMode 绑定 -## 质量评估标准 # Rubric + 接受度(预留) -## Book 结构 # 可选,novel / dialogue 形态说明 -``` - -代码当前**结构化解析**的仍主要是 `## 启动询问`;其余章节整段注入编排器 prompt(待 `buildSkillContext`)。**全部是 Markdown 字符串,不矛盾。** - -### 3.3 正文必需章节(检查清单) - -| 章节 | 生命周期 | 内容 | -|---|---|---| -| frontmatter | 触发 | name、description、tags、bookKind | -| **启动询问** | 写前 | 必收集项、写入 key | -| **创作总纲** | 写前 | 顺序、边界、体裁原则 | -| **推荐阶段** | 写中 | 阶段链、worker、产出 key、prerequisites | -| **示例** | 写中 | 好/坏对照或完整流程范例 | -| **禁用行为** | 写中 | 绝对不要做的事 | -| **自检清单** | 写后 | 提交验收前的检查点 | -| **验收策略** | 写后 | 各 stage 的 acceptanceMode | -| **质量评估标准** | 质量 | 可量化维度 + **接受度(预留)** | -| **编排器思维链** | 编排 | 每轮决策检查 | -| **询问策略** | 编排 | 编排器问 vs worker 问 | -| **推荐 Worker** | 编排 | 与 suggestedWorkers 一致 | - -可选:`## Book 结构`、`examples.md` 外链。 +正文章节、验收与禁用行为见 `orchestrator-skill-format.md`。不要再写「推荐阶段 / 质量评估标准 / 推荐 Worker」那套旧 SKILL 骨架。 --- -## 4. registry.yaml(可选) +## 4. registry.yaml -启动时列举可用 skill,不必扫描目录: +启动时列举可用 skill,不必全靠扫盘: ```yaml skills: - - name: novel-standard - description: 标准长篇小说:大纲 → 事件 → 正文 - category: novel - - name: weird-rules-short - description: 短篇规则怪谈:隐含核心 → 护命规则 → 成章 - category: novel - - name: theater-roleplay - description: 剧场式角色扮演:角色 → 场景 → 回合互动 + - name: world-simulator + description: 默认包:选配方 → 编排工作流计划 → 执行单元上场 category: dialogue - - name: forum-thread - description: 论坛体连载:楼主身份 → 回帖风格 → 楼层 - category: novel + bookKind: dialogue + path: dialogue/world-simulator/orchestrator.md ``` -若无 `registry.yaml`,Runtime 扫描 `skills/novel/*.md` 与 `skills/dialogue/*.md`。 -**registry 列举的是第二层 skill(name),不是 category。** +无 `registry.yaml` 时,Runtime 扫描 `skills/novel/` 与 `skills/dialogue/`。 +registry 列举的是第二层 skill(`name`),不是 category。 --- -## 5. 会话启动:描述需求,而非选包 +## 5. 会话启动 -新建作品 **不再** 让用户输入 skill name 或列表编号。Runtime 自动加载默认 orchestrator(`world-simulator`,见 `src/config/default-orchestrator.ts`),直接进入 intake。 - -### 5.1 启动转移 +新建作品 **不** 让用户输入 skill name。Runtime 加载默认编排器(`world-simulator`,见 `src/config/default-orchestrator.ts`),用户只选**配方**。 ```text idle session_started { initialSkill } - → waiting_user(intake) + → waiting_user(intake) # 展示 uiPrompt;用户描述需求 ``` `session_started` 携带 `initialSkill` 时跳过 `skill_selection`。 -registry 中其它包仅供 `startWithOrchestrator` / 旧作品读档兼容。 +registry 中其它包仅供 `startWithOrchestrator` / 旧作品读档。 -**Legacy(旧会话恢复):** +无 `initialSkill` 的旧快照才可能出现 `waiting_user(skill_selection)`。 -```text -session_started(无 initialSkill) - → waiting_user(skill_selection) # 仅旧快照可能出现 -``` - -```ts -| { kind: "skill_selection"; availableSkills: SkillIndexEntry[] } // legacy -| { kind: "intake"; prompt: string } -``` - -### 5.2 向用户展示 - -来自 orchestrator `## 启动询问`,例如 world-simulator: - -```text -请用你自己的话描述想做什么,例如: - -- 西幻升级、长篇 AI 交互、世界推着走 -- 部分代入:() 是指令,"" 是角色话,【】 是行动 -- 或:仿写/扩写、规则怪谈、快节奏爽文…… - -Agent 会根据你的描述推理需要哪些 Worker,并产出 Worker 集。 -``` - -### 5.3 用户回答方式 - -```text -直接描述创作目标(一句话即可) -``` - -Runtime 写入 `用户.需求`(或 skill 指定的 startupTargetKey),确认后进入 design stage。 - -### 5.4 两阶段启动(现行) - -```text -阶段 1(系统) 自动绑定默认 orchestrator -阶段 2(intake) 启动询问 → 用户描述需求 → confirm → agent burst -``` - -**Agent 根据需求编排能力并收成 worker 集**(`design-flow` → `design-step`),不再让用户在 registry 里四选一。 +用户回答写入 `demandTag`(现行包为 `用户.需求`),之后 `design-flow` → `design-step` 编排并收成 worker 集。 --- -## 6. 编排器如何使用已选 Skill +## 6. 解析与加载 -`session.slots.activeSkill` 加载后,编排器 prompt 注入: +| 文件 | 干嘛的 | +|---|---| +| `src/skills/types.ts` | SkillIndexEntry、ParsedSkill、ParsedWorkerSkill | +| `src/skills/loader.ts` | 读 registry 或扫盘;解析 orchestrator.md 与 workers/*/SKILL.md | +| `src/config/default-orchestrator.ts` | 默认包 id、uiPrompt 兜底 | -```text -当前 skill: novel-standard -category: novel -创作总纲: (SKILL.md 摘要或全文) -当前推荐阶段: outline(由 resolver 根据黑板推断) -询问策略: 编排器应先问 brief;outline 细节交给 worker -建议 worker: outline-worker, drafting-worker -defaultFlowId: ghostwriting-flow -``` - -编排器决策仍通过 tool / JSON 决策,**不**直接改 phase。 - ---- - -## 7. 示例 - -完整示例见仓库内真实文件(不要只在文档里维护一份): +完整示例以仓库内真实文件为准: ```text skills/dialogue/world-simulator/orchestrator.md @@ -451,62 +135,10 @@ skills/dialogue/world-simulator/modules/catalog.yaml skills/dialogue/world-simulator/recipes/catalog.yaml ``` -(历史示例 `skills/novel/weird-rules-short`、`theater-roleplay` 已不在仓库。) - --- -## 8. 解析与加载(将来代码) +## 7. 与其它文档 -| 文件 | 干嘛的 | -|---|---| -| `src/skills/types.ts` | SkillIndexEntry、ParsedSkill 类型 | -| `src/skills/loader.ts` | 扫描 skills/、解析 frontmatter + 正文 | -| `src/skills/registry.ts` | 读 registry.yaml 或目录扫描 | -| `src/skills/resolver.ts` | 根据黑板 index 推断当前 stage | - -加载流程: - -```text -listSkills() → SkillIndexEntry[] -loadSkill(skillId) → ParsedSkill(含 startupInquiry 解析自 ## 启动询问) -selectSkill(session, skillId) → session.slots.activeSkill -getStartupPrompt(activeSkill) → 流程 2 展示文案 -buildSkillContext(activeSkill, blackboardIndex) → 编排器 prompt 片段 -``` - ---- - -## 10. 与 creation-playbook.md 的关系 - -`creation-playbook.md` 描述**概念与数据结构**(Playbook、Stage、InquiryPolicy)。 - -**本文件**描述**落盘格式**(SKILL.md 怎么写、放哪、启动时怎么选)。 - -关系: - -```text -Creation Playbook(概念) - = SKILL.md(存储)+ stages.yaml(可选结构化) - + session.slots.activeSkill(运行时) -``` - -`creation-playbook.md` 中的 TS 类型,实现时可从 SKILL.md 解析或从 stages.yaml 读取。 - ---- - -## 11. 第一版范围 - -```text -skills/ 目录 + 示例 orchestrator 包 -启动 → 自动绑定默认 orchestrator → intake(描述需求) -编排器 prompt 注入 skill 摘要 -registry.yaml 可选(legacy 包 / 读档兼容) -``` - -不做: - -```text -skill 可视化编辑器 -运行时 LLM 自动生成 skill -与 Cursor .cursor/skills 混用(路径独立) -``` +`creation-playbook.md` 描述创作/游玩流程概念。 +本文件描述包怎么存、启动时怎么绑。 +方法正文见 `design-orchestrator-guide.md`。 diff --git a/docs/ui-design.md b/docs/ui-design.md index 48b926a..6c36e35 100644 --- a/docs/ui-design.md +++ b/docs/ui-design.md @@ -452,5 +452,5 @@ flowchart TB | `runtime-state-machine.md` | `waitingReason` 定义 | | `worker-skill-format.md` | `ask_user` / 提问侧契约 | | `run-snapshot.md` | 快照与分支;左轨/检查器入口 | -| `implementation-guide.md` | `web/*` 文件职责 | +| `implementation-guide.md` | 写代码规则与文档地图 | | `book-storage.md` | 作品、存档、资产形态 | diff --git a/docs/ui-glossary.md b/docs/ui-glossary.md index 021726c..f4a5629 100644 --- a/docs/ui-glossary.md +++ b/docs/ui-glossary.md @@ -183,7 +183,7 @@ | `input` | 补充说明 | 发送 / 补充并发送 | | `worker_questions` | 答题 | 补充并发送;已进技能步时旁挂「返回节点」 | | `approve_step` | 确认 | 同意并开始;重进已完成节点时文案为「回头修改 · {技能名}」;次要为「返回节点」 | -| `pick_creation_step` | 选节点 | 点可进入的节点即开始;要改排在底栏写意见再发 | +| `pick_creation_step` | 选节点 | 点图上可进入的节点即开始;要看技能池点上方「技能」;要改排在底栏写意见再发 | | `review_artifact` | 视产物(勿一律「验收」) | **流程编排** → 确认编排;技能步 → 接受;开场 → 选定此开场。旁挂「按意见改编排 / 按意见修改」 | | `next_intent` | 说话 | 继续(可留空) | | `revision` | 说话 | 按意见修改 | diff --git a/docs/world-simulator-modules.md b/docs/world-simulator-modules.md index 74a0d92..3e4edcd 100644 --- a/docs/world-simulator-modules.md +++ b/docs/world-simulator-modules.md @@ -8,6 +8,7 @@ > **游玩呈现壳**:**`docs/play-presentation-shells.md`**(预览页 `/shells.html`)。 > **主世界层↔旁观怎么配合**:**`docs/play-dm-auditor.md`**。 > **提示词待改清单**:**`docs/briefs/prompt-revision-inventory.md`**。 +> **design-flow 提示词人工审查**:**`docs/briefs/design-flow-prompt-review.md`**。 > **给外部 AI 的完整泛用规范**:**`docs/briefs/capability-authoring-brief.md`**(含 `context-fragment.v1`)。 ## 两层 @@ -44,7 +45,10 @@ name: … id: … artifact: 设计.… -declaration: … +declaration: … # 规划第一眼:解决什么缺口 +when: … # 对照现场能判定才排 +when_not: … # 每条指向另一技能或「不排」 +boundary: … ``` ## opening @@ -93,7 +97,18 @@ declaration: … | `params` | 可选;普通节点=编排期 `steps[].params` 声明(必填项须在进执行前钉齐)。〔先验产物〕=规划产物字段(可提前填,空则步内钉) | | `opening` | 可选覆盖;一般只写在 prompt 的 `opening` 块 | -编排器注入【能力 · 可选工序】时,会读取各能力 `prompt.md` 的 `meta`(`declaration` / `when` / `when_not` / `boundary`),**不是**只看 catalog 短声明。执行全文仍只在 design-step 注入。 +编排器注入【能力 · 可选工序】时,会读取各能力 `prompt.md` 的 `meta`(`declaration` / `when` / `when_not` / `boundary`),**不是**只看 catalog 短声明。执行全文(`task` / `opening` / `output` 等)仍只在 design-step 注入。 + +**写给规划,不是写给执行:** + +| 字段 | 规划用来做什么 | 怎么写 | +|------|----------------|--------| +| `declaration` | 扫描池时的第一眼 | 解决什么缺口;不要写产物 JSON 长什么样 | +| `when` | **现在**要不要进近期 DAG | 对照用户话、已验收步骤、已有产物就能判定的信号(还不能回答哪句 / 已有哪份产物) | +| `when_not` | 缺口其实该交给谁,或明确跳过 | 每条指向另一个技能或「不排」;不要只写禁止 | +| `boundary` | 别和邻居排重 | 本步定什么 / 不定什么 / 交给谁 | + +`when` 里不要搬 `task` 的执行细则。配方 `process` 只写方法顺序(如收成链、默认槽),**不要再抄各技能调用条件**。 ### 配方 `recipe.yaml` @@ -161,9 +176,10 @@ recipes/world-simulator|expand-assistant/recipe.yaml | 生成规则 | `generation-rules` | **已写**:`context-fragment.v1`;宽原则 + 严合同键;可反复;**〔先验产物〕**;规划字段 `target`;挂 gm+auditor;**专用卡已接** | | 具体实例 | `concrete-instances` | **已写**:`context-fragment.v1`;只按规则执行;可反复;**〔先验产物〕**;规划字段 `rule_id` | | 叙事指南与故事推进 | `narrative` | **已写**:一份全文双挂;**不**为省 token 拆投影;结构化卡 | -| 拓扑图谱 | `topology` | 骨架,待细写(拟改为选项小循环或降级) | -| 设计监控栏 | `status-bar` | **已写**:只盯会变信息;通用 fragment 卡 | -| 正文组成 | `reply-format` | **已写**:壳适配 + 正文.`示例`(present.v1 预览,看美化);P2 present 渲染已接 | +| 拓扑图谱 | `topology` | 必须生成且不适合走生成规则→实例时,用拓扑结构写出(升级路径、地图、人物关系等) | +| 回复呈现 | `status-bar` | **已写**:每轮终稿看什么(正文/字数/日期/变量);旧称设计监控栏 | +| 随机范围整理 | `random-range` | **已写**:汇总检定/对抗等随机项与范围;正文组成之前;替代机遇裁定槽 | +| 正文组成 | `reply-format` | **已写**:把回复呈现清单展示出来;选壳+美化,可写 CSS/HTML/JS;可接隐藏备用随机区 | | 变量设计与更新规则 | `variable-design` | **已写**;专用/结构化卡 | | 变量控制上下文 | `variable-context` | **已写**:旁观汇总;mount 含 auditor;通用 fragment 卡 | | 开场白与开场变量 | `opening-setup` | **已写**:开场守版式+同真相初值;**〔收口〕**选定后落库并保存定稿 | @@ -172,13 +188,13 @@ recipes/world-simulator|expand-assistant/recipe.yaml | 能力 | id | 状态 | |------|-----|------| -| 游玩拓扑 | `worker-spec` | **已写**:勾选固定槽(含旁观维护 auditor);禁自由发明 worker | +| 游玩拓扑 | `worker-spec` | **已写**:不能吃默认槽才勾选;主世界必要;有变量开旁观;禁机遇槽与自由发明 worker | | 上下文投影排序 | `context-order` | **已写**:扁平投影序(含对话.历史;旁观维护默认无历史);收成进 `context_order`;Runtime 已拼装 | | 细化终稿 | `refine` | **已写**:按 `play_slots`(及排序表)收成 `设计.worker集` | | 编排器 | 状态 | |------|------| -| 世界模拟器 | 创作链路已写;**play**:`gm → perspective? → narrator → auditor`;gm harness 批量 chance;settlement/maintain 合并变量已接 | +| 世界模拟器 | 创作链路已写;**play**:`gm → perspective? → narrator → auditor`;真随机改走随机范围表+程序插数(机遇槽弃用);settlement/maintain 合并变量已接 | | 扩写助手 | 方法论已写;起点:美学纲领与交互范式;勿默认套世界模拟全套 | --- diff --git a/skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md b/skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md index c375a59..1a5b65e 100644 --- a/skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md +++ b/skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md @@ -11,19 +11,19 @@ name: 美学纲领与交互范式 id: aesthetics-interaction artifact: 设计.美学纲领与交互范式 declaration: > - 钉清站位、正文呈现、核心体验与禁忌、何时等用户; - 询问相近故合为一步,勿拆成「交互」「美学」两步 + 钉清用户会在意的体验承诺:站位、反复感到什么、轮转何时停。询问相近故合为一步。 when: | - 可玩/可沉浸体验,但站位、呈现、核心感觉或轮转边界仍不清时; - 世界模拟类配方通常作为工作流计划第一步(无上游依赖)。 - 已有等价定稿且用户未要求重谈 → 不要重复排入。 + 还不能回答这三件:代入还是旁观?最想反复感到什么?轮转到哪必须停等用户? + 无上游,通常作第一步。 when_not: | - 只改实现细节且体验契约已验收;纯工具/排版;与「给玩家什么体验」无关。 + 这三件已有等价定稿、用户未要求重谈 → 不重复排入。 + 只改文风 → 「叙事指南与故事推进」;只改每轮看什么 → 「回复呈现」;只改排版/壳 → 「正文组成」。 + 只改舞台、规则、真值、槽位 → 对应下游技能。与「给玩家什么体验」无关 → 不排。 boundary: | - 本技能:体验是什么、怎么发生在用户身上、轮转怎么停;产出 context-fragment.v1。 + 本技能:体验是什么、怎么发生在用户身上、轮转怎么停。产出供后续编排阅读的开头节点。 叙事指南与故事推进:把感觉落成遣词/笔墨/禁忌与推进——本步只钉感觉与轮转。 舞台骨架 / 具体实例 / 生成规则:舞台与可执行规则——本步不定。 - 实现机制 / 变量* / 监控栏 / 正文组成 / 游玩拓扑 / 上下文投影排序 / 细化终稿:落到可运行结构——本步不定。 + 实现机制 / 变量* / 回复呈现 / 正文组成 / 游玩拓扑 / 上下文投影排序 / 细化终稿:落到可运行结构——本步不定。 feeds: design_only ``` diff --git a/skills/dialogue/world-simulator/modules/catalog.yaml b/skills/dialogue/world-simulator/modules/catalog.yaml index b8d4d51..705dff4 100644 --- a/skills/dialogue/world-simulator/modules/catalog.yaml +++ b/skills/dialogue/world-simulator/modules/catalog.yaml @@ -2,7 +2,7 @@ # 各【导演】与编排都从这里选型。 # id = modules/{id}/ 文件夹 # name = 固定中文名(流程 JSON 的 name;同能力可多次时靠 step.id 区分) -# declaration = catalog 短声明(可被 prompt.md ```meta 覆盖) +# declaration = 给人看/兜底的短声明(规划选型以 prompt.md ```meta 为准并覆盖本表) # artifact = 执行期产物 tag(程序映射;不写进流程 JSON) # repeatable = true 时允许同能力多次**新建**编入增量 DAG(如生成规则、具体实例)。 # 回头修改已完成节点不是 repeatable:用户在图上点该节点重进,不要排 mode=revise。 @@ -13,8 +13,9 @@ # 〔先验产物〕=规划产物字段(可提前填,空则步内钉) # opening = 可选;覆盖 prompt.md 里 ```opening 默认问题(一般只写在 prompt.md) # -# 编排选型:程序会读取各 modules/{id}/prompt.md 的 meta -# (declaration / when / when_not / boundary)注入 design-flow;勿只靠本表短声明。 +# 编排选型:程序读取各 modules/{id}/prompt.md 的 meta +# (declaration / when / when_not / boundary)注入 design-flow。 +# when/when_not 必须是规划对照用户话与已有产物就能判定的信号;调用条件写在技能 meta,不要写进配方 process。 # # 标准范例:aesthetics-interaction(美学纲领与交互范式) # 后来写能力:同结构 prompt.md(含默认问题)+ 本表一行索引 @@ -30,16 +31,16 @@ modules: - id: aesthetics-interaction name: 美学纲领与交互范式 declaration: >- - 钉清站位、正文呈现、核心体验与禁忌、何时等用户; - 询问相近故合为一步,勿拆成「交互」「美学」两步 + 钉清用户会在意的体验承诺:站位、反复感到什么、轮转何时停。 + 询问相近故合为一步。 artifact: 设计.美学纲领与交互范式 # —— 世界与内容 —— - id: world-blueprint name: 舞台骨架 declaration: >- - 体验需要可引用舞台时:钉尺度、基底与变造、关键舞台区,以及社会结构与世界状况; - 只细化会上台部分,不做地图百科 + 本局舞台备案:划出玩家实际游玩会换区活动的主要区域并写细; + 尺度与详细度随体验变。代入后几乎不移动、只在一处待着则不排 artifact: 设计.舞台骨架 - id: generation-rules @@ -47,8 +48,8 @@ modules: kind: prior-artifact repeatable: true declaration: >- - 仅当某类内容既重要又无法凭基底稳定生成时:写出规则 - (怎么描写/生成 + 产物格式 + 可选多池,池绑 JSON 字段);可按对象反复调用 + 要精准格式,或本局原创导致知识中无可参考对象、或难以在无指导情况下生成足够可信内容且故事里还要生成时:写出该对象族怎么生成; + 不填最终实例;可按对象反复 artifact: 设计.生成规则 params: - key: target @@ -66,7 +67,7 @@ modules: kind: prior-artifact repeatable: true declaration: >- - 按预生成规则原样产出实际产物;不设计、不改合同;可按 rule_id/批次反复调用 + 已有预生成规则时:按该规则原样交出 records;不设计、不改合同;可按规则/批次反复 artifact: 设计.具体实例 params: - key: rule_id @@ -82,49 +83,59 @@ modules: - id: narrative name: 叙事指南与故事推进 declaration: >- - 一次钉清写法与推进(遣词/笔墨/禁忌/示范 + 故事如何往前); - 整份双挂转述与主世界层,不为省 token 拆投影 + 美学已有方向时:把感觉落成可执行的遣词、笔墨落点、禁忌与推进方式; + 不重做体验问卷 artifact: 设计.叙事指南与故事推进 # —— 机制与数据 —— - id: mechanism name: 实现机制 declaration: >- - 核心体验已明时:识别承重切面(如何支撑 / 缺失后果),产出可挂主世界层的上下文片段; - 不重定体验、不写百科或执行单元 + 整体感觉已钉,故事里有必须当作既成事实的变造法则时: + 点出它们如何约束故事,不解释为何存在 artifact: 设计.实现机制 - id: topology name: 拓扑图谱 - declaration: 钉 worker/表/阶段的依赖、触发与数据流向;一张图说清谁读谁写 + declaration: >- + 必须生成、但不适合走「生成规则→具体实例」时:用拓扑结构写出来 + (升级路径、地图、人物关系等) artifact: 设计.拓扑图谱 - id: variable-design name: 变量设计与更新规则 declaration: >- - 钉真值字段、写入源(执行单元/用户/程序)、更新规则,以及按真值门控的 - side_effects(Progressive 投影);与运行规格 tables 对齐 + 体验必须跨轮记住少数状态时:钉真值、谁可写、如何变、维护语句, + 以及按值换文案的映射索引 artifact: 设计.变量设计与更新规则 - id: variable-context name: 变量控制上下文 declaration: >- - 钉真值与投影如何挂进主世界层等上下文:可见性、措辞、未解锁不注入 + 已有真值或映射时:钉谁看见什么(主世界层/转述/旁观)、未解锁不注入; + 无信息差则可不排 artifact: 设计.变量控制上下文 # —— 呈现 —— - id: status-bar - name: 设计监控栏 + name: 回复呈现 declaration: >- - 钉用户可见监控栏字段:只留会变、影响决策或沉浸的信息 - (主角/攻略目标/场景交互物等);旧称设计状态栏 + 几乎每局都要:钉每轮终稿的必选/可选区域,以及各区域的简单内容规则 + (字数、段落、选项怎么组成等);不排版 artifact: 设计.监控栏 + - id: random-range + name: 随机范围整理 + declaration: >- + 上游已有检定/对抗/掷骰需求时:汇总全部要用的随机项与取值范围(含表达式), + 供程序每轮插入备用随机数;排在正文组成之前 + artifact: 设计.随机范围整理 + - id: reply-format name: 正文组成 declaration: >- - 基于固定呈现壳做适配微调(选 shell_id + 字段/显示名等); - 产出壳适配单,禁止从零发明布局;旧称设计回复格式 + 把「回复呈现」已钉的内容展示给用户:选壳、美化排版,可写 CSS/HTML/JS; + 排在回复呈现之后、开场白之前;有随机表则一并接到隐藏备用区 artifact: 设计.正文组成 # —— 开局(创作偏晚) —— @@ -141,8 +152,8 @@ modules: name: 游玩拓扑 repeatable: false declaration: >- - 勾选固定游玩槽位(主世界层/叙事转述/可选角色视角/可选机遇裁定,或写手大纲+章节); - 禁止自由发明执行单元 + 不能吃默认槽时才勾选:主世界层必开;有变量/表才开旁观;转述默认开; + 强秘密才开视角;写手则大纲+章节;禁止发明执行单元与机遇槽 artifact: 设计.worker规格 - id: context-order @@ -150,13 +161,12 @@ modules: repeatable: false auto: true declaration: >- - 先抄固定执行单元名册,再为每个已启用者写出扁平投影序 - (含对话.历史与 projection);不发明槽、不重写长文、不演情节选择题 + 收成前给已启用槽排扁平投影序(含对话.历史); + 不发明槽、不重写长文、不演情节选择题 artifact: 设计.上下文投影排序 - id: refine name: 细化终稿 declaration: >- - 按已勾选固定槽与投影排序表收成运行规格(play_slots、常驻、表副作用); - 不发明新执行单元 + 按已勾选槽(或默认槽)与投影排序表收成运行规格;不发明新执行单元 artifact: 设计.worker集 diff --git a/skills/dialogue/world-simulator/modules/concrete-instances/prompt.md b/skills/dialogue/world-simulator/modules/concrete-instances/prompt.md index cf9595d..c0cd3ee 100644 --- a/skills/dialogue/world-simulator/modules/concrete-instances/prompt.md +++ b/skills/dialogue/world-simulator/modules/concrete-instances/prompt.md @@ -11,13 +11,13 @@ name: 具体实例 id: concrete-instances artifact: 设计.具体实例 declaration: > - 按一条预生成规则原样产出实际产物(单层 JSON records);可按 rule_id/批次反复调用; - 本步不设计、不改合同 + 已有预生成规则时:按该规则原样交出 records;不设计、不改合同;可按规则/批次反复 when: | - 「设计.生成规则」中已有 `seed_only` 或 `seed_and_runtime` 的规则,需要生成实际内容。 + 「设计.生成规则」里已有 `seed_only` 或 `seed_and_runtime` 的规则,且现在需要实际名片/记录(开局 NPC、种子事件等)。 when_not: | - `runtime_only` → 游玩期再生成。 - 无规则 / 规则不完整 / 想改格式或方法 → 回「生成规则」。 + 尚无规则或规则不完整 → 先「生成规则」。想改格式/方法/池 → 回「生成规则」,本步不改合同。 + 规则是 `runtime_only` → 不排,游玩期再生成。 + 只要规则不要预写实例 → 不排。 boundary: | 本技能只做一件事:按指定规则生成 records。规则说怎么写、什么格式、如何用池,就照做。 生成规则:合同制定方——本步不重论证、不修改。 diff --git a/skills/dialogue/world-simulator/modules/context-order/prompt.md b/skills/dialogue/world-simulator/modules/context-order/prompt.md index 184c7ff..ee863c8 100644 --- a/skills/dialogue/world-simulator/modules/context-order/prompt.md +++ b/skills/dialogue/world-simulator/modules/context-order/prompt.md @@ -12,16 +12,15 @@ name: 上下文投影排序 id: context-order artifact: 设计.上下文投影排序 declaration: > - 先列出本局固定执行单元(程序名册),再为每个已启用者写出扁平投影序 - (含对话.历史与 projection);不发明槽、不重写正文、不演情节选择题 + 收成前给已启用槽排扁平投影序(含对话.历史);不发明槽、不重写长文、不演情节选择题 when: | - 游玩槽已确认(或可按默认),且主要上下文块已有可摘要产物, - 需要决定各执行单元看见什么、以何顺序插入时。 + 游玩槽已确认(或可按默认),且主要上下文块已有可摘要产物,需要决定各执行单元看见什么、以何顺序插入。 + 本步为〔程序步〕:上下文已多、即将收成时排入。 when_not: | - 体验/站位仍混沌 → 先美学纲领与交互范式。 - 槽位未定且用户拒绝默认 → 先游玩拓扑。 + 体验/站位仍混沌 → 先「美学纲领与交互范式」。 + 槽位未定且用户拒绝默认 → 先「游玩拓扑」。 上游上下文仍大量空洞、无法判断稳/变 → 先补缺口,勿空排。 - 只需勾选槽 → 游玩拓扑;只需合并终稿 → 细化终稿。 + 只需勾选槽 → 「游玩拓扑」;上下文很少、只需合并终稿 → 「细化终稿」可按默认序退化。 boundary: | 本技能:抄名册 → 凭各块 brief/挂载/稳变 给每槽 inserts[]。 名册权威在程序(及已勾选的游玩拓扑);本步不增白名单外 id。 @@ -36,7 +35,8 @@ feeds: design_only ```opening 按已验收产物的概括,给每个固定执行单元分配上下文顺序(只排序,不改设定、不演游玩)。 -名册由程序钉死:主世界层 / 叙事转述 / 旁观维护(回合末)/ 可选角色视角 / 按需机遇(已并入主世界层工具)。 +名册由程序钉死:主世界层 / 叙事转述 / 旁观维护(回合末)/ 可选角色视角。 +无机遇裁定槽;「设计.随机范围整理」按 mount 挂进主世界层(等)inserts 即可。 若前面产物够用,直接回复「按已有概括排序」。 ``` @@ -47,21 +47,20 @@ feeds: design_only 执行顺序(必须按此,禁止颠倒): 1. **抄名册**:以程序注入的【本局固定执行单元】为准列出 agents[](id / label / enabled / when / duty)。 - 启用与否跟已勾选游玩拓扑走;未勾选则按默认:旁观+主世界层+转述开,角色视角关,机遇关。 + 启用与否跟已勾选游玩拓扑走;未勾选则按默认:主世界层+转述+旁观开,角色视角关(无机遇槽)。 2. **再分配**:只对 enabled 的每轮槽写 inserts(order / ref / projection / 可选 note)。 凭上游 **brief、挂载、稳变** 排序,禁止把百科全文再读一遍当创作。 规则: -1. 禁止发明白名单外 id(含画图等未入册槽)。 +1. 禁止发明白名单外 id(含画图、机遇裁定等未入册槽)。 2. 禁止重写上游长文;只写顺序与投影。 3. 每轮槽:order 0=该槽固定人设;其后按「稳→对话.历史→易变」软排。 4. 主世界层必须含 ref=`对话.历史`(默认 projection=summary);转述与旁观维护默认不含历史。 -5. 主世界层应双挂「设计.叙事指南与故事推进」等 mount 到 gm 的块;转述只读裁决+文风/壳。 +5. 主世界层应双挂「设计.叙事指南与故事推进」等 mount 到 gm 的块;有「设计.随机范围整理」则挂 gm(summary 即可);转述只读裁决+文风/壳。 6. 旁观维护在回合末:须含「运行.本轮.裁决」与变量合同,不含历史。 -5. 按需槽(机遇)enabled 时 inserts 可空。 -6. 越稳越靠前;本轮输入/真值/裁决通常在历史之后。 -7. 同一内容可挂多槽;chance 不必排进每轮 inserts。 -8. summary:如 `投影排序 · 旁观+主世界层+转述`。 +7. 越稳越靠前;本轮输入/真值/裁决通常在历史之后。 +8. 同一内容可挂多槽。 +9. summary:如 `投影排序 · 旁观+主世界层+转述`。 若程序已发默认问题:禁止重复同一开场;用户说「按已有概括排序」或等价同意 → **立刻产出表**,禁止再问情节内选项。 禁止 askUser 出游玩选择题(迎上去/推开她/反客为主 等)。材料已齐则顶层 askUser 为 null。 @@ -149,14 +148,6 @@ feeds: design_only "when": "every_turn", "duty": "强信息隔离时出反应建议", "inserts": [] - }, - { - "id": "chance", - "label": "机遇裁定", - "enabled": false, - "when": "on_demand", - "duty": "骰子/抽签;按需调用,不进每轮", - "inserts": [] } ] } @@ -165,7 +156,7 @@ feeds: design_only ## checklist ```checklist -- [ ] agents 只使用程序名册 id(auditor / gm / narrator / perspective / chance) +- [ ] agents 只使用程序名册 id(auditor / gm / narrator / perspective);无 chance - [ ] 未发明白名单外执行单元 - [ ] 未重写上游长文,只有排序/投影 - [ ] 未把游玩选项示例当成当前提问 @@ -173,5 +164,5 @@ feeds: design_only - [ ] 主世界层含「对话.历史」;转述与旁观维护默认无历史 - [ ] 旁观维护含「运行.本轮.裁决」;转述含裁决且不含历史 - [ ] 少变块整体靠前、本轮/真值靠后(软规则) -- [ ] 与游玩拓扑勾选一致 +- [ ] 与游玩拓扑勾选一致;有随机范围表则已挂 gm ``` diff --git a/skills/dialogue/world-simulator/modules/generation-rules/prompt.md b/skills/dialogue/world-simulator/modules/generation-rules/prompt.md index 0fa3ce5..6db11f0 100644 --- a/skills/dialogue/world-simulator/modules/generation-rules/prompt.md +++ b/skills/dialogue/world-simulator/modules/generation-rules/prompt.md @@ -11,25 +11,23 @@ name: 生成规则 id: generation-rules artifact: 设计.生成规则 declaration: > - 仅当某类内容既重要又无法凭基底稳定生成时:为该对象族写出一条可执行规则 - (怎么描写/生成 + 产物格式 + 可选多池,池绑 JSON 字段);可按对象反复调用;本步不填最终实例 + 要精准格式,或本局原创听了会雾且故事里还要生成时:写出该对象族怎么生成(描写/格式/可选池);不填最终实例;可按对象反复 when: | - 上游体验与世界基底已足以判断某类内容同时满足: - 1. 对游玩重要;2. 仅凭现有上下文无法稳定产出合格、一致、可供下游使用的结果。 + 已有「美学纲领与交互范式」或等价整体感觉,且下面两条满足一条就排(可按对象族反复): + a. 生成物必须有精准格式。例:武功典籍要有名字、效果、阶层。 + b. 本局原创、听了会一头雾水的东西,故事里还要随机/反复生成。例:人人能绽放的「心之彩」;当成本局原创的斩魄刀。 when_not: | - 重要但常识/世界基底已够 → 不建规则。 - 难生成但不影响核心体验 → 不建规则。 - 只要预写最终记录、且不需专门规则 → 通常不必本步。 - 变量如何增减 → 「变量设计与更新规则」。 - 剧情如何推进 → 不借本步泛化。 + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 常识能推、也不需要精准格式(现实名车、西幻常见种族)→ 不排。 + 只要几张具名名片、不必按规则生成 → 不排;已有规则再要名片 → 「具体实例」。 + 跨轮记住什么 → 「变量设计与更新规则」。故事怎么往前写 → 「叙事指南与故事推进」。 boundary: | - 本技能产出的是「规则」本身,一条规则包含: - (1)应该怎么描写、生成;(2)产物格式——单层 JSON(对接表格/旁观者/投影); - (3)可选多「池」——各挂一个顶层字段,供抽取/组装/枚举。 + 本技能:一条规则=怎么描写/生成 + 单层 JSON 产物格式 + 可选多池(各绑一个顶层字段)。 具体实例:按规则填最终 records;本步不写最终实例(池条目≠实例)。 - 舞台骨架 / 实现机制:可引用,不重写百科、不重做移除检验。 + 舞台骨架 / 实现机制:可引用,不重写百科、不重钉既成法则。 变量*:游玩期状态更新——本步只约束生成时的类型与合法初值范围。 - 旁观维护:可读「合同」——rule_id、产物格式、何时可 need_generate;不依赖整份描写长文。 + 随机范围整理:把本步(及其他上游)里需要的掷骰/检定范围收成插入表——本步可写合法区间,不代替那份汇总。 + 旁观维护:可读合同(rule_id、产物格式、何时可 need_generate);不依赖整份描写长文。 feeds: gm,auditor ``` @@ -41,10 +39,11 @@ feeds: gm,auditor - 若规划为空,先钉对象族,再谈规则。 然后谈: -1. 若不做专门规则、只靠世界设定临场写,最怕出现什么不可接受的结果? -2. 更需要:开局先钉一批、游玩中再随机补,还是只在游玩期动态生成? -3. 这类实例彼此有没有必须同场钉死的关系(如互为亲属、对立、同场搭档)?有 → 一次同批生成;彼此独立 → 一次一条。 -4. 哪些产物字段需要「池」?(池挂在 JSON 字段上,如气质标签池→`气质`;可多个;没有就说没有) +1. 生成出来必须钉死哪些字段吗?(如武功典籍的名字、效果、阶层)没有就说没有。 +2. 这是不是本局原创、听了会一头雾水、还要在故事里随机生成的东西? +3. 更需要:开局先钉一批、游玩中再随机补,还是只在游玩期动态生成? +4. 这类实例彼此有没有必须同场钉死的关系(如互为亲属、对立、同场搭档)?有 → 一次同批生成;彼此独立 → 一次一条。 +5. 哪些产物字段需要「池」?(池挂在 JSON 字段上,如气质标签池→`气质`;可多个;没有就说没有) 想到什么写什么;完整规则在正式产物里钉。 ``` @@ -64,7 +63,7 @@ feeds: gm,auditor 执行顺序: 1. 认定对象族:规划有 `target` 则采用(用户要改则以最新为准);规划为空则先钉对象。不要停下来让编排器补参。 -2. 双门槛:重要性 + 基础上下文不足。任一项不成立 → 结论「无需专门规则」,`rules: []`。 +2. 对照时机 a/b:必须有精准格式,或本局原创听了会雾且故事里还要生成。两条都不成立 → 结论「无需专门规则」,`rules: []`。 3. 两项成立时,生命周期三选一(规划里 `lifecycle_intent` 合理则采用): - `runtime_only`:仅游玩期动态生成;不要求「具体实例」。 - `seed_only`:由「具体实例」预生成;规则用完可丢。 @@ -85,7 +84,7 @@ summary:建立 → `生成规则 · {对象} · {仅动态|仅预生成|预生 ## principles ```principles -1. 整条规则先问必要性:是否值得单独用「生成规则」承接?双门槛不成立则跳过,勿硬造表。 +1. 整条规则先问必要性:时机 a(精准格式)或时机 b(原创会雾且还要生成)是否成立?两条都不成立则跳过,勿硬造表。 2. 一调用一对象族;格式或用途不同则分次编排。 3. 规则 = 描写/生成方法 + 产物格式;池是可选附属(可多池),不是必填第三设计。 4. 属性逐个过筛:每个字段必须对本对象族有意义;禁塞通用名片字段,也禁漏掉玩法接口字段。 @@ -104,7 +103,7 @@ summary:建立 → `生成规则 · {对象} · {仅动态|仅预生成|预生 每轮 1~2 点。规划已钉且用户未改对象时,禁止重问 target / rule_id。规划为空或用户要换对象时,先问本轮生成什么。 优先:整条规则是否必要;实例彼此有无必须同场对齐的关系(一次生成:同批 vs 单条);某字段该不该进表(冗余 vs 漏接口);单层格式类型/枚举/边界;哪些字段要池。 -若双门槛不成立 → 建议跳过,停追问字段与格式。 +若时机 a/b 都不成立 → 建议跳过,停追问字段与格式。 不追问:最终实例正文、变量增减公式、其它对象族、完整世界百科。 ``` @@ -125,8 +124,8 @@ summary:建立 → `生成规则 · {对象} · {仅动态|仅预生成|预生 }, "必要性判断": { "生成对象": "本轮对象族", - "对游玩的重要性": "没有专门规则会损失什么", - "基础生成的不足": "现有上下文为何不够;若足够则写清", + "对游玩的重要性": "时机 a:必须钉死哪些字段;无则写「不需精准格式」", + "基础生成的不足": "时机 b:为何听了会雾、现有常识推不出;能推则写清", "结论": "建立专门规则|无需专门规则" }, "rules": [ @@ -212,7 +211,7 @@ summary:建立 → `生成规则 · {对象} · {仅动态|仅预生成|预生 { "名": "必要性", "分数": 8, - "说明": "整条规则:是否有必要单独用「生成规则」承接该类内容;跳过时理由是否充分" + "说明": "时机 a 或 b 是否成立;跳过时理由是否充分" }, { "名": "属性妥当", @@ -266,12 +265,14 @@ summary:建立 → `生成规则 · {对象} · {仅动态|仅预生成|预生 ```examples 好: +- 武功典籍:单层含 名字/效果/阶层(时机 a)。 +- 「心之彩」:本局原创、听了会雾,故事里还要随机生成(时机 b)。 - D&D 怪物:单层含 名称/等级/攻击骰/……;池可绑 `气质`;自评属性妥当高(未漏战斗接口)。 - 女主规则:不设「性别」字段;关系切面进表;池可空。 - 互为仇敌的两名开局 NPC:一次生成=同批,关系写清对立如何对齐;数量=2。 - 可互换的酒馆路人:一次生成=单条,关系写「彼此独立」;要 5 个就点 5 次。 - 事件钩子:池绑顶层 `钩子`;方法写抽 1~2 条写入该字段。 -- 普通古董 → 无需专门规则(必要性维度说明跳过理由)。 +- 现实名车、西幻常见种族 → 无需专门规则(常识能推且不需精准格式)。 坏: - 产物写成 `{ "外貌": { "发色": "…" } }` → 非单层,前端表格/投影难对接。 diff --git a/skills/dialogue/world-simulator/modules/mechanism/prompt.md b/skills/dialogue/world-simulator/modules/mechanism/prompt.md index a556735..68b8d58 100644 --- a/skills/dialogue/world-simulator/modules/mechanism/prompt.md +++ b/skills/dialogue/world-simulator/modules/mechanism/prompt.md @@ -1,4 +1,4 @@ -# 实现机制 +# 实现机制 > 技能文档。程序只切割下方 **fence 块**;`##` 标题仅供人读。 > 产物外壳对齐:`docs/context-fragment-design.md`;范例:`aesthetics-interaction`。 @@ -10,39 +10,34 @@ name: 实现机制 id: mechanism artifact: 设计.实现机制 declaration: > - 当核心体验已经明确,需要识别由哪些角色、世界、关系、规则或情境切面支撑, - 并把体验落成可供后续设定工作的核心支点时使用 + 整体感觉已钉,故事里有必须当作既成事实的变造法则(科幻意义上的第一初设定)时:点出它们如何约束故事,不解释为何存在 when: | - 已有「美学纲领与交互范式」或等价的体验声明,但还不能回答: - “这个体验具体靠什么存在?” - “拿掉哪些东西后,核心感觉就会明显变质?” - “哪些设定切面必须被后续世界、角色与规则设计继承?” + 已有「美学纲领与交互范式」或等价整体感觉,且用户表述或美学卡里有必须当作既成事实的变造法则。 + 例:现代都市但已繁荣一统、存在修炼体系;三体黑暗森林;机器人三定律。 + 特征:故事不必纠结它为什么存在,拿掉则故事骨架会换。 when_not: | - 核心体验尚未明确 → 先「美学纲领与交互范式」。 - 只需补舞台骨架/实例 → 「舞台骨架」或「具体实例」。 - 需持续生成规则 → 「生成规则」;需真值门控 → 「变量设计与更新规则」。 - 只需叙述呈现与推进口径 → 「叙事指南与故事推进」。 + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 没有特殊变造,或「特殊」只是身份/开场处境、能被「舞台骨架」「具体实例」「开场白与开场变量」覆盖(如现实世界模拟普通大学生)→ 不排。 boundary: | - 本技能:识别支撑核心体验的关键切面(如何支撑 / 缺失后果);产出 context-fragment.v1。 - 美学纲领与交互范式:体验目标与轮转——本步不重定。 - 舞台骨架 / 具体实例 / 生成规则 / 变量* / 叙事指南与故事推进:展开环境、实例、生成、真值、写法——本步只钉承重切面。 + 本技能:点名故事当作既成事实的变造法则,写清如何约束后续;不补起源、不写舞台百科、不写人物名片。 + 美学纲领与交互范式:体验与轮转——本步不重定。 + 舞台骨架:环境与社会格局。具体实例 / 开场白与开场变量:名片与第一屏(身份特殊走它们)。 + 生成规则 / 变量* / 叙事指南与故事推进:持续生成、跨轮真值、遣词推进——本步只钉前提法则。 feeds: gm ``` ## opening ```opening -核心体验已有方向时,用几句话想想:它具体靠什么撑住?(想到什么写什么,不必整齐;点名即可,不必论证来源或补起源史。) +整体感觉已有方向时,把故事里「必须当作已经成立」的变造法则点出来(想到什么写什么;点名即可,不必解释它为什么存在)。 -1. 这体验主要靠哪些东西成立? - 角色的某一面、一段关系、世界条件、规则或情境……用你自己的词点名。 - 例:丈夫会把异常证据合理化;力量越用越侵蚀自我;村里每年必须献祭才能过冬。 +1. 这局有哪些特殊变造,后续情节都得认它? + 例:现代都市,但世界已繁荣一统;存在修炼体系;黑暗森林法则;机器人三定律。 -2. 拿掉或改弱哪一样,核心感觉会明显变味甚至垮掉? - 一句话即可——只点「缺了就不对」的,装饰和以后再展开的先别列。 +2. 拿掉或改弱哪一条,故事骨架会换成另一个? + 一句话——只点「缺了就不是这个故事」的。 -3. 若已有具体画面或作品参照,它主要指哪一切面在撑体验? - 例:信息差、无法撤销的前提、身份代价、循环反馈……不必复述整部设定。 +3. 若只是某人身份特殊、开场处境特殊,先别写在这里(那是舞台 / 人物 / 开场白)。 ``` ## task @@ -50,21 +45,21 @@ feeds: gm ```task 你正在执行「实现机制」。产物必须是 **context-fragment.v1** JSON,写入「设计.实现机制」。 -这里的「机制」不是必须解释到底的科学原理,也不等于程序规则。它更接近可直接成立的初始设定:后续内容依赖它,本步不必补起源史或完整理论。 +本步钉的是故事的第一初设定:已被承认、不必解释来源、却会决定后续能不能这么写的变造法则。不是科学原理,不是舞台百科,也不是人物名片。 -核心操作:从已确认的核心体验出发,追问「什么在支撑它」,识别缺失后会让体验不成立、变弱或变质的角色、关系、世界、规则与情境切面。 +从已确认的整体感觉出发,点出这些法则,写清它们如何约束故事、拿掉会怎样。用户没有这类特殊变造:覆盖检验写明「无特殊法则」,追问确认是否跳过;身份/开场类特殊交给「舞台骨架」「具体实例」「开场白与开场变量」。 执行顺序: -1. 读依赖产物与用户表述,忠实提取核心体验;不重做美学/交互。 +1. 读依赖产物与用户表述,忠实提取整体感觉与已点名的变造;不重做美学/交互。 2. 思考阶段判断基准世界可能性范围(只校验,不写入产物)。 -3. 检查体验如何产生、增强、维持,及多支点如何共同成立。 -4. 对每个候选做移除检验。 -5. 只保留有明确支撑关系的主要支点;常识、装饰、完整人物卡、后续技能展开对象不纳入。 -6. 写入正文:依据体验、支撑点(含切面形态)、支撑点关系、覆盖判断。 +3. 列出必须当作既成事实的变造法则,检查拿掉后故事骨架是否会换。 +4. 对每条候选做移除检验。 +5. 只保留缺了会换骨架的法则;常识、装饰、人物名片、开场处境、后续技能展开对象不纳入。 +6. 写入正文:依据体验、支撑点(每条法则)、支撑点关系、覆盖判断。 7. 填自评与追问(薄弱点才问;题目可空数组)。 8. 输出符合 output 契约的 JSON。 -工作姿态——「识别已经在那里之物」:不另造体验;不设设定菜单;不题材套件;可整理未命名关系;可暂定请用户修正;二选一支点先问清再写。 +工作姿态——「点出已经成立之物」:不另造体验;不补起源史;不设设定菜单;不题材套件;可整理用户未命名的法则并请修正;二选一先问清再写。 依赖含混时不越权重做上一步。无法在本步解决的写入开放问题或追问。 @@ -75,25 +70,22 @@ summary:`实现机制 · …`(点题主要支撑)。 ## principles ```principles -1. 体验向支撑正推 - 始终保持:核心体验 → 成立所需条件 → 承担该条件的具体元素 → 该元素真正相关的切面 → 切面如何支撑体验。 - 不能从题材标签、常见套路或预制角色清单反推「应该具有什么」。题材只能提供可能性,不能代替支撑关系。 +1. 从整体感觉正推到既成法则 + 始终保持:整体感觉 → 故事必须承认的变造法则 → 该法则如何约束后续。 + 题材标签不能代替「这条法则缺了故事会换」。 -2. 支撑点不是完整设定 - 同一元素可有很多面向,本步只描述承担支撑功能的那一面。 - 例:「丈夫」可有职业、外貌、童年;若核心体验只依赖认知过滤,本步只写认知过滤如何运作及支撑了什么,不补完整人物小传。 +2. 法则不是完整设定 + 同一设定可有很多面向,本步只写「当作已经成立、后续必须认」的那一面。钉的就是这类既成事实整句,不顺着去补体系百科: + 这个世界没有花里胡哨的魔法,只有繁衍到极致的斗气。 + 这个西幻世界里,男尊女卑是常态。 + 这里以三国杀高手为尊。 3. 以缺失后果检验必要性 - 每个支撑点至少能回答其一,最好两个都能答: - - 它如何让某项核心体验产生、增强或持续? - - 缺少它以后,哪项核心体验会消失、减弱或改变性质? - 只能回答「更丰富」「一般都会有」「以后可能用得上」的,不是本步核心支点。 + 每条法则至少能回答:拿掉以后,故事骨架会换成哪一个?只能回答「更丰富」「以后可能用得上」的,不纳入。 -4. 机制可以是不同性质的切面 - 不必都是世界法则,也不必形成统一机械系统。可以是: - 角色的认知/欲望/能力/限制/心理张力;关系结构;社会制度/习俗/权力/信息条件; - 环境物理/空间/资源;被直接承认的超常前提;约束/循环/反馈;反衬/代价/对照。 - 按体验所需识别性质,不把所有支点强行改写成规则。 +4. 本步写的是第一初设定,不是人物或舞台 + 可以是:被直接承认的超常前提、已完成的世界变造(繁荣一统)、约束性公理(黑暗森林、三定律)、体系性硬规则(修炼境界)。 + 人物个性、身份特殊、开场处境、地理社会展开,交给舞台 / 实例 / 开场白。 5. 基准世界只作内部校验 思考阶段判断「什么可能存在」,不要写入产物。最小充分继承: @@ -102,12 +94,12 @@ summary:`实现机制 · …`(点题主要支撑)。 - 具体作品世界:优先最近一层作品设定;原作未定义处再参考其底层世界。 - 类型世界:只继承与当前体验有关的类型约定,不带入类型全部常见元素。 - 从头创造:显式设定优先;未定义处用最少量常识基础。 - - 混合或二创:只处理与当前支撑点有关的继承与变造,不整理完整谱系。 - 变造可表现为情境极端化、既有效果强化或新增法则。候选超出已知可能性时不要暗中加入;先确认变造是否本在用户设想中。 + - 混合或二创:只处理与当前法则有关的继承与变造,不整理完整谱系。 + 候选超出已知可能性时先确认变造是否本在用户设想中,不暗中加入。 -6. 初始设定可以不解释来源 - 解释「它怎样支撑体验」,不要求「宇宙为什么会有它」。 - 超常前提、社会常态或人物特性可作为初始事实成立;不要为显得严谨而补起源、发明者、历史沿革或伪科学理论,除非这些本身就是核心体验的支撑。 +6. 法则可以不解释来源 + 写清「它怎样约束故事」,不要求「宇宙为什么会有它」。 + 不为显得严谨而补起源、发明者、历史沿革或伪科学理论,除非「追查来源」本身就是这条法则要支撑的体验。 7. 按真实复杂度描述 一句话能说清就用一句话;否则才按过程、张力、层次、构成、循环或关系网展开。 @@ -263,7 +255,7 @@ summary:`实现机制 · …`(点题主要支撑)。 - [ ] 依据的核心体验忠实来自上游,非本步新设计? - [ ] 每个支撑点有归属元素、切面、如何支撑、缺失后果? - [ ] 自评含覆盖度 / 充分度 / 克制度? -- [ ] 未写成设定菜单、人物卡、起源史、叙事指南与故事推进、order 表? +- [ ] 未把身份/开场处境写成法则?未写成设定菜单、人物卡、起源史、order 表? - [ ] 宁少勿多;支撑点关系仅保留有体验作用的项(可空)? - [ ] 追问只打会改变支点的缺口,带建议选项? ``` @@ -272,23 +264,23 @@ summary:`实现机制 · …`(点题主要支撑)。 ```examples 好: -- brief「秘密靠丈夫认知过滤与证据逼近维持」;正文有依据体验 + 支撑点(认知切面过移除检验)+ 覆盖检验;自评三维(覆盖/充分/克制);追问用短场景打待探。 -- 循环支点「力量与自我侵蚀同步」:展开诱因/收益/代价/反馈;与「身边人延迟识别」写进支撑点关系。 +- brief「现代都市认修炼境界与繁荣一统」;正文有依据体验 + 支撑点(修炼可越级、世界已一统)过移除检验;自评三维;无宗门百科。 +- 公理支点「黑暗森林」:一句话钉「猜到即打击」;不写宇宙社会学论文。 - 整份落在 context-fragment.v1;支撑点切片示例: { - "名称": "丈夫的认知过滤", - "归属元素": "丈夫", - "支撑切面": "面对威胁完美家庭信念的证据时,优先采用无害解释", - "切面形态": { "结构": "一句话", "概述": "维护既有信念的认知过滤,而非单纯迟钝。", "展开": [] }, - "对应体验": ["秘密长期存在", "濒临暴露的紧张"], - "如何支撑": "可疑证据可出现而不立刻终结秘密。", - "缺失后果": "若能直接识别证据则秘密速终;若永无证据则紧张消失。", + "名称": "黑暗森林", + "归属元素": "宇宙公理", + "支撑切面": "暴露坐标即招来打击,文明默认隐藏", + "切面形态": { "结构": "一句话", "概述": "被承认的既成法则,不解释为何如此。", "展开": [] }, + "对应体验": ["猜疑链下的生存紧张"], + "如何支撑": "后续情节不能靠「对外广播求援」轻松收场。", + "缺失后果": "若可公开求援而不被打击,故事从藏匿改成外交。", "完备度": "90%" } 坏: - 设定菜单:「可选诅咒/寄生物/邪神…」 -- 人物卡膨胀;叙事文风;无必要起源史 +- 把普通大学生的身份特殊写成法则;起源史、人物卡、舞台百科 - 只有散文支点、无 schema / 自评 / 追问 ``` diff --git a/skills/dialogue/world-simulator/modules/narrative/prompt.md b/skills/dialogue/world-simulator/modules/narrative/prompt.md index c5f114d..f8632fa 100644 --- a/skills/dialogue/world-simulator/modules/narrative/prompt.md +++ b/skills/dialogue/world-simulator/modules/narrative/prompt.md @@ -12,14 +12,15 @@ name: 叙事指南与故事推进 id: narrative artifact: 设计.叙事指南与故事推进 declaration: > - 一次钉清写法与推进:遣词、笔墨、禁忌、示范,以及故事如何往前(可含变量钩子); - 不重做美学感觉问卷;整份双挂转述与主世界层 + 美学已有方向时:把感觉落成可执行的遣词、笔墨落点、禁忌与推进方式;不重做体验问卷 when: | - 已有美学纲领,需要把感觉落成可执行的写法与推进时。 + 已有美学纲领(或等价),但转述/主世界层仍会不知道这四件:遣词什么味道、笔墨落谁身上、绝对不能写什么、故事靠场面自己推还是等用户。 + 用户主动谈文风、措辞禁忌、写法档(官能/爽文/恐怖/情色等)也排。 when_not: | 美学未钉 → 先「美学纲领与交互范式」。 - 版式/监控栏 → 「正文组成」/「设计监控栏」。 - 事件池 schema / side_effects → 「生成规则」/「变量设计」。 + 用户只要感觉/站位、不要文风细则 → 不排,沿用美学。 + 版式/壳 → 「正文组成」;每轮看什么(字数/变量/日期)→ 「回复呈现」。 + 事件池 schema、真值增减 → 「生成规则」/「变量设计与更新规则」。 boundary: | 本技能:一份 context-fragment,写清怎么写 + 怎么推;不必拆技能、也不必为省 token 做精细双投影。 美学:感觉与轮转。生成规则/变量*:合同与表。 @@ -33,6 +34,9 @@ feeds: narrator,gm 1. 像什么文风?遣词什么味道?笔墨花在谁身上?有什么绝对不能写? 2. 故事往前靠什么:场面自己推、等用户决策,还是无专门推进?正文若有几种写法档要切换(官能 / 爽文 / 恐怖 / 情色这类),点名即可;没有就说没有。 +3. 用户每轮输入怎么用?未提及时按体验二选一写入(可简短确认,不必当缺口追问): + - **大纲扩写**(写手/成稿向):输入=待扩写为事实的大纲;细化完全后写正文;不超出大纲未涉及的剧情,完整演绎大纲。 + - **扮演停笔**(代入扮演、等用户决策):用户本轮行为与对话作正文开头并扩写填满;不可写用户角色未给出的其它行为/对话;不可替用户角色做决定;正文停在其他角色等用户角色回应之刻。 ``` ## task @@ -46,8 +50,13 @@ mount:`narrator` 与 `world-simulator` 都挂同一份全文——不要为省 执行顺序: 1. 继承美学体验与禁忌,改写成做法向句子。 2. 写纲领、遣词(含示范)、笔墨焦点、禁忌/不偏好。 + 遣词用户未提段落形态时,默认写入:完整长自然段叙述,不要单句成段(篇幅数字交给「回复呈现」)。 3. 情境备用 = 写法档(体裁/调性容器),不是具体桥段。有切换则每条写:名字=档名(如「官能小说」「网文爽文」「展示恐怖」「展示情色」),用法=该档怎么遣词、笔墨落哪、何时切进来。无切换则 `[]`。用户若报出「当众折辱」「独处一室」这类场合,升一档写进对应写法档,场合本身不单列。 4. 写推进与决策(可写「无专门推进」);变量只写钩子。 + 「用户输入用法」未提及时:按美学/交互范式选一种写入产物—— + - 写手/大纲成稿 → **大纲扩写**(输入=大纲→细化成正文;不越界、完整演绎); + - 代入扮演、轮转等用户决策 → **扮演停笔**(输入的行为与对话作正文开头并扩写填满;不写用户角色未给出的行为/对话;不替用户角色做决定;停在其他角色等回应之刻)。 + 两种都像则写进追问让用户点一次;不要混成半套规则。 5. 自评 + 追问。 summary:`叙事指南与故事推进 · …` @@ -58,9 +67,14 @@ summary:`叙事指南与故事推进 · …` ```principles 1. 感觉 vs 做法:美学写要什么爽;本步写怎么遣词、笔墨落哪、故事怎么推。 2. 遣词与禁忌要可执行;绝对禁忌 ≠ 不偏好。 + 用户未提及时:完整长自然段,不要单句成段。 3. 推进可轻可无;表规格交给变量/生成规则。 + 用户输入用法两套可选默认(未提及时择一,勿混用): + - 大纲扩写:输入=大纲→扩写为事实→细化后正文;不发明大纲未涉及的剧情,完整演绎大纲。 + - 扮演停笔:用户本轮行为与对话→正文开头并扩写填满;禁止描述用户角色未输入的其它行为/对话;禁止替用户角色做决定;正文停在其他角色需要用户角色回应之刻。 4. 情境备用是写法档:名字用「官能小说」「网文爽文」「展示恐怖」「展示情色」同级;用法写该档遣词与何时切入。无切换则空数组。 5. 整份双挂即可;禁止拆成两个技能。 +6. 字数区间归「回复呈现」;本步管怎么写与怎么推,不重钉字数。 ``` ## probe @@ -70,10 +84,14 @@ summary:`叙事指南与故事推进 · …` 已在美学写清的感觉改写成做法向句子,不重问「想感受到什么」。 -缺其中一件:在产物「追问」写 1~2 点(建议选项 + 短句示例)。四件够验收:`追问.题目` 为 `[]`。推进方式不明则正文写「无专门推进」,不问好感公式、进度表或事件池。 +用户未提段落形态时:写入长自然段默认并简短确认即可。 +用户未提输入用法时:按体验选「大纲扩写」或「扮演停笔」写入产物并简短确认;两者都像才追问二选一,不必当成大缺口。 + +缺遣词/笔墨/禁忌/推进其中一件:在产物「追问」写 1~2 点(建议选项 + 短句示例)。四件够验收:`追问.题目` 为 `[]`。推进方式不明则正文写「无专门推进」,不问好感公式、进度表或事件池。 用户谈到变量增减、生成规则、舞台百科:只抽取能改遣词 / 禁忌 / 推进方式的一句,其余写入「开放问题」。 用户提到要换写法:收成写法档写入「情境备用」(官能 / 爽文 / 恐怖 / 情色这类),不追问具体场合怎么摆;没提则 `[]`。 +字数问「回复呈现」;本步不追问字数。 ``` ## output @@ -120,12 +138,14 @@ summary:`叙事指南与故事推进 · …` "推进与决策": { "有无专门推进": "有|无", "驱动力来源": "…", + "用户输入用法": "择一写入。大纲扩写:输入=待扩写为事实的大纲;细化后写正文;不超出大纲未涉及处,完整演绎。扮演停笔:用户本轮行为与对话作正文开头并扩写填满;不可写用户角色未给出的其它行为/对话;不可替用户角色做决定;停在其他角色等用户角色回应之刻。用户另定则改写", "叙事速度与详略": "…", "成败与难度": "…", "变量门控钩子": [] }, "内容与表达": { "视角执行": "…", + "段落形态": "默认:完整长自然段叙述,不要单句成段;用户另定则改写", "场景详略映射": ["…"] } }, @@ -157,6 +177,6 @@ summary:`叙事指南与故事推进 · …` ## examples ```examples -好:一次钉清遣词 + 笔墨落点 + 禁忌;推进写「等用户决策」或「无专门推进」;情境备用是「展示情色」「网文爽文」两档及切换时笔墨。 -坏:拆成「文风技能」和「推进技能」两步;追问好感公式 / 事件池;或把「当众折辱」「独处一室」当成情境备用。 +好:一次钉清遣词 + 笔墨落点 + 禁忌;推进写「等用户决策」或「无专门推进」;输入用法按体验钉「大纲扩写」或「扮演停笔」之一;情境备用是「展示情色」「网文爽文」两档及切换时笔墨。 +坏:拆成「文风技能」和「推进技能」两步;把两套输入用法混成半套;追问好感公式 / 事件池;或把「当众折辱」「独处一室」当成情境备用。 ``` diff --git a/skills/dialogue/world-simulator/modules/opening-setup/prompt.md b/skills/dialogue/world-simulator/modules/opening-setup/prompt.md index 7a3c434..2c22993 100644 --- a/skills/dialogue/world-simulator/modules/opening-setup/prompt.md +++ b/skills/dialogue/world-simulator/modules/opening-setup/prompt.md @@ -12,19 +12,18 @@ name: 开场白与开场变量 id: opening-setup artifact: 设计.开场白与开场变量 declaration: > - 创作终节点:写出 1~多条遵循正文组成/叙事/监控栏契约的开场白,并钉与之同真相的开场变量初值; - 选定后程序落库、结束创作并保存定稿 + 创作终节点:写出 1~多条开场白并钉同真相初值;选定后落库、结束创作并保存定稿 when: | - 体验、舞台、叙事、变量(若有)、正文组成、细化终稿等已大致可引用, - 需要可开玩的第一段剧情与初始真值快照时;排在收成链之后,作为最后一步。 + 收成链已齐(至少体验契约可引用,且「细化终稿」已产出或可立即收成运行规格),需要可开玩的第一段剧情与同真相初值。 + 排在收成之后作最后一步。用户要进游玩但还没有第一屏 → 排。 when_not: | - 体验/呈现仍混沌 → 先美学与正文组成等。 - 只要改文风不要开场 → 叙事指南。 - 只要改真值规则不要开场文 → 变量设计。 - 尚未细化终稿、Worker 集未齐 → 先收成。 + 体验/呈现仍混沌 → 先「美学纲领与交互范式」与「回复呈现」「正文组成」等。 + 只要改文风不要开场 → 「叙事指南与故事推进」。 + 只要改真值规则不要开场文 → 「变量设计与更新规则」。 + 运行规格未齐 → 先「细化终稿」。尚未选定开场前若要补前序节点(如 NPC)→ 插在本步之前,勿以「收口已排入」拒绝追加。 boundary: | - 本技能是创作终节点:1~多条开场正文(按正文组成块序)+ 开场变量初值 + 可选监控栏初值示意。 - 必须遵守已验收的叙事指南、正文组成、监控栏、变量设计;不重做这些契约。 + 本技能是创作终节点:1~多条开场正文(按回复呈现清单 + 正文组成展示)+ 开场变量初值。 + 必须遵守已验收的叙事指南、回复呈现、正文组成、变量设计;不重做这些契约。 具体实例:开场可引用已有实例名片,不在本步新造百科。 选定后由程序写入 输出.开场白 / 运行.初始变量 / 变量.当前,关闭 DAG 并保存定稿;不要在本步之后再排其它能力。 feeds: narrator diff --git a/skills/dialogue/world-simulator/modules/random-range/prompt.md b/skills/dialogue/world-simulator/modules/random-range/prompt.md new file mode 100644 index 0000000..b09122e --- /dev/null +++ b/skills/dialogue/world-simulator/modules/random-range/prompt.md @@ -0,0 +1,138 @@ +# 随机范围整理 + +> 技能文档。程序只切割下方 **fence 块**;`##` 标题仅供人读。 +> 产物外壳:`docs/context-fragment-design.md`。 +> 本步把上游已定的检定/对抗/掷骰需求,收成一份**程序可插入的随机值范围表**;不发明新裁定法则。 +> 游玩期:程序按本表每轮往消息里塞备用随机数(前端折叠隐藏、用户看不见,发给 AI 时仍在上下文);主世界层直接用表中本次数,不再单独「机遇裁定」槽。 + +## meta + +```meta +name: 随机范围整理 +id: random-range +artifact: 设计.随机范围整理 +declaration: > + 上游已有检定/对抗/掷骰需求时:汇总全部要用的随机项与取值范围(含表达式),供程序每轮插入备用随机数;排在正文组成之前 +when: | + 机制/生成规则/变量/叙事等上游已出现需要随机数的内容(对抗、检定、抽签、伤害区间等),且尚未收成一份范围表。 + 排在「正文组成」之前(通常紧挨其前;回复呈现可并行或略前)。 +when_not: | + 全程不靠随机数推进 → 不排。 + 还在定「怎么裁定 / 公式本身」→ 先「实现机制」「生成规则」或「变量设计与更新规则」;本步只汇总已定需求。 + 只谈前端怎么藏、选壳美化 → 「正文组成」。 + 只谈每轮可见区域与字数 → 「回复呈现」。 +boundary: | + 本技能:一份清单——每项随机用途、范围或表达式(如力量*5~*10、敏捷检定 1~100)、本轮建议备用条数。 + 不写新裁定法则、不写骰子剧情;法则来自上游,此处只整理成程序可读范围。 + 游玩拓扑:不再开「机遇裁定」槽;真随机靠本表 + 程序插入上下文。 + 正文组成:负责把隐藏备用区接到壳/消息里——本步只交「要插什么数」。 +feeds: gm,narrator +``` + +## opening + +```opening +把本局所有要用的随机数收成一张表(想到什么写什么): + +1. 上游里哪些地方要掷 / 检定 / 抽区间?(对抗、伤害、事件抽签……) +2. 每一项的取值范围或表达式?(例:敏捷检定 1~100;攻击伤害=力量×5~×10) +3. 每轮消息大概要预先塞几条备用?(够用即可,不要灌爆) +``` + +## task + +```task +你正在执行「随机范围整理」。产物必须是 **context-fragment.v1** JSON,写入「设计.随机范围整理」。 + +本步只做一件事:把上游已定、游玩时会用到的随机需求,整理成程序可插入的范围表。 +禁止重议「要不要检定」「公式对不对」——缺则追问上游或写进开放问题;本步不发明新法则。 + +执行顺序: +1. 扫机制 / 生成规则 / 变量 / 叙事 / 美学:列出所有「需要随机数才能裁定」的点。 +2. 每项写清:用途短名、范围或表达式(相对变量/表字段时写清引用)、单位(整数 d100 / 闭区间等)。 +3. 钉本轮建议备用条数(按项或全局);够本轮最坏情况即可。 +4. 无随机需求则本步不应被排;若误进:正文写空清单并说明「无需随机」。 +5. 自评 + 追问;输出 JSON。 + +summary:`随机范围整理 · {项数或主要用途}`。 +``` + +## principles + +```principles +1. 只汇总,不定新法。范围与表达式必须能追溯到上游已验收产物。 +2. 表达式写给人与程序都能读:`力量*5~*10`、`1~100`、`池权重抽 1`——忌散文。 +3. 一项一类用途;不要把「战斗」糊成一条却含三种掷法。 +4. 备用条数服务「本轮上下文预插入」;宁少可补,勿一次塞上百。 +5. 不输出机遇裁定槽、不写 chance tool 调用说明。 +``` + +## probe + +```probe +每轮 1~2 点:某项范围是否仍是散文;表达式引用的变量/表是否未在上游出现;有无漏掉已声明的检定。 +不追问:壳怎么藏、CSS、文风、要不要主世界层。 +全程明显无随机:确认不排即可,不必硬凑表。 +``` + +## output + +```output +{ + "schema": "context-fragment.v1", + "技能": "随机范围整理", + "brief": "一句话:收了哪些随机项", + "mount": ["world-simulator", "narrator"], + "稳变": "stable", + "正文": { + "依据": ["上游机制/生成规则/变量/叙事中与随机相关的要点"], + "插入意图": "程序按本表每轮往消息隐藏区插入备用随机数;裁决时只用上下文已有数,不另开机遇槽", + "项": [ + { + "id": "agility-check", + "用途": "敏捷检定", + "范围": "1~100", + "表达式": null, + "来源": "实现机制·… / 变量·…", + "每轮备用条数": 3 + }, + { + "id": "attack-damage", + "用途": "攻击伤害", + "范围": null, + "表达式": "力量*5~*10", + "来源": "变量设计·力量 / 机制·对抗", + "每轮备用条数": 2 + } + ], + "全局备用上限": "可选;防止灌爆上下文的软上限" + }, + "自评": { + "维度": [ + { "名": "覆盖", "分数": 8, "说明": "上游随机点是否收齐" }, + { "名": "可执行", "分数": 8, "说明": "范围/表达式是否可直接插数" } + ], + "薄弱点": "" + }, + "追问": { "导语": "", "题目": [] }, + "开放问题": [] +} +``` + +硬规则:合法 JSON;`项` 可 `[]`(仅当误排且确认无随机);有项则每项须有用途 +(范围或表达式至少一者);禁止 order;summary 见 task。 + +## checklist + +```checklist +- [ ] 每项都能对上上游,没有本步新发明的裁定? +- [ ] 范围/表达式短且可插数? +- [ ] 未要求机遇裁定槽或 chance tool? +- [ ] 排在正文组成之前的意图是否写进 brief/插入意图? +``` + +## examples + +```examples +好:两项——敏捷 1~100(备用 3);攻击伤害 力量*5~*10(备用 2);插入意图写清隐藏备用区。 +坏:在本步新写一套战斗规则;或只写「战斗要掷骰」无范围;或指引去开 play_slots.chance。 +``` diff --git a/skills/dialogue/world-simulator/modules/refine/prompt.md b/skills/dialogue/world-simulator/modules/refine/prompt.md index 41cfaf3..fb1573a 100644 --- a/skills/dialogue/world-simulator/modules/refine/prompt.md +++ b/skills/dialogue/world-simulator/modules/refine/prompt.md @@ -11,16 +11,15 @@ name: 细化终稿 id: refine artifact: 设计.worker集 declaration: > - 按已勾选固定槽与「上下文投影排序」表收成可进游玩的规格: - play_slots、投影插入序、常驻上下文、表与副作用;不发明新执行单元 + 按已勾选槽(或默认槽)与投影排序表收成运行规格;不发明新执行单元 when: | - 前面技能已大致谈清(至少有体验契约;槽已勾选或可按默认; - 若已有多块上下文则宜先有投影排序表),需要输出「设计.worker集」JSON 时; - 编排应将流程 status 导向 closed。 + 至少体验契约可引用;槽已勾选或可按默认;若上下文块已多则宜先有投影排序表。 + 需要输出「设计.worker集」才能进游玩时排;编排应将流程导向 closed。 when_not: | - 体验站位未定 → 先上游。 - 拓扑未勾选且用户拒绝默认槽 → 先「游玩拓扑」。 + 体验站位未定 → 先「美学纲领与交互范式」。 + 不能吃默认槽且尚未勾选 → 先「游玩拓扑」。 上下文块已多且稳/变未排序 → 先「上下文投影排序」。 + 只要改某一块设定长文 → 回头修改对应上游节点,不要用本步重写。 boundary: | 本能力:合并上游 → 完整运行规格 JSON(interaction、play_slots、context_order/inserts、 workers 由槽展开、resident_context、tables)。 diff --git a/skills/dialogue/world-simulator/modules/reply-format/prompt.md b/skills/dialogue/world-simulator/modules/reply-format/prompt.md index e2b3848..3fe6b58 100644 --- a/skills/dialogue/world-simulator/modules/reply-format/prompt.md +++ b/skills/dialogue/world-simulator/modules/reply-format/prompt.md @@ -1,7 +1,7 @@ # 正文组成 > 技能文档。程序只切割下方 **fence 块**;`##` 标题仅供人读。 -> **创作定位:基于固定呈现壳做适配微调**(`docs/play-presentation-shells.md`)。 +> **创作定位:把「回复呈现」已钉的内容展示给用户**(选壳、美化排版,可写 CSS/HTML/JS)。壳介绍与规格写在各壳自己的文档,程序动态装载。 > 产物外壳:`docs/context-fragment-design.md`。 > 旧称:设计回复格式。 @@ -12,41 +12,33 @@ name: 正文组成 id: reply-format artifact: 设计.正文组成 declaration: > - 基于七种固定呈现壳做适配微调(选 shell_id + 填字段/显示名/开关等); - 产出壳适配单;禁止从零发明布局或完整 UI + 把「回复呈现」已钉的内容展示给用户:选壳、美化排版,可写 CSS/HTML/JS;有「随机范围整理」则把隐藏备用随机区接到消息;排在二者之后、开场白之前 when: | - 需要为本局选定呈现壳,或微调监控字段/块显示名/建议行动开关时; - 或需要约定隐藏变量段时。 + 已有「回复呈现」(或等价:每轮终稿看什么已钉)后排。几乎每局都要。 + 若本局有随机需求:须已有「随机范围整理」(或确认无随机)后再排本步。 + 必须在「开场白与开场变量」之前。 when_not: | - 明确只要纯散文 → 可不排(运行时默认 prose)。 - 只谈文风 → 「叙事指南与故事推进」。 - 壳已定、只筛监控字段明细 → 「设计监控栏」。 - 不要在本步设计新布局或写 CSS。 + 还不知道每轮给用户看什么 → 先「回复呈现」。 + 已定要检定/掷骰但范围表未收 → 先「随机范围整理」。 + 不要排在开场白之后。几乎不跳过。 + 只谈文风遣词 → 「叙事指南与故事推进」。只改呈现区域与内容规则(字数/选项槽/监控键)→ 「回复呈现」。 boundary: | - 本技能:壳适配单(shell_id + 微调轴 + 块挂到壳已有区域)。 - 布局骨架只读:docs/play-presentation-shells.md。 - 设计监控栏:字段表细则。叙事指南:文风。变量设计:真值规则。 + 本技能:前端展示——从【可选呈现壳】选壳、把回复呈现的各区域落到版式、美化排版(可含 CSS/HTML/JS);若有随机范围表,预留/接到隐藏备用随机区(用户看不见、发给 AI 仍在上下文)。 + 回复呈现:必选/可选区域 + 各区简单内容规则——本步不重议清单与规则,只负责怎么显示。 + 随机范围整理:要插哪些数、范围是什么——本步不改范围表,只负责怎么藏进消息。 + 叙事指南:文风。变量设计:真值规则。开场白:第一屏——本步先定展示。 feeds: narrator ``` ## opening ```opening -本局在固定呈现壳上做适配(不是设计新界面)。 +本局把「回复呈现」里已钉的内容展示给用户(选壳、美化排版)。壳清单由程序动态装载,不要背死几种。 -0. 按「要同时看见什么」七选一: - · prose — 只要正文 - · chat_monitor — 正文 + 扫状态 - · spotlight — 大正文 + 弱状态 - · turn_panel — 场面 + 交互物 + 行动 - · split_board — 正文 ‖ 线索 - · choice_dock — 局面 + 选项 - · chapter_reader — 章正文 + 进度 - -1. 要微调什么?(监控字段、块称呼、要不要建议行动、tone_chrome…) -2. 有没有隐藏段给模型/程序维护变量? -3. 定稿时会用前面情节架空一幕灌进壳里,专供你看版式/美化(内容随便,不当正史)。 -4. 不要谈「再发明一种全新布局」。 +1. 对照【可选呈现壳】:哪一个最适合放下已钉的那些东西? +2. 各项落到壳的哪一区?显示名叫什么? +3. 要不要额外的 CSS/HTML/JS 来美化(没有就说没有)? +4. 定稿时会用前面情节架空一幕灌进壳里,专供你看版式/美化(内容随便,不当正史)。 ``` ## task @@ -54,18 +46,17 @@ feeds: narrator ```task 你正在执行「正文组成」。产物必须是 **context-fragment.v1** JSON,写入「设计.正文组成」。 -本步 = **壳适配单**:七种壳里选一个,只改允许的微调轴。 -权威:`docs/play-presentation-shells.md`。 -禁止从零设计分区、禁止自造 shell_id、禁止完整 CSS。 +本步 = **前端展示**:按「回复呈现」的清单,从【可选呈现壳】里选一个,把内容落到区域并美化排版。可写本局需要的 CSS/HTML/JS。 +禁止重议「看什么、正文多少字」;禁止自造目录没有的 shell_id。 执行顺序: -1. 读美学/叙事:继承人称与终稿归属;不重开文风问卷。 -2. **选 shell_id**;说明为何是这个壳而不是其它壳(主面积给谁)。 -3. 可见块:只挂到该壳已有区域;写显示名与职责(适配文案,不是新分区)。 -4. 监控栏:字段意图(细则可交「设计监控栏」);无 monitor 的壳写「不启用」。 -5. 隐藏段(若有):定界与用途。 -6. 填「呈现壳.微调」;前端拆分区域必须与壳一致。 -7. **示例**:用前面已定情节架空一幕,按本步壳与可见块灌进 `present.v1` 形状,专供验收版式/美化;示例文可短,游玩正文字数不在本步打磨。 +1. 读「回复呈现」与美学/叙事:清单是权威;不重开「看什么」问卷。 +2. **选 shell_id**(必须是【可选呈现壳】里的 id);说明为何这个壳放得下清单里的项。 +3. 可见块:把清单各项挂到该壳已有区域;写显示名与职责。 +4. 需要时写「渲染」:本局 CSS/HTML/JS 片段(美化排版,不是新后端协议)。 +5. 隐藏段(若清单要求):定界与用途。 +6. 填「呈现壳.微调」;分区必须与壳一致。 +7. **示例**:用前面已定情节架空一幕灌进 `present.v1`,专供验收版式/美化;字数以回复呈现为准,本步不重钉篇幅。 8. 自评 + 追问;禁止写 context `order`。 summary:`正文组成 · 适配 {shell_id} · …`。 @@ -74,21 +65,20 @@ summary:`正文组成 · 适配 {shell_id} · …`。 ## principles ```principles -1. 创作 = 选壳 + 适配微调 - 不是 UI 创意;布局骨架只读。本步验收重点是「看起来对不对」,不是故事写得好不好。 - 「按意见修改」:以最新产物为底;用户要求按先后都有效,冲突时以较新的为准。用户说整体可以、或只提美化/行距/显示名 → 不换 shell_id。换壳必须用户点名。 +1. 创作 = 把「回复呈现」的清单展示出来 + 选壳、分区、显示名、CSS/HTML/JS 都为那份清单服务。本步验收重点是「看起来对不对」。 + 「按意见修改」:以最新产物为底;用户要求按先后都有效,冲突时以较新的为准。用户说整体可以、或只提美化 → 不换 shell_id。换壳必须用户点名。 -2. 只改微调轴 - 字段、显示名、开关、tone_chrome、空态;不改分区、不增区域、不自造壳。 +2. 清单权威在「回复呈现」 + 正文篇幅、要不要日期、展示哪些变量,以那份产物为准。本步只决定怎么显示。 -3. 监控栏 ≠ 名片卡 - 只盯会变、影响决策或沉浸的信息。 +3. 壳是底,渲染可加 + 从【可选呈现壳】选底。需要时写本局 CSS/HTML/JS 做美化;不要发明新的后端协议或目录没有的壳。 4. 隐藏段服务维护,不污染阅读 5. 与转述、变量分工 - 文风归叙事指南;真值归变量设计;本步只交壳适配契约。 - 游玩单轮用户主读正文默认 500~2000 字,写进「拼装与终稿.单轮正文篇幅」,供转述遵守。 + 文风归叙事指南;真值归变量设计;看什么归回复呈现;本步只交展示契约。 6. 示例 = 壳与美化预览,非正史 用已定材料随便架空一幕,把各区域/监控/行动坞撑满,让用户看见版式。 @@ -100,8 +90,8 @@ summary:`正文组成 · 适配 {shell_id} · …`。 ```probe 每轮 1~2 点。 -优先:选哪个壳;微调哪些字段/显示名;隐藏段要不要;示例灌数是否让版式看得清。 -不追问:新布局、完整 CSS、事件池 schema、文风遣词、示例文笔好坏。 +优先:壳能否放下回复呈现的各项;分区与显示名;要不要 CSS/HTML/JS。 +不追问:重议字数/变量清单、事件池 schema、文风遣词、示例文笔好坏。 ``` ## output @@ -115,10 +105,10 @@ summary:`正文组成 · 适配 {shell_id} · …`。 "稳变": "stable", "正文": { "依据的体验与呈现": [ - "从美学/叙事继承的呈现要点" + "从回复呈现继承的清单 + 美学/叙事呈现要点" ], "呈现壳": { - "shell_id": "prose|chat_monitor|spotlight|turn_panel|split_board|choice_dock|chapter_reader", + "shell_id": "必须与【可选呈现壳】某一 id 一致", "为何选它": "一句话", "微调": { "tone_chrome": "messenger|terminal|book|default", @@ -136,20 +126,18 @@ summary:`正文组成 · 适配 {shell_id} · …`。 "职责": "这块给用户什么信息", "顺序": 1, "可空": true, - "填充方": "叙事转述|程序拼装|监控栏|其它", + "填充方": "叙事转述|程序拼装|回复呈现变量|其它", "内容形态": "散文|短列表|键值行|其它", "示例": "可选:该块一句占位(总预览见正文.示例)" } ], - "监控栏锚点": { - "本局是否启用": "是|否", - "在可见块中的块id": "若启用则指向可见块之一", - "职责摘要": "盯哪些类信息", - "字段草稿": [ + "呈现清单落实": { + "依据的回复呈现": "brief 或要点", + "各项落到": [ { - "名": "会变且值得盯的字段", - "为何监控": "决策/沉浸理由", - "来源意图": "真值|投影|临场生成" + "清单项": "正文|日期|某变量|建议行动|…", + "区域": "monitor|header|body|footer|aside|hidden", + "显示名": "可空" } ] }, @@ -171,16 +159,21 @@ summary:`正文组成 · 适配 {shell_id} · …`。 "区域id": "monitor|header|body|footer|aside", "对应块id": ["…"], "意图": "固定顶栏|主滚动|折叠文末|…", - "渲染提示": "纯文本|Markdown;勿写完整工程" + "渲染提示": "纯文本|Markdown|自定义" } ], + "渲染": { + "html": "可选:本局结构片段;无则空字符串", + "css": "可选:本局样式;无则空字符串", + "js": "可选:本局交互;无则空字符串" + }, "说明": "无分区则写「单流渲染」(通常 prose)" }, "拼装与终稿": { "终稿tag": "通常 输出.用户展示", "拼装方": "叙事转述一次写出各块|程序按块拼接|混合", "推荐灌数": "分块壳优先 present.v1;prose 可为纯 Markdown", - "单轮正文篇幅": "默认 500~2000 字(汉字,写入 body);短于 500 仅当用户明确要求极短", + "单轮正文篇幅": "以回复呈现的字数为准,本步不重钉", "与裁决包关系": "转述读 settlement 再填各块;隐藏段可含 variable_changes 镜像" }, "示例": { @@ -211,14 +204,14 @@ summary:`正文组成 · 适配 {shell_id} · …`。 "说明": "用户该看见的块是否齐、顺序是否服务体验" }, { - "名": "监控克制", + "名": "清单落实", "分数": 8, - "说明": "监控栏是否只盯会变信息(若无监控栏可 N/A)" + "说明": "回复呈现的各项是否都落到壳区域" }, { "名": "可实现", "分数": 8, - "说明": "shell_id 是否在七种壳内;分区与隐藏段是否可交给转述/程序" + "说明": "shell_id 是否在【可选呈现壳】内;分区与隐藏段是否可交给转述/程序" }, { "名": "版式可感", @@ -244,22 +237,22 @@ summary:`正文组成 · 适配 {shell_id} · …`。 硬规则: 1. 合法 JSON;含公共三段外壳。 -2. 正文须含 `呈现壳.shell_id`(七种之一)与 `微调`;可见块只挂壳已有区域。 -3. `可见块` 至少 1 条(通常含 body);禁止自造区域 id / 第五种壳。 +2. 正文须含 `呈现壳.shell_id`(须在【可选呈现壳】内)与 `微调`;可见块只挂壳已有区域。 +3. `可见块` 至少 1 条(通常含 body);禁止自造区域 id / 目录没有的壳。 4. 正文须含 `示例`:`性质` 标明非正史;`灌数` 为 `present.v1`,`shell` 与本步 shell_id 一致;只填该壳已有区域。 5. 示例内容可糙:只为验收壳与美化;禁止当开场白/正史;禁止为示例新造设定。 -6. 禁止程序 API schema、context `order`、完整 CSS。 -7. 自评:可见完备 / 监控克制 / 可实现 / 版式可感。 +6. 禁止程序 API schema、context `order`。需要美化时写本局 CSS/HTML/JS,不要另起后端协议。 +7. 自评:可见完备 / 清单落实 / 可实现 / 版式可感。 8. summary:`正文组成 · 适配 {shell_id} · {brief 缩略}`。 9. 兼容旧称产物 tag「设计.回复格式」。 ## checklist ```checklist -- [ ] 是「选壳+微调」,不是从零设计布局? -- [ ] shell_id 在七种壳内?可见块未超出该壳分区? -- [ ] 微调轴已填或明确默认?监控栏未塞死名片字段? -- [ ] 隐藏段(若有)定界清楚?未写 CSS 工程? +- [ ] 是把「回复呈现」的清单展示出来,而不是重议看什么? +- [ ] shell_id 在【可选呈现壳】内?可见块未超出该壳分区? +- [ ] 清单各项已落到区域?字数未在本步另定一套? +- [ ] 隐藏段(若有)定界清楚?CSS/HTML/JS 只服务本局展示? - [ ] 有示例灌数(present.v1),壳一致、各区撑开,且标明非正史? - [ ] 未把示例写成开场白或打磨成长文? ``` @@ -268,14 +261,13 @@ summary:`正文组成 · 适配 {shell_id} · …`。 ```examples 好: -- 适配 chat_monitor:微调监控字段=好感/今日话题;body 显示名=「短信」;示例灌数把气泡区+监控撑开,文笔随便。 -- 适配 chapter_reader:只开 header+body;aside 关;示例给短章头+一段 body。 -- 适配 turn_panel:开 suggested_actions;监控只盯体力/好感;示例 meta 带 2~3 个占位行动。 +- 回复呈现要正文+好感:选 chat_monitor,好感进 monitor,正文进 body;可加短 CSS 美化芯片。 +- 回复呈现只要正文:选 prose;渲染可空。 +- 回复呈现要选项:选 choice_dock,示例 meta 带占位行动。 坏: -- 「我们自定义一种左右分栏新界面」。 +- 本步重钉「正文 300 字」而回复呈现已经写了 800~1500。 - 不写 shell_id,只写「要好看的 UI」。 -- 监控栏列出姓名、性别等死设定。 - 示例写成第一章正史,或为写好看新造未定设定。 - 示例 shell 与呈现壳不一致,或灌了壳没有的区域。 ``` diff --git a/skills/dialogue/world-simulator/modules/status-bar/prompt.md b/skills/dialogue/world-simulator/modules/status-bar/prompt.md index 6d1ab5b..06b64e4 100644 --- a/skills/dialogue/world-simulator/modules/status-bar/prompt.md +++ b/skills/dialogue/world-simulator/modules/status-bar/prompt.md @@ -1,89 +1,92 @@ -# 设计监控栏 +# 回复呈现 > 技能文档。程序只切割下方 **fence 块**;`##` 标题仅供人读。 -> 产物外壳:`docs/context-fragment-design.md`;字段筛选气质对齐「生成规则」属性妥当。 -> 旧称:设计状态栏。更名因:这里盯的是**会变、要监控的信息**,不是名片式「状态展览」。 +> 产物外壳:`docs/context-fragment-design.md`。 +> 旧称:设计监控栏 / 设计状态栏。 +> 本步钉:**每轮终稿有哪些区域(必选/可选)**,以及各区域的**简单内容规则**;不排版、不选壳。 ## meta ```meta -name: 设计监控栏 +name: 回复呈现 id: status-bar artifact: 设计.监控栏 declaration: > - 钉用户可见监控栏字段:只留会变、影响决策或沉浸的信息 - (主角状态/攻略目标/场景可交互对象等);不进姓名性别等死字段 + 几乎每局都要:钉每轮终稿的必选/可选区域,以及各区域的简单内容规则(字数、段落、选项怎么组成等);不排版 when: | - 「正文组成」已启用监控栏,或体验需要持续可见的监控信息时; - 需要逐字段筛「该不该监控」时。 + 舞台/世界/变量等上游大致齐后排。几乎每局都要。 + 排在「正文组成」之前:先钉有什么区域、各区怎么写,再交给正文组成去展示。 when_not: | - 明确不要 HUD/监控条 → 不排。 - 版式块序未定、连有没有监控栏都不清 → 先「正文组成」。 - 真值如何增减 → 「变量设计与更新规则」(本步只选展示哪些)。 -boundary: | - 本技能:监控栏字段清单、来源意图、刷新与可见条件;产出 context-fragment.v1。 - 正文组成:监控栏在整轮版式中的位置——本步不重排其它块。 - 变量设计:真值与 side_effects——本步可引用字段名,不写更新公式。 - 生成规则:内容表 schema——监控栏不是生成实例表,但同样忌冗余字段。 + 上游还没齐 → 先那些。 + 只谈怎么排版、选壳、CSS/HTML/JS → 「正文组成」。 + 只谈文风遣词 → 「叙事指南与故事推进」。 + 检定/掷骰范围汇总 → 「随机范围整理」。 + 变量如何增减 → 「变量设计与更新规则」(本步只定展示哪些、展示规则)。 +boundary: > + 本技能:区域清单(必选/可选)+ 各区域简单内容规则(字数、自然段、选项槽位与提示口径等)。 + 正文组成:如何把这些区域展示给用户(壳、美化、CSS/HTML/JS)——本步不定版式。 + 随机范围整理:隐藏备用随机数表——本步不收范围。 + 变量设计:真值与更新——本步可点名要展示的键与监控规则,不写增减公式。 feeds: narrator ``` ## opening ```opening -这一局监控栏要让用户盯住什么?(想到什么写什么) +每轮最终回复要分哪些区域?(想到什么写什么) -1. 监控对象是谁/哪一层? - 例:主角生存资源;攻略目标态度;当前场景可交互对象;任务进度…… - -2. 哪些数字或短状态会变、且变了会影响你下一步? - 不要列几乎不变的名片(姓名、性别等——绝大多数局都不需要)。 - -3. 刷新节奏?每轮都刷,还是事件后才变? +1. 必选:正文——字数、段落形态?未提及时默认:约 1000~2000 字;完整长自然段,不要单句成段。 +2. 要不要状态/变量监控(如开头日期、好感)?盯哪些键? +3. 要不要选项栏?若要:几个槽、各自什么气质(如 A 冒险 / B 稳重),生成选项时遵守什么提示? +4. 要不要可选块:小故事旁支、线索条等?没有就说没有。 ``` ## task ```task -你正在执行「设计监控栏」。产物必须是 **context-fragment.v1** JSON,写入「设计.监控栏」。 +你正在执行「回复呈现」。产物必须是 **context-fragment.v1** JSON,写入「设计.监控栏」。 -监控栏 = 用户可见的**监控**区:只放有用、会变的信息。 -可含:主角资源/状态、攻略目标状态、当前场景可交互对象等——按体验需要选,不默认堆满。 +本步做两件事: +1. **区域**:每轮终稿有哪些块——哪些必选、哪些可选。 +2. **简单规则**:每个启用区域怎么生成/填写(字数、自然段、选项槽与提示口径、监控键等)。 + +不选壳、不写 CSS/HTML/JS、不排版。展示交给「正文组成」。 + +默认必选:`正文`。用户未点名正文规格时,采用默认规则: +- 字数约 **1000~2000**; +- **完整长自然段叙述,不要单句成段**。 +用户另有要求则以用户为准。 + +常见可选:`状态监控`(日期、变量芯片等)、`选项栏`、`小故事`(旁支短文)等——按体验增减,不要堆满。 执行顺序: -1. 读正文组成(若有)与变量设计:继承栏位位置与已有真值名。 -2. 逐字段过筛(同生成规则「属性妥当」):对本局是否值得监控?不变的名片字段删除。 -3. 写清每字段:名、为何监控、来源意图、可见条件、展示形态(短文本/数值/列表)。 -4. 写刷新时机与空态(无目标/无交互物时显示什么)。 -5. 自评 + 追问;输出 JSON。 +1. 读美学/叙事/变量/舞台:继承体验与已有真值名。 +2. 钉必选区域:至少含正文;写清内容规则。未提及时用默认(1000~2000 字;长自然段、勿单句成段)。 +3. 逐个判定可选区域:要则写规则;不要则不进清单(可在「刻意不启用」说明)。 +4. 若开选项栏:钉槽位数、各槽气质/组成规则、生成时的短提示口径(供转述遵守)。 +5. 若开状态监控:点名键、形态、刷新意图;不写变量增减公式。 +6. 自评 + 追问;输出 JSON。 -summary:`设计监控栏 · …`(点题监控对象)。 +summary:`回复呈现 · …`(点题必选+主要可选)。 ``` ## principles ```principles -1. 监控 ≠ 角色卡 - 姓名、性别、种族等几乎不变内容默认排除(除非玩法就是改性别/改名且必须盯)。 - -2. 只留有用消息 - 能回答:变了以后用户会不会改决策或沉浸感?不能则删。 - -3. 对象可以多层 - 不限于「主角状态」:攻略目标、场景可交互列表、世界危机进度等都可进栏——但每层字段仍要克制。 - -4. 来源可追溯 - 字段应能指向真值、投影或临场短生成;禁止无来源的装饰假数。 - -5. 展示短 - 监控栏不是正文;长描写放叙事,栏内短标签/数字/一行列表。 +1. 区域 = 用户每轮会看见的内容槽;规则 = 槽里怎么写。两者都在本步钉死。 +2. 正文默认必选。其它区域默认可选:有体验需要才开。 +3. 规则要可执行、宜短:字数、自然段、选项槽气质、监控键名——够转述与正文组成接上即可。 + 正文规格用户未提及时:字数 1000~2000;完整长自然段,不要单句成段。 +4. 选项栏的「选项由什么组成 / 各槽提示词」在本步规定,不推到叙事指南或正文组成。 +5. 不问「长什么样」。壳、分区、CSS/HTML/JS 交给「正文组成」。 +6. 展示用的变量是子集;增减仍归变量设计。 ``` ## probe ```probe -每轮 1~2 点:缺哪类监控对象;某字段是否死字段该删;刷新过频还是过稀。 -不追问:整页 CSS、文风、完整变量更新公式。 +每轮 1~2 点:必选是否只剩正文;某可选区开了却没规则;选项槽气质是否空;正文段落/字数是否离谱。 +不追问:选哪个壳、CSS、文风遣词、变量更新公式。 ``` ## output @@ -91,62 +94,92 @@ summary:`设计监控栏 · …`(点题监控对象)。 ```output { "schema": "context-fragment.v1", - "技能": "设计监控栏", - "brief": "一句话:监控谁/什么", + "技能": "回复呈现", + "brief": "一句话:必选哪些区 + 开了哪些可选区", "mount": ["narrator"], "稳变": "stable", "正文": { - "依据": ["正文组成锚点 / 变量设计字段 / 体验需要"], - "监控对象": [ + "依据": ["美学/叙事/变量/舞台里与「每轮看见什么」相关的要点"], + "必选区域": [ { - "对象id": "pc|target|scene|world|…", - "名称": "主角|攻略目标|当前场景|…", - "为何出现在栏内": "…" + "id": "body", + "名称": "正文", + "规则": { + "字数": "默认 1000~2000;用户另定则从其", + "自然段": "完整长自然段叙述,不要单句成段", + "其它": "可选:人称、是否含对白密度等一句" + } } ], - "字段": [ + "可选区域": [ { - "名": "短名,用户可见", - "对象id": "归属上述对象", - "为何监控": "变了如何影响决策或沉浸", - "来源意图": "真值键名|投影tag|临场", - "类型示意": "number|string|short_list|enum", - "可见条件": "始终|某阶段|有目标时…", - "展示形态": "例:❤ 37;或一行「可交互:门、柜」", - "禁止原因若曾候选": "例:性别——不变,已剔除;无则空" + "id": "status", + "名称": "状态监控", + "启用": true, + "规则": { + "字段": [ + { + "名": "日期|好感|…", + "来源": "真值键|投影|临场", + "形态": "短文本|数字|枚举" + } + ], + "刷新": "每轮|事件后" + } + }, + { + "id": "choices", + "名称": "选项栏", + "启用": true, + "规则": { + "槽数": 2, + "槽": [ + { + "槽id": "A", + "气质": "冒险", + "组成": "推进风险/探索的行动一句", + "生成提示": "写给转述:本槽选项须偏冒险、短、可点" + }, + { + "槽id": "B", + "气质": "稳重", + "组成": "保守/观察/缓和的行动一句", + "生成提示": "写给转述:本槽选项须偏稳重、短、可点" + } + ] + } + }, + { + "id": "side_story", + "名称": "小故事", + "启用": false, + "规则": { + "字数": "无则空", + "与正文关系": "旁支;不抢主线" + } } ], - "刻意不监控": [ - "姓名、性别…及原因" - ], - "刷新": { - "时机": "每轮|事件后|变量边沿|手动", - "空态": "无数据时显示什么" - }, - "与版式关系": "在正文组成中的块位置;若尚无正文组成则写建议位置" + "刻意不启用": [ + "本局不开的区域及原因" + ] }, "自评": { "维度": [ { - "名": "属性妥当", + "名": "区域清楚", "分数": 8, - "说明": "逐字段:无死名片;该盯的生存/关系/场景信息未漏" + "说明": "必选/可选是否分明;下游能否直接按区展示与灌数" }, { - "名": "克制度", + "名": "规则可执行", "分数": 8, - "说明": "字段是否够少、展示是否够短" - }, - { - "名": "可接线", - "分数": 8, - "说明": "来源意图是否接得上变量/投影/正文组成" + "说明": "字数/段落/选项槽/监控键是否够转述遵守" } ], "薄弱点": "一句话" }, "追问": { - "导语": "为钉准监控栏,还需确认:", + "导语": "为钉准每轮区域与规则,还需确认:", "题目": [ { "问": "…", @@ -161,29 +194,31 @@ summary:`设计监控栏 · …`(点题监控对象)。 硬规则: 1. 合法 JSON;公共三段外壳。 -2. 正文键固定:依据、监控对象、字段、刻意不监控、刷新、与版式关系。 -3. 自评:属性妥当 / 克制度 / 可接线。 -4. 字段不得无故包含姓名/性别等死设定(列入「刻意不监控」并说明)。 -5. summary:`设计监控栏 · {brief 缩略}`。 -6. 兼容旧 artifact「设计.状态栏」。 +2. 正文须含:必选区域(至少正文)、可选区域、刻意不启用。 +3. 每个启用区域须有可执行的 `规则`;选项栏须含槽气质与生成提示。 +4. 禁止选壳、写 CSS/HTML/JS、发明前端分区。 +5. summary:`回复呈现 · {brief 缩略}`。 +6. 产物 tag 仍为「设计.监控栏」。 ## checklist ```checklist -- [ ] 字段均为会变且有用?死名片进了「刻意不监控」? -- [ ] 可含攻略目标/场景交互物等非主角对象? -- [ ] 来源意图清楚?未写成长文正文? +- [ ] 正文在必选区,且有字数/自然段等规则? +- [ ] 可选区逐项启用或刻意不启用? +- [ ] 选项栏若开:槽气质与生成提示已写? +- [ ] 状态监控若开:字段与来源已写? +- [ ] 未写排版或 CSS/HTML/JS? ``` ## examples ```examples 好: -- 末日:体力、口粮、威胁等级;刻意不监控姓名性别。 -- 恋爱:攻略目标好感/心情;场景可交互:公园长椅、便利店。 -- 字段 3~7 个,短展示。 +- 必选正文默认 1000~2000 字、长自然段勿单句成段;可选状态监控=日期+好感;选项栏 A 冒险 / B 稳重,各有生成提示。 +- 必选正文;不开选项、不开小故事;状态只盯体力。用户要求极短时字数可低于默认。 坏: -- 监控栏 = 完整人物卡(名/性/龄/身高/籍贯…)。 -- 把叙事指南整段塞进栏内。 +- 只写「要选项」却不定 A/B 气质与生成提示。 +- 正文无字数/段落规则。 +- 在本步选壳或写 CSS。 ``` diff --git a/skills/dialogue/world-simulator/modules/topology/prompt.md b/skills/dialogue/world-simulator/modules/topology/prompt.md index 638da73..5539543 100644 --- a/skills/dialogue/world-simulator/modules/topology/prompt.md +++ b/skills/dialogue/world-simulator/modules/topology/prompt.md @@ -1,6 +1,8 @@ # 拓扑图谱 -> **状态:待完善** — 块格式见 `docs/world-simulator-modules.md`;范例见 `aesthetics-interaction`。 +> 技能文档。程序只切割下方 **fence 块**;`##` 标题仅供人读。 +> 产物外壳:`docs/context-fragment-design.md`。 +> 必须生成、但不适合走「生成规则→具体实例」时:用拓扑结构写出来。 ## meta @@ -8,52 +10,156 @@ name: 拓扑图谱 id: topology artifact: 设计.拓扑图谱 -declaration: 钉 worker/表/阶段的依赖、触发与数据流向;一张图说清谁读谁写 -when: 实现机制大致清楚,需要钉依赖边、触发边与数据流向时 -when_not: 尚未决定有哪些执行单元就先画复杂图 +declaration: > + 有些东西必须生成,但不需要或不适合走「生成规则→具体实例」时:用拓扑结构写出来(升级路径、地图、人物关系等) +when: | + 已有「美学纲领与交互范式」或等价整体感觉,且同时满足: + 这些东西必须生成;不需要或不适合走「生成规则→具体实例」;能用拓扑结构描述。 + 很泛:升级路径、地图、人物关系等等都可以。 +when_not: | + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 需要精准格式,或本局原创听了会雾且还要按规则生成 → 「生成规则」;已有规则再要名片 → 「具体实例」。 + 只是活动区域写细、没有拓扑可描述 → 「舞台骨架」。 + 跨轮真值 → 「变量设计与更新规则」。执行单元勾选 → 「游玩拓扑」。 + 没有必须生成的拓扑结构 → 不排。 boundary: | - 本能力:依赖/触发/读写流向。 - 游玩拓扑:固定槽勾选;本步若仍需要,只画已启用槽之间的数据流。 - 实现机制:总览「要哪些件」,本步钉件与件的边。 + 本技能:用拓扑结构写出必须存在、又不走生成规则合同的内容(节点、连接、方向/层级)。 + 生成规则 / 具体实例:复杂合同与 records——本步不写生成格式、不填名片表。 + 舞台骨架:活动区域写细——本步不重写舞台百科。 + 游玩拓扑:固定槽勾选——本步不描述执行单元谁读谁写。 + 变量*:跨轮状态——本步不设计变量表。 +feeds: gm ``` ## opening ```opening +先说要写哪块拓扑(想到什么写什么): + +1. 有什么必须生成、又不适合走「生成规则→具体实例」? +2. 它的拓扑是什么:升级路径、地图、人物关系,还是别的连接? + 例:家门→小区门→花园↑;谁连谁;功法从哪一阶接到哪一阶。 ``` ## task ```task -钉清拓扑:单元、依赖、触发、读写流向。写入 设计.拓扑图谱。 -(待作者细写) +你正在执行「拓扑图谱」。产物必须是 **context-fragment.v1** JSON,写入「设计.拓扑图谱」。 + +本步写出必须生成、但不需要或不适合走「生成规则→具体实例」的内容。用拓扑结构描述即可:升级路径、地图、人物关系等都很泛,能连起来就写。 + +执行顺序: +1. 认定本步写哪几块拓扑(名称 + 为何必须生成、为何不走生成规则)。 +2. 每块列出节点与连接(从哪到哪、什么关系、有无方向或层级)。 +3. 路径写清顺序或岔路;关系写清称谓或从属;升级写清阶与阶怎么接。点保持短名,不写成百科或名片表。 +4. 填齐正文 + 自评 + 追问,输出 JSON。 + +若程序已发默认问题:禁止重复开场;在首答上补洞。 +summary:`拓扑图谱 · {名称或类型}`。 ``` ## principles ```principles -一张图说清;环依赖与隐式读写必须显式写出或拆掉。 +1. 先问:必须生成吗?走「生成规则→具体实例」是不是过重或不合适?能用拓扑结构描述吗?三问成立才写。 +2. 拓扑很泛:升级路径、地图、人物关系都是同一类产物,不要只当成探索地图。 +3. 节点短、连接准。点不是名片,连接不是散文,也不是生成合同。 +4. 该用规则反复生成的对象族不要塞进本步。 ``` ## probe ```probe -(待作者细写) +每轮 1~2 点。已答清的禁止重问。 + +优先:为何不走生成规则;这块拓扑是路径、地图还是关系;缺了哪条连接会断。 +不追问:执行单元读写、生成格式与池、变量公式、舞台百科、具体名片字段。 ``` ## output ```output { - "节点": [{ "id": "…", "类型": "worker|表|阶段|…" }], - "边": [{ "from": "…", "to": "…", "关系": "依赖|触发|读写|…" }], - "说明": "…" + "schema": "context-fragment.v1", + "技能": "拓扑图谱", + "brief": "一句话:写了哪几块拓扑", + "mount": ["world-simulator"], + "稳变": "stable", + "正文": { + "拓扑": [ + { + "名称": "升级路径 / 地图 / 人物关系 / …", + "类型": "路径|地图|关系|其它", + "用途": "为何必须生成、游玩里怎么用", + "节点": [ + { + "id": "英文或短码", + "名称": "家门 / 某阶 / 某人短名", + "是什么": "一句;不是名片" + } + ], + "连接": [ + { + "from": "节点 id", + "to": "节点 id", + "关系": "通往 / 下一阶 / 父女 / …", + "方向": "单向|双向", + "备注": "如 ↑ 上楼;无则空字符串" + } + ] + } + ] + }, + "自评": { + "维度": [ + { + "名": "时机合适", + "分数": 8, + "说明": "是否必须生成、且不该走生成规则→具体实例" + }, + { + "名": "结构清楚", + "分数": 8, + "说明": "拓扑是否写清、有无断连" + } + ], + "薄弱点": "一句话" + }, + "追问": { + "导语": "为钉准这块拓扑,还需确认:", + "题目": [ + { + "问": "…", + "建议选项": ["选项A", "选项B", "其它(请写明)"], + "示例": "可选" + } + ] + }, + "开放问题": [] } ``` +硬规则: +1. 合法 JSON;必含 `schema` / `技能` / `brief` / `正文` / `自评` / `追问`(题目可 `[]`)。 +2. 正文含 `拓扑` 数组;每块含名称、类型、节点、连接。 +3. `mount` 默认主世界层;**禁止**写 `order`。不写执行单元槽位、不交 records、不写生成 schema。 +4. summary:`拓扑图谱 · {brief 缩略}`。 + ## checklist ```checklist -- [ ] 每个关键读写是否有边? -- [ ] 是否与实现机制列表一致? +- [ ] 含 schema / brief / 正文 / 自评 / 追问? +- [ ] 每块拓扑有节点和连接?路径/地图/关系能认? +- [ ] 确是必须生成且不适合走生成规则→具体实例? +``` + +## examples + +```examples +好:家门→小区门→花园↑——地图拓扑,连接带方向。 +好:家族谁连谁——关系拓扑,连接是称谓。 +好:功法一阶接到二阶、旁支接到某秘术——升级路径。 +坏:其实该按规则反复生成的对象族(如心之彩)硬写成拓扑。 +坏:把舞台活动区再抄一遍,没有连接。 +坏:描述主世界层谁读谁写 → 游玩拓扑,不是本步。 ``` diff --git a/skills/dialogue/world-simulator/modules/variable-context/prompt.md b/skills/dialogue/world-simulator/modules/variable-context/prompt.md index ed8c5f5..3860437 100644 --- a/skills/dialogue/world-simulator/modules/variable-context/prompt.md +++ b/skills/dialogue/world-simulator/modules/variable-context/prompt.md @@ -10,19 +10,19 @@ name: 变量控制上下文 id: variable-context artifact: 设计.变量控制上下文 declaration: > - 钉真值/投影/Data 摘要如何挂进主世界层、叙事转述与旁观: - 可见性、措辞、未解锁不注入;汇总映射当前档供旁观 agent + 已有真值或映射时:钉谁看见什么(主世界层/转述/旁观)、未解锁不注入;无信息差则可不排 when: | - 变量设计已有真值或 Data 映射索引,需要规定谁看见什么、旁观看哪份摘要时。 + 变量设计已有真值或 Data 映射,且存在信息差:玩家不该看见但主世界层/旁观要知道,或到某档才允许提起,或旁观需要「当前档摘要」。 when_not: | - 尚无变量且无投影。 - 仅内部记账永不进提示词 → 可跳过,在变量设计备注即可。 - 只改字段与更新规则 → 变量设计与更新规则。 + 尚无变量且无投影 → 不排。 + 仅内部记账、永不进任何提示词 → 跳过,在变量设计备注即可。 + 只改字段与更新规则 → 「变量设计与更新规则」。 + 真值对所有槽同样可见、无剧透边界 → 可不排。 boundary: | 本技能:挂载表、剧透边界、旁观汇总视野、与维护语句/投影 tag 对齐。 变量设计:字段、映射索引、维护语句形状、side_effects。 具体实例:表行正文——本步不重生成,只声明「旁观读当前档/哪几个摘要键」。 - 设计监控栏 / 正文组成:用户可见层;本步管提示词视野。 + 回复呈现 / 正文组成:用户可见层(看什么 / 怎么展示);本步管提示词视野。 feeds: gm,auditor ``` diff --git a/skills/dialogue/world-simulator/modules/variable-design/prompt.md b/skills/dialogue/world-simulator/modules/variable-design/prompt.md index 22f0fe6..f4bb463 100644 --- a/skills/dialogue/world-simulator/modules/variable-design/prompt.md +++ b/skills/dialogue/world-simulator/modules/variable-design/prompt.md @@ -11,20 +11,20 @@ name: 变量设计与更新规则 id: variable-design artifact: 设计.变量设计与更新规则 declaration: > - 钉真值、谁可写、如何变;起草 side_effects;约定维护语句形状; - 汇总 Data 映射索引(分档/实例来自生成规则与具体实例)供投影与旁观 + 体验必须跨轮记住少数状态时:钉真值、谁可写、如何变、维护语句,以及按值换文案的映射索引 when: | - 体验需要可追踪状态,且下游要可靠查询、门控、防重复或按值换文案时。 + 体验需要跨轮记住少数状态,否则会糊:必须可查询、门控、防重复,或到某值换一套态度/文案/章纲。 + 用户点名要好感/资源/阶段数字、分档换性格、进度门控时排。 when_not: | - 无状态纯对话,或状态只临场描写、从不程序化。 - 只要大段设定不要门控 → 舞台骨架 / 生成规则。 - 只规定挂进谁的提示词 → 「变量控制上下文」。 - 只规定用户看见哪些监控字段 → 「设计监控栏」。 + 无状态纯对话,或状态只临场描写、从不程序化 → 不排。 + 只要大段设定不要门控 → 「舞台骨架」/「生成规则」。 + 只规定谁的提示词看见什么 → 「变量控制上下文」。 + 只规定每轮给用户看哪些(正文/字数/变量/日期)→ 「回复呈现」。 boundary: | 本技能:真值清单、更新规则、维护语句约定、Data 映射索引、side_effects 草案。 分档长文/性格切片正文:由生成规则定格式、具体实例填表;本步做索引与门控,不重写整表。 正文组成:隐藏段定界符——本步钉「维护语句写什么」;定界样式与之对齐。 - 机遇裁定 chance:真随机 toolcall,不是变量表维护手段。 + 随机范围整理:检定/掷骰取值范围汇总(程序插备用数)——不是变量表维护手段;本步不收随机表。 变量控制上下文:挂载对象与旁观汇总视野。 细化终稿:收成 tables.side_effects。 feeds: gm @@ -52,7 +52,7 @@ feeds: gm - **Progressive**:side_effects 按真值边沿投影当前切片;旁观/主世界层读投影或汇总,不整表常驻 **维护语句**:规定模型每轮如何声明变更(供程序拆进 `变量.当前` / 裁决包 `variable_changes`)。 -这不是 chance toolcall;toolcall 只做骰子/抽签。隐藏段定界与「正文组成」对齐。 +这不是掷骰;随机数走「随机范围整理」+ 程序插入的备用数。隐藏段定界与「正文组成」对齐。 执行顺序: 1. 读美学/机制/生成规则/具体实例/正文组成;不重开体验。 diff --git a/skills/dialogue/world-simulator/modules/worker-spec/prompt.md b/skills/dialogue/world-simulator/modules/worker-spec/prompt.md index 1b4f22b..d89402a 100644 --- a/skills/dialogue/world-simulator/modules/worker-spec/prompt.md +++ b/skills/dialogue/world-simulator/modules/worker-spec/prompt.md @@ -2,7 +2,8 @@ > 能力文档。程序只切割下方 **fence 块**;`##` 标题仅供人读。 > **禁止自由发明执行单元。** 只从固定槽勾选;程序按 `play_slots` 展开 workers。 -> 方法:`docs/progressive-data-design.md`;模板:`worker-templates/`。 +> 方法:`docs/progressive-data-design.md`;模板:`worker-templates/`。 +> 真随机:不靠「机遇裁定」槽;上游定法则 →「随机范围整理」收表 → 程序往消息隐藏区插备用数。 ## meta @@ -11,21 +12,22 @@ name: 游玩拓扑 id: worker-spec artifact: 设计.worker规格 declaration: > - 勾选固定游玩槽位(旁观维护 / 主世界层 / 叙事转述 / 可选角色视角 / 可选机遇裁定;写手路径为大纲+章节), - 禁止自由发明新的执行单元 ref + 不能吃默认槽时才勾选:主世界层必开;有变量/表维护才开旁观;转述默认开;强秘密才开视角;写手则大纲+章节;禁止发明执行单元与机遇槽 when: | - 体验契约已大致清楚,需要决定游玩期启用哪些固定槽时; - 或要修订已勾选槽位(开/关 auditor、perspective、chance 等)时。 + 体验契约已大致清楚,且不能吃默认槽:要关旁观、关转述、开角色视角(强秘密不能进主世界层),或走写手大纲+章节。 + 或要修订已勾选槽(开/关 auditor、perspective、narrator 等)。 when_not: | - 体验/站位仍混沌 → 先美学纲领与交互范式。 - 只需收成完整运行规格 → 交给细化终稿(本步只交槽位勾选)。 - 不要用本步「发明」世界观/性格/变量专用执行单元。 + 体验/站位仍混沌 → 先「美学纲领与交互范式」。 + 世界模拟可吃默认(主世界层+转述+旁观;视角关)→ 可不排,「细化终稿」按默认收成。 + 只需输出完整运行规格 → 「细化终稿」(本步只交槽位勾选)。 + 检定/掷骰范围汇总 → 「随机范围整理」;不要为本步加「机遇裁定」槽。 + 不要用本步发明世界观/性格/变量专用执行单元。 boundary: | 本能力:输出 play_slots(及写手路径的 writing_slots),可选覆盖挂载说明;不写完整 设计.worker集。 + 主世界层(gm)几乎总要。旁观维护:有变量/表/规则要程序化盯时才开。转述默认开。 + 不再设机遇裁定(chance)槽:真随机走「随机范围整理」+ 程序插入上下文备用数。 细化终稿:按本步勾选展开 workers、合并常驻与 tables。 变量设计 / 变量控制上下文:真值与投影,不是推理槽。 - 旁观维护(auditor):副 LLM,表/规则检查,默认空操作;无长对话史。 - 机遇裁定(chance):`play_slots.chance` 开时主世界层 harness 获批量程序工具;非每轮独立上场。 叙事指南与故事推进:挂到转述槽(推进可兼挂主世界层);世界/机制:挂到主世界层——本步只点名槽。 ``` @@ -35,15 +37,16 @@ boundary: | 游玩时用哪些固定槽?(只勾选,不要发明新角色名当「新系统」) 世界模拟类常见: -1. 旁观维护(表/规则检查,默认每轮上场但多数轮空操作)——要 / 不要(默认要) -2. 主世界层(裁决,几乎总要)——要 / 不要 -3. 叙事转述(写你看见的正文,几乎总要)——要 / 不要 +1. 主世界层(裁决)——要(几乎总要) +2. 叙事转述(写你看见的正文)——要 / 不要(默认要) +3. 旁观维护(有变量/表/规则要盯时才开;默认:有变量类上游则要)——要 / 不要 4. 角色视角(仅当有强秘密、不能进主世界层时)——要 / 不要(默认不要) -5. 机遇裁定(骰子/抽签/比点等真随机,按需调用、不进每轮)——要 / 不要(默认不要;有战斗检定、抽签事件时建议开) + +不要勾「机遇裁定」:检定/掷骰用「随机范围整理」收表,程序插备用随机数。 写手/扩写类常见:大纲/细纲 + 章节正文(固定两槽,同上只勾选)。 -变量、性格分档、世界观:不是槽,后面用变量/世界等技能收进上下文。 +变量、性格分档、世界观:不是槽,用变量/世界等技能收进上下文。 ``` ## task @@ -51,22 +54,23 @@ boundary: | ```task 你正在执行「游玩拓扑」。产物写入「设计.worker规格」。 -核心操作:让用户勾选固定槽,写成 `play_slots`(世界模拟)或 `writing_slots`(扩写)。**禁止**新建未在固定列表中的 ref。 +核心操作:让用户勾选固定槽,写成 `play_slots`(世界模拟)或 `writing_slots`(扩写)。**禁止**新建未在固定列表中的 ref;**禁止**再开机遇裁定槽。 固定 ref 白名单: - 世界模拟每轮:`world-simulator`(gm)、`narrator`、`auditor`(回合末)、`role-decide`(perspective,默认关) -- 世界模拟机遇:`play_slots.chance` 控制主世界层 harness 的批量 `chance` 工具(默认 false);非每轮独立 LLM 槽 - 扩写:`outline`、`chapter-writer` -- 禁止:`variable-update`、自造 kebab、为世界观/性格再拆槽 +- 禁止:`chance` / 机遇裁定、`variable-update`、自造 kebab、为世界观/性格再拆槽 执行顺序: 1. 读配方与体验契约,判断路径:世界模拟 vs 写手分段。 -2. 默认世界模拟:`auditor: true, gm: true, narrator: true, perspective: false, chance: false`; +2. 默认世界模拟:`gm: true, narrator: true, auditor: true, perspective: false`; 调度序 gm → perspective? → narrator → auditor; - 仅信息隔离才开 perspective;需要骰子/抽签/比点等真随机时设 `chance: true`(主世界层 harness 批量工具,不进每轮序)。 + 主世界层必开(用户明确只要旁观/写手路径除外); + 有变量设计/表维护需求 → auditor true;纯无状态对话可 auditor false; + 仅信息隔离才开 perspective。 3. 写手路径:`outline` + `chapter-writer` 默认都开;用户明确只要正文则可关 outline。 4. 可写简短 `mount_notes`(哪类上游产物挂哪槽),不粘贴长文。 -5. 输出 JSON。summary:`游玩拓扑 · 旁观+gm+转述` 或 `游玩拓扑 · gm+转述+机遇` 等。 +5. 输出 JSON。summary:`游玩拓扑 · gm+转述+旁观` 等(勿写机遇)。 若程序已发默认问题:禁止重复同一开场;在首答上补洞。 ``` @@ -74,12 +78,13 @@ boundary: | ## principles ```principles -1. 只勾选,不发明:ref 必须在白名单内。 -2. 默认:世界模拟 = 旁观维护 + 主世界层 + 转述;perspective 默认关。 -3. 变量 / Data / Progressive 不是执行单元;旁观维护只出 maintain.v1,不写真相。 -4. 删掉检验仍适用:关某个槽要说得清损失什么。 -5. 本步不输出完整 Worker 集、不写 tables 全文(交给细化终稿 / 变量设计)。 -6. 可修订已有勾选,不要为「更聪明」加槽。 +1. 只勾选,不发明:ref 必须在白名单内;无机遇裁定槽。 +2. 默认:世界模拟 = 主世界层 + 转述 + 旁观;perspective 默认关。主世界层必要。 +3. 有变量/表/规则要盯 → 开旁观;无则可不开。 +4. 变量 / Data / Progressive 不是执行单元;旁观维护只出 maintain.v1,不写真相。 +5. 删掉检验仍适用:关某个槽要说得清损失什么。 +6. 本步不输出完整 Worker 集、不写 tables 全文、不写随机范围表(交给细化终稿 / 变量设计 / 随机范围整理)。 +7. 可修订已有勾选,不要为「更聪明」加槽。 ``` ## probe @@ -89,9 +94,10 @@ boundary: | - 正文是否必须由独立转述写?(不要则 gm 兼呈现,narrator=false——需用户明确) - 是否有「主世界层不该知道的角色秘密」?(有才 perspective=true) +- 有变量/表要盯却关了旁观?或无状态却硬开旁观? - 扩写:要不要先验大纲再写章? -不要问「还想加什么 Worker」。 +不要问「还想加什么 Worker」;不要问要不要机遇裁定。 ``` ## output @@ -104,8 +110,7 @@ boundary: | "auditor": true, "gm": true, "narrator": true, - "perspective": false, - "chance": false + "perspective": false }, "writing_slots": { "outline": true, @@ -115,7 +120,7 @@ boundary: | "生成规则/变量合同/旁观摘要 → auditor(无长对话史)", "叙事指南与故事推进 → narrator(推进兼 gm)", "世界/机制/变量规则 → gm", - "真随机检定 → play_slots.chance=true(gm harness 批量工具,非每轮 chance worker)", + "随机范围整理 → gm(上下文备用随机数;无机遇槽)", "真值与 side_effects → 细化终稿 tables" ], "开放问题": [] @@ -125,28 +130,30 @@ boundary: | 填写规则: - `path=world_sim` 时必须有 `play_slots`;`writing_slots` 可省略。 - `path=writing` 时必须有 `writing_slots`;`play_slots` 可省略。 -- `auditor` / `chance` 缺省:auditor 视为 true,chance 视为 false;`chance: true` 时为主世界层开启 harness 机遇工具(仍可声明按需 `chance` ref 供显式 run_worker,但游玩默认不走每轮 chance 演员)。 +- `play_slots.gm` 世界模拟路径下应为 true。 +- `auditor` 缺省:有变量/表维护意图视为 true,否则可 false。 +- 不要输出 `chance` 字段;旧产物若有 `chance: true`,本步改为 false/删除,并指向「随机范围整理」。 - 不要输出自造 `actors[]` / 自由 `workers[]`。 - 旧产物若含 `actors[]`:本步应改写为槽位勾选,不再追加自定义 ref。 ## checklist ```checklist -- [ ] 是否只有白名单槽,无自造 ref? -- [ ] auditor / perspective / chance / 只要正文等非常规选择是否有理由? -- [ ] 是否误把变量管理做成槽?是否误把 chance 当成每轮 LLM? -- [ ] 是否误交完整 设计.worker集? +- [ ] 是否只有白名单槽,无自造 ref、无机遇裁定? +- [ ] 主世界层是否开启(世界模拟路径)?旁观是否与变量需求一致? +- [ ] auditor / perspective / 只要正文等非常规选择是否有理由? +- [ ] 是否误把变量管理做成槽?是否误交完整 设计.worker集? ``` ## examples ```examples 好: -- play_slots: auditor+gm+narrator,perspective/chance false;mount_notes 一行。 +- play_slots: gm+narrator+auditor,perspective false;有变量故开旁观。 - 有凶手真名不能进 GM:perspective true,并说明只出反应建议。 -- 需要检定/抽签:`chance: true`(gm harness 批量工具)。 +- 需要检定:不写 chance;提醒排「随机范围整理」。 坏: - actors 里发明 affinity-manager、lore-keeper、dice-master(LLM)。 -- 为性格分档再拆一个执行单元。 +- 为性格分档再拆一个执行单元;或再开机遇裁定槽。 ``` diff --git a/skills/dialogue/world-simulator/modules/world-blueprint/prompt.md b/skills/dialogue/world-simulator/modules/world-blueprint/prompt.md index e6c7dec..b7746b5 100644 --- a/skills/dialogue/world-simulator/modules/world-blueprint/prompt.md +++ b/skills/dialogue/world-simulator/modules/world-blueprint/prompt.md @@ -10,24 +10,19 @@ name: 舞台骨架 id: world-blueprint artifact: 设计.舞台骨架 declaration: > - 体验需要可引用的舞台背景时:钉尺度、基底与变造、关键舞台区,以及社会结构与世界状况; - 只细化会上台的部分,不做地图或设定百科 + 本局舞台备案:划出玩家实际游玩会换区活动的主要区域并写细;尺度与详细度随体验变。代入后几乎不移动、只在一处待着则不排 when: | - 体验契约(及可选的实现机制)已大致清楚,但仍不能回答: - “这局发生在多大的舞台上?以什么基底成立、变在哪里?” - “台上是谁在互动?世界以何种状况运转故事?” - “下游要引用哪些舞台区、社会格局或世界状况?” + 已有「美学纲领与交互范式」或等价整体感觉,且玩家实际游玩会在划分的活动区域上发生(会换区、会移动)。 + 变造世界与现实世界都要排:只是详细度有所不同。 + 玩家实际游玩过程中的主要活动区域必须写细,但如果本身世界变造不多、或特殊设定较少(如西幻就足以概括的世界),就不需要多写。 when_not: | - 核心体验未钉清 → 先「美学纲领与交互范式」。 - 只需识别体验支撑切面、不必展开环境与社会 → 「实现机制」。 - 需要可点名的人/地/物名片 → 「具体实例」。 - 需要内容如何持续生成 → 「生成规则」。 - 用户只要轻设定、明确拒绝世界骨架 → 不要排入。 + 整体感觉未钉 → 先「美学纲领与交互范式」。 + 代入后几乎不移动:玩家只会在一处待着体验,不会走到别的活动区域(如网聊、门卫室)→ 不排。 + 可点名名片 → 「具体实例」另排。持续生成合同 → 「生成规则」。 boundary: | - 本技能:可引用舞台骨架——尺度、基底+变造、关键舞台区、社会结构、世界状况;产出 context-fragment.v1。 - 不是地理志:凡影响核心运转且会上台的(生灵种类、势力、灾变、通道、习俗等)都落在社会结构或世界状况里。 + 本技能:舞台备案——范围、基底+变造、主要活动区域(写细)、社会结构、世界状况。 美学纲领与交互范式:体验与轮转——本步不重定。 - 实现机制:承重切面——本步展开世界侧骨架,不重做移除检验。 + 实现机制:既成变造法则——本步把法则落到活动区域上长什么样,不重钉法则来源。 具体实例 / 生成规则 / 叙事指南与故事推进:名片、生成节奏、遣词与推进——本步不定。 feeds: gm ``` @@ -35,17 +30,17 @@ feeds: gm ## opening ```opening -先用几句话框住「这局会出现的背景舞台」(想到什么写什么): +先框住「玩家实际会待着玩的地方」(想到什么写什么): 1. 舞台有多大?熟悉基底是什么?变在哪里? 例:一座城 / 一所学校几个系 / 「魔族与人族对峙的前线」(可抽象,不必真地图)。 2. 社会结构与世界状况里,什么在撑故事? 例:人类与丧尸如何相处;每年寒灾;南极通往怪物世界的出口;村中活人祭祀…… - 只点会影响核心运转、会反复碰到的,不写物种大全或民俗全书。 + 只点会影响核心运转、会反复碰到的。 -3. 真正会反复出现的舞台区是哪里? - 一句话即可——只点「会上台」的部分,其余可留黑。 +3. 玩家实际游玩的主要活动区域是哪几块? + 这些区域要写细——不是点名就走。舞台外可以留黑。 ``` ## task @@ -53,27 +48,25 @@ feeds: gm ```task 你正在执行「舞台骨架」。产物必须是 **context-fragment.v1** JSON,写入「设计.舞台骨架」。 -钉的是**会出现在台上、影响故事核心运转的背景**——不只是地理: -空间格局、谁在台上互动(社会结构)、世界如何运转(世界状况:灾变、通道、习俗、禁忌、命脉等)都属本步。 -不是纸面地图,也不是设定集百科。尺度由本局体验决定。 +本步是舞台**备案**:变造世界与现实世界都有划分的舞台。钉的是玩家实际游玩过程中的**主要活动区域**——这些区域要写细。范围、基底与变造、社会结构、世界状况沿用现有字段。 -同一「现代都市」基底下: -- 「体验作为韩国顶级财阀」→ 舞台往往是地球级势力、国家与资本网络; -- 「体验普通大学生活」→ 舞台可能只是一座城,甚至一所学校的几个系。 +尺度由本局体验决定。同一「现代都市」基底下: +- 「体验作为韩国顶级财阀」→ 舞台往往是地球级势力、国家与资本网络,活动区写到财团/宴会/听证层; +- 「体验普通大学生活」→ 舞台可能只是一座城或一所学校,活动区写到系馆与社团层。详细度不同,不是跳过本步。 -核心操作:在已确认体验(及可选机制支点)之上,用「熟悉基底 + 变造」钉出可引用骨架;写清社会结构与世界状况;只细化关键舞台区。 +核心操作:在已确认体验(及可选的既成法则)之上做备案;玩家主要活动区域写细;舞台外留黑。 执行顺序: -1. 读依赖与用户表述,忠实继承体验与世界侧机制支点;不重做美学/机制。 +1. 读依赖与用户表述,忠实继承体验与既成法则;不重做美学/机制。 2. 判定舞台尺度:以体验会碰到的边界为准。 3. 选定熟悉基底,写清变点。 4. 钉「社会结构」:台上有哪些种类/势力/阶层在互动(种类级与格局级,非名片)。 5. 钉「世界状况」:灾变、通道、祭祀、资源命脉、禁忌等——须能回答如何影响核心运转;软性日常条件也归此。 -6. 只展开关键舞台区;舞台外「刻意留黑」。 +6. 玩家主要活动区域写细;舞台外「刻意留黑」。 7. 类型滤镜仅作体裁/氛围参照;禁止题材套件勾选。 8. 填齐正文 + 自评 + 追问,输出 JSON。 -工作姿态——「搭舞台,不写百科」:不问世界完整长什么样,问玩家会反复看见/碰到什么背景与运转部件。 +工作姿态——「备案活动区,不写百科」:问玩家会反复待在哪、碰到什么运转部件;舞台外不补全图。 若程序已发默认问题:禁止重复开场;在首答与依赖上补洞。 summary:`舞台骨架 · …`(点题尺度 / 社会结构或世界状况)。 @@ -92,20 +85,20 @@ summary:`舞台骨架 · …`(点题尺度 / 社会结构或世界状况) 可以是抽象格局(对峙、割据、阶层天井)。不要求接壤比例尺、全史年表。 下游需要点名条目时交给「具体实例」;本步给格局级与状况级引用钩子。 -3. 变造基底,再按舞台细化 - 优先路径:大家都有印象的基底世界 → 点明变在哪里 → 只细化关键舞台区与会撑故事的社会/状况条目。 - 细化粒度跟舞台走:财阀博弈可写到国家/财团层;校园日常写到系馆与社团层即可。 +3. 变造基底,再按活动区写细 + 优先路径:大家都有印象的基底世界 → 点明变在哪里 → 玩家主要活动区域写细,并写清会撑故事的社会/状况条目。 + 详细度跟体验走:财阀博弈可写到国家/财团层;校园日常写到系馆与社团层。这是备案详细度,不是跳过本步。 4. 类型滤镜是叠加在基底上的体裁/氛围参照,不是必选题单 可用于澄清「故事以何种体裁被讲述」,从而影响冲突模式与背景气质。 禁止:列出大菜单请用户勾选;禁止因选了滤镜就自动塞满该类型常见地理与势力。 5. 与实现机制的分工 - 机制已钉「世界侧支撑切面」时:本步展开其环境/社会/状况骨架,不重做「如何支撑/缺了会怎样」。 - 机制未排入时:仍可从体验直接推断最小舞台;不要假装已经做过支撑检验。 + 机制已钉既成变造法则时:本步把法则落到主要活动区域上长什么样,不重钉「为何存在」。 + 机制未排入时:仍从体验直接做舞台备案。 -6. 宁少勿多,舞台外留黑 - 关键舞台区 + 撑故事的社会与状况写清即可停止。舞台外、体验碰不到的部分默认不写。 +6. 活动区写细,舞台外留黑 + 玩家主要活动区域写细即可停止。舞台外、体验碰不到的部分默认不写。 「未展开范围」写明刻意省略,避免下游把留黑当成缺口去补百科。 7. 正推,禁止否定式路由 @@ -122,7 +115,7 @@ summary:`舞台骨架 · …`(点题尺度 / 社会结构或世界状况) ```probe 只追问会改变尺度、变造、社会结构、世界状况或台上格局的缺口。每轮 1~2 点。已答清的禁止重问。 -【默认问题已覆盖】尺度、基底+变点、社会结构/世界状况、会反复出现的舞台区。首答后按缺口补。 +【默认问题已覆盖】尺度、基底+变点、社会结构/世界状况、玩家主要活动区域。首答后按缺口补。 优先方式: @@ -136,13 +129,13 @@ summary:`舞台骨架 · …`(点题尺度 / 社会结构或世界状况) 例:「台上互动方是否就是『人类 + 无攻击欲的丧尸』?还有没有别的智能方会影响你的掌控?」 例:「『每年寒灾』是全局运转的硬时钟,还是只在边陲传说?祭祀是真要死人,还是可被你改写的习俗?」 -4. 关键舞台区边界 - 例:「真正会反复出现的,是总部—宴会—监管听证,还是还要经常切到海外子公司现场?」 +4. 主要活动区域 + 例:「真正会反复待着玩的,是总部—宴会—监管听证,还是还要经常切到海外子公司现场?这些区要写细。」 5. 滤镜澄清 / 机制落地(可选) 体裁气质会改变冲突模式时才问滤镜;机制已点世界侧切面时,问它在台上长什么样,不重做支撑检验。 -才追问:两种尺度会显著改变后续;变点/社会/状况不清会改核心运转;关键舞台区范围决定要否某类势力;类型标签分不清氛围与硬设定。 +才追问:两种尺度会显著改变后续;变点/社会/状况不清会改核心运转;主要活动区域范围决定要否某类势力;类型标签分不清氛围与硬设定。 不追问:具体名片(→ 具体实例);完整物种志/民俗志/世界史/全地图;生成/变量/文风;用户已拒绝展开的背景;基底可默认继承的常识。 ``` @@ -258,7 +251,7 @@ summary:`舞台骨架 · …`(点题尺度 / 社会结构或世界状况) - [ ] 自评为覆盖度 / 充分度 / 克制度? - [ ] 尺度由体验决定?基底+变造可引用? - [ ] 社会结构与世界状况已写(或空数组且说明无需)?硬状况能说清如何影响运转? -- [ ] 只细化关键舞台区,且有未展开范围? +- [ ] 玩家主要活动区域已写细,且有未展开范围? - [ ] 未写成地图百科、物种志、民俗全书、类型勾选菜单、具体名片? - [ ] 追问只打尺度/社会/状况/变造缺口,带建议选项? ``` @@ -267,7 +260,7 @@ summary:`舞台骨架 · …`(点题尺度 / 社会结构或世界状况) ```examples 好: -- 体验「普通大学生活」→ 舞台=校园几系;社会结构=师生/社团层;世界状况可轻;未展开=国家政治。 +- 体验「普通大学生活」→ 仍要备案;舞台=校园几系(活动区写细);世界状况可轻;未展开=国家政治。 - 体验「垄断粮食的末日支配」→ 社会结构=人类 + 无攻击欲丧尸 + 楼内依赖关系;世界状况=外出采集命脉;舞台区=楼内安全区 / 楼外采集区。 - 世界状况示例:每年寒灾;南极通往怪物世界的出口;村中活人祭祀。 - 抽象:「魔族与人族对峙割据」——社会结构两种阵营;不画大陆全图。 diff --git a/skills/dialogue/world-simulator/present-shells/catalog.yaml b/skills/dialogue/world-simulator/present-shells/catalog.yaml new file mode 100644 index 0000000..9103e6d --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/catalog.yaml @@ -0,0 +1,19 @@ +# 游玩呈现壳目录 +# 介绍与壳规格写在 present-shells/{id}/prompt.md(```intro / ```shell) +# 正文组成执行时程序注入【可选呈现壳】;prompt 里不要写死壳清单。 + +shells: + - id: prose + name: 纯散文 + - id: chat_monitor + name: 对话+监控 + - id: spotlight + name: 场面主视 + - id: turn_panel + name: 回合面板 + - id: split_board + name: 双栏看板 + - id: choice_dock + name: 选择坞 + - id: chapter_reader + name: 章节阅读 diff --git a/skills/dialogue/world-simulator/present-shells/chapter_reader/prompt.md b/skills/dialogue/world-simulator/present-shells/chapter_reader/prompt.md new file mode 100644 index 0000000..336af06 --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/chapter_reader/prompt.md @@ -0,0 +1,18 @@ +# 章节阅读 + +## intro + +```intro +章正文 + 进度。阅读柱为主;进度窄栏钉住。 +同时看见:章正文 + 进度。 +主面积:阅读柱 + 窄进度侧栏。 +适合:长文 / 爽文。 +``` + +## shell + +```shell +id: chapter_reader +regions: [header, body, aside, footer] +default_actions: false +``` diff --git a/skills/dialogue/world-simulator/present-shells/chat_monitor/prompt.md b/skills/dialogue/world-simulator/present-shells/chat_monitor/prompt.md new file mode 100644 index 0000000..79871b2 --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/chat_monitor/prompt.md @@ -0,0 +1,18 @@ +# 对话+监控 + +## intro + +```intro +正文 + 扫状态。顶栏芯片矮;主聊/场面往下长。 +同时看见:正文 + 状态。 +主面积:正文(聊天气泡区)。 +适合:网恋 / 日常 / 轻 AIRP。 +``` + +## shell + +```shell +id: chat_monitor +regions: [monitor, body, footer] +default_actions: false +``` diff --git a/skills/dialogue/world-simulator/present-shells/choice_dock/prompt.md b/skills/dialogue/world-simulator/present-shells/choice_dock/prompt.md new file mode 100644 index 0000000..e57bf11 --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/choice_dock/prompt.md @@ -0,0 +1,19 @@ +# 选择坞 + +## intro + +```intro +局面 + 选项。读完再选;坞贴视口底。 +同时看见:局面 + 选项。 +主面积:正文 + 底部大行动坞。 +适合:选项驱动 / AVG 关口。 +默认开建议行动。 +``` + +## shell + +```shell +id: choice_dock +regions: [monitor, body, footer] +default_actions: true +``` diff --git a/skills/dialogue/world-simulator/present-shells/prose/prompt.md b/skills/dialogue/world-simulator/present-shells/prose/prompt.md new file mode 100644 index 0000000..f9d1695 --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/prose/prompt.md @@ -0,0 +1,18 @@ +# 纯散文 + +## intro + +```intro +只要正文。无 HUD。读完即止。 +同时看见:只要正文。 +主面积:正文 ≈ 全屏。 +适合:只要沉浸、不要监控条。 +``` + +## shell + +```shell +id: prose +regions: [body, footer] +default_actions: false +``` diff --git a/skills/dialogue/world-simulator/present-shells/split_board/prompt.md b/skills/dialogue/world-simulator/present-shells/split_board/prompt.md new file mode 100644 index 0000000..1dca049 --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/split_board/prompt.md @@ -0,0 +1,18 @@ +# 双栏看板 + +## intro + +```intro +正文 ‖ 线索对照。左右对照;侧栏钉住。 +同时看见:正文 + 线索。 +主面积:左正文 · 右线索。 +适合:调查、推理。 +``` + +## shell + +```shell +id: split_board +regions: [header, body, aside, footer] +default_actions: false +``` diff --git a/skills/dialogue/world-simulator/present-shells/spotlight/prompt.md b/skills/dialogue/world-simulator/present-shells/spotlight/prompt.md new file mode 100644 index 0000000..3cfd4e9 --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/spotlight/prompt.md @@ -0,0 +1,18 @@ +# 场面主视 + +## intro + +```intro +大正文 + 弱状态。少气泡框;场面即画布。 +同时看见:大正文 + 弱状态。 +主面积:正文极大(追光)。 +适合:电影感一幕、少机制。 +``` + +## shell + +```shell +id: spotlight +regions: [monitor, body, footer] +default_actions: false +``` diff --git a/skills/dialogue/world-simulator/present-shells/turn_panel/prompt.md b/skills/dialogue/world-simulator/present-shells/turn_panel/prompt.md new file mode 100644 index 0000000..e5cbd30 --- /dev/null +++ b/skills/dialogue/world-simulator/present-shells/turn_panel/prompt.md @@ -0,0 +1,19 @@ +# 回合面板 + +## intro + +```intro +场面 + 交互物 + 行动。对照交互物;行动在下。 +同时看见:场面 + 物 + 行动。 +主面积:中栏场面 + 侧栏交互。 +适合:资源/检定/跑团。 +默认开建议行动。 +``` + +## shell + +```shell +id: turn_panel +regions: [monitor, header, body, aside, footer] +default_actions: true +``` diff --git a/skills/dialogue/world-simulator/recipes/expand-assistant/recipe.yaml b/skills/dialogue/world-simulator/recipes/expand-assistant/recipe.yaml index 8bd9669..cb99e84 100644 --- a/skills/dialogue/world-simulator/recipes/expand-assistant/recipe.yaml +++ b/skills/dialogue/world-simulator/recipes/expand-assistant/recipe.yaml @@ -11,10 +11,10 @@ core: >- 世界舞台与状态机仅在体验真需要时才引入,默认不做世界模拟全套。 process: - - 开始通常先做「美学纲领与交互范式」,钉清助手站位、分段节奏与体验禁忌。 - - 之后对照能力池选型:写法/推进不够时用叙事指南与故事推进;重要同类内容难稳定生成时用生成规则,需预生成时再排具体实例。 - - 收成前排「游玩拓扑」勾选写手固定槽(大纲/细纲 + 章节正文,禁止发明新 ref)→「细化终稿」并 closed。 - - 舞台骨架、实现机制、变量、状态栏等:仅当体验需要可引用舞台或状态机时再选。 + - 开始通常先做「美学纲领与交互范式」。 + - 对照【能力 · 可选工序】的「何时用 / 何时不用」选型;调用条件以技能 meta 为准。 + - 收成前若不能吃写手默认槽(大纲+章节),再排「游玩拓扑」勾选 →「细化终稿」并 closed。 + - 舞台、机制、变量、监控栏等:仅当对应技能「何时用」成立时再选,勿套世界模拟全套。 principles: - 正推写手体验,勿默认套「世界模拟」全套能力。 diff --git a/skills/dialogue/world-simulator/recipes/world-simulator/recipe.yaml b/skills/dialogue/world-simulator/recipes/world-simulator/recipe.yaml index 1d08146..c7fe8d9 100644 --- a/skills/dialogue/world-simulator/recipes/world-simulator/recipe.yaml +++ b/skills/dialogue/world-simulator/recipes/world-simulator/recipe.yaml @@ -1,44 +1,38 @@ # 世界模拟器 · 配方 # 写方法论:适用、核心思路、设计流程、原则。 # 各技能何时用 / 不用 → 读技能 meta(编排器会注入),勿在此重复。 -# steps = 近期起点;选中本配方时程序写入「设计.创作流程」,开局即坐在第一步(不是固定全程 DAG)。 +# steps = 开局起点;选中本配方时程序写入「设计.创作流程」,开局即坐在第一步。 when: 回合互动、世界推进、角色扮演、沉浸推演类体验 core: >- - 先钉清用户如何参与、正文如何呈现、核心体验与禁忌; - 再按缺口增量写出上下文,并标明挂哪些固定槽(默认:主世界层裁决 + 叙事转述); + 先钉清用户如何参与、正文如何呈现、核心体验与禁忌(美学卡上用户会在意的部分); + 再按那些承诺选出要兑现的上下文技能,并标明挂哪些固定槽(默认:主世界层裁决 + 叙事转述); 挂载归属可早定,插入顺序必须晚定——收成前用「上下文投影排序」按各块概括排出数字序与双锚点投影; - 再细化终稿收成运行规格。不发明执行单元、不为表/百科再拆槽。 + 再细化终稿收成运行规格。执行单元只用固定槽(主世界层 / 叙事转述 / 可选角色视角;旁观按变量需要),不为表/百科再拆槽,不开机遇裁定槽。 process: - - 开始通常先做「美学纲领与交互范式」,确认站位、轮转与要反复感受到什么。 - - 体验契约稍清后即可确认游玩槽(「游玩拓扑」或按默认:主世界层 + 叙事转述,角色视角默认关);此后写上下文时只标挂谁,不标最终顺序。 - - 对照技能池「何时用 / 何时不用」,只排近期缺的 1~4 步;不预设固定长链。 - - 中段软顺序:机制/舞台支点 → 要不要真值 → 有门控再排变量与分档/事件 → 叙事/正文组成/监控栏按需;每块产物带 mount(挂哪些槽)与可选「稳/变」信号,勿写死 order。 - - 用户看见的呈现:用「正文组成」**选固定壳并微调**(见 docs/play-presentation-shells.md),不是从零设计 UI;会变信息用「设计监控栏」。 - - 需要可引用舞台时用「舞台骨架」;识别体验支点用实现机制;同类内容难稳定生成用生成规则,需预生成再排具体实例。 - - 需要门控/分档/程序事件:先「变量设计与更新规则」,再「变量控制上下文」。变量与 Progressive 不是执行单元。 - - 挂载归属(非顺序):世界/机制/生成 → 主世界层;叙事指南与故事推进 → 叙事转述(推进兼挂主世界层);美学进常驻。勿为世界观或性格表另开槽。拓扑图谱在固定槽已够用时通常跳过。 - - 需要把美学「感觉」落成遣词/笔墨焦点/禁忌与推进时用「叙事指南与故事推进」;事件表 schema 仍用生成规则,真值门控用变量设计。 - - 收成链(顺序固定):上游上下文大致齐 →「上下文投影排序」→「细化终稿」→ 需要开场则排「开场白与开场变量」(〔收口〕:选定后结束创作并保存)。 - - 「开场白与开场变量」写出 1~多条开场白;选定后程序落库到输出.开场白与运行.初始变量,不必再调 opening-generator。 - - 变量:真值 + Data 映射索引(实例表在具体实例)+ 维护语句(裁决包/隐藏段,非 chance)+ 旁观汇总挂载(变量控制上下文)。 + - 开始通常先做「美学纲领与交互范式」。 + - 读美学卡上用户会在意的部分,对照【能力 · 可选工序】的何时用 / 何时不用,把兑现那些承诺所需的节点写进 steps(需要几步排几步)。各技能调用条件以 meta 为准,本表不重复。 + - 世界模拟默认槽:主世界层 + 叙事转述 + 旁观维护(有变量/表时;视角关)。能吃默认则不必排「游玩拓扑」。主世界层必要。 + - 中段按承诺写上下文;每块只标挂谁(mount)与稳/变,order 留给「上下文投影排序」。挂载归属:世界/机制/生成 → 主世界层;叙事指南 → 叙事转述(推进兼挂主世界层);美学进常驻。 + - 「回复呈现」几乎都排:先钉每轮看什么。有检定/对抗/掷骰则排「随机范围整理」收范围表。二者都在「正文组成」之前;正文组成把清单(及隐藏备用随机区)展示出来,开场白之前。 + - 收成链顺序固定:上游上下文大致齐 →「回复呈现」→(若有随机)「随机范围整理」→「正文组成」→「上下文投影排序」→「细化终稿」→ 需要开场则「开场白与开场变量」(〔收口〕)。选定开场后结束创作并保存。 principles: - - 正推:体验 → 缺口 → 技能;禁止题材默认全选世界模拟套件。 + - 正推:美学卡上用户会在意的部分 → 缺口 → 技能。同一题材换核就换图,不按题材套世界模拟全套。 - 技能选型以技能 meta 为准;本配方不代替各技能写调用条件。 - - 禁止自由发明执行单元;只用固定槽(主世界层 / 叙事转述 / 可选角色视角 / 可选机遇裁定)。 - - 默认少槽:主世界层 + 叙事转述;仅强信息隔离才开角色视角;骰子/抽签/比点开机遇裁定(按需程序工具,不进每轮)。 - - 挂谁可早、排第几须晚:插入序与投影位只由「上下文投影排序」产出;中段技能禁止抢写最终 order。 + - 执行单元只用固定槽(主世界层 / 叙事转述 / 可选角色视角;旁观按需)。不开机遇裁定;真随机=随机范围整理 + 程序插备用数。 + - 默认少槽:主世界层必开 + 叙事转述;有变量/表开旁观;仅强信息隔离才开角色视角。 + - 挂谁可早、排第几须晚:插入序与投影位只由「上下文投影排序」产出;中段技能写 mount 与稳/变。 - 投影序扁平:「对话.历史」按 projection 动态裁剪;少变靠前、易变靠后是软规则,不是硬分区。 - - 真值 / Data / Progressive 三分;派生性格与章细纲不落可写真值(见 progressive-data-design)。 - - 有编排参数的步骤必须在进执行前钉齐 params(askUser 选项+其它),禁止空壳进 design-step。 - - 同技能可反复编入(不同 step.id + params);已验收步骤不得删除。 - - 轻设定或用户明确不要世界骨架时,跳过不必要的世界/机制步骤。 + - 真值 / Data / Progressive 三分;派生性格与章细纲不落可写真值。 + - 有编排参数的步骤:进执行前钉齐 params(askUser 选项+其它);缺参时先问再进 design-step。 + - 〔可反复〕可再追加(彻底新建);已验收 id 留在 steps。 + - 舞台骨架通常都排(备案,只分详细度);代入后几乎不移动、只在一处待着则不排。实现机制对照其 meta。 - 百科与查表归主世界层;裁决归主世界层、可见正文归叙事转述。 -brief: 世界模拟类:体验→挂槽写上下文→晚排序投影→收成运行规格 +brief: 世界模拟类:美学卡上在意的部分→挂槽写上下文→晚排序投影→收成运行规格 steps: - id: 美学纲领与交互范式 diff --git a/skills/dialogue/world-simulator/worker-templates/chapter-writer.yaml b/skills/dialogue/world-simulator/worker-templates/chapter-writer.yaml index 7edca48..2e7fd25 100644 --- a/skills/dialogue/world-simulator/worker-templates/chapter-writer.yaml +++ b/skills/dialogue/world-simulator/worker-templates/chapter-writer.yaml @@ -22,4 +22,6 @@ presentation_hints: prompt_excerpt: | 你是章节写手。只写本轮要求的一段/一章,对照大纲节点兑现承诺。 输出进 正文.当前段;若需归档到 正文.已完成 按声明 outputs 执行。 + 用户本轮输入视为待扩写为事实的大纲:细化完全后写成正文;剧情不超出大纲未涉及处,完整演绎大纲内容。 + 正文采用完整长自然段叙述,不要单句成段;篇幅默认约 1000~2000 字(用户或回复呈现另有规定则从其)。 不要重写整本;不要发明与大纲冲突的主线转折,除非用户本轮明确要求。 diff --git a/skills/dialogue/world-simulator/worker-templates/narrator.yaml b/skills/dialogue/world-simulator/worker-templates/narrator.yaml index 68f8372..c4eed20 100644 --- a/skills/dialogue/world-simulator/worker-templates/narrator.yaml +++ b/skills/dialogue/world-simulator/worker-templates/narrator.yaml @@ -36,7 +36,11 @@ prompt_excerpt: | "meta": { "suggested_actions": ["…"] } } monitor 用短键值(芯片),勿写长文。只填该壳已有区域。 - 用户主读正文(body)默认 500~2000 字(汉字):写成可连读的场面/对话推进,不要几句短信就结束。 + 用户主读正文(body)默认 1000~2000 字(汉字);以「设计.监控栏」回复呈现已钉字数为准。 + 采用完整长自然段叙述,不要单句成段;不要几句短信就结束。 + 用户输入用法以「设计.叙事指南与故事推进」为准。常见两套: + - 大纲扩写:输入当大纲扩写为事实,细化后写正文;不超出大纲未涉及的剧情,完整演绎大纲。 + - 扮演停笔:把用户本轮行为与对话作正文开头并扩写填满;不可写用户角色未给出的其它行为/对话;不可替用户角色做决定;正文停在其他角色等用户角色回应之刻。 禁止在正文里写出 tag 名(「输出.用户展示」)、压缩摘要或过程日志。 禁止写出 do_not_say;禁止编造包中没有的事实。 若裁决含 tone_hint / npc_moves / suggested_actions,须体现在 body 或 meta。 diff --git a/skills/dialogue/world-simulator/worker-templates/world-simulator.yaml b/skills/dialogue/world-simulator/worker-templates/world-simulator.yaml index c3e87d0..649152b 100644 --- a/skills/dialogue/world-simulator/worker-templates/world-simulator.yaml +++ b/skills/dialogue/world-simulator/worker-templates/world-simulator.yaml @@ -26,5 +26,6 @@ prompt_excerpt: | player_action、resolved[]、visible_now、npc_moves[]、variable_changes[]、do_not_say[]、tone_hint。 variable_changes 由 Runtime 合并进变量.当前——请写清 key 与 to/delta。 叙事质量 intentionally 低——用户正文交给 narrator。 - 需要真随机时:调用 chance 工具,在 requests 数组中一次性提交全部掷骰/抽取(每项带 id);禁止口算。 + 若叙事指南为「扮演停笔」:只裁决用户本轮已声明的行为/对话;禁止替用户角色发明其它行动或做决定;npc_moves 可推进到需要用户角色回应之刻即停。 + 需要随机数时:只用本轮上下文里程序已插入的备用随机数(见「设计.随机范围整理」);禁止口算编造;不要调用已取消的机遇裁定槽。 不要把未投影的分档长文整表塞进输出;只写本轮可见后果。 diff --git a/skills/dialogue/world-simulator/workers/design-flow/SKILL.md b/skills/dialogue/world-simulator/workers/design-flow/SKILL.md index fda9c8b..6fb723a 100644 --- a/skills/dialogue/world-simulator/workers/design-flow/SKILL.md +++ b/skills/dialogue/world-simulator/workers/design-flow/SKILL.md @@ -3,8 +3,8 @@ id: design-flow skill: world-simulator name: 创作 · 流程编排 description: >- - 【编排】以用户已选配方为起点,从能力池排出近期 DAG 骨架(节点 + 依赖 + 原型槽位 + 建议)。 - 不决定执行顺序;用户在图上点选。本步不写美学/机制正文。 + 【编排】从美学卡上用户会在意的部分推出要哪些节点、节点建议写什么;对照已完成 id。 + 产出工作流计划 DAG。用户在图上点选执行顺序。本步不写各技能正文。 version: 1 stage: design inputTags: @@ -13,6 +13,7 @@ inputTags: - "用户.最新输入" - "用户.worker答复" - "用户.修订说明" + - "设计.美学纲领与交互范式" - "设计.创作流程" - "创作.选用配方" - "创作.已验收单位" @@ -20,14 +21,18 @@ outputTags: - "设计.创作流程" inputMerge: latest contextSegments: - - id: prior-flow + - id: opening-aesthetics tier: static - tags: ["设计.创作流程"] - label: "## 【已有剧本草案】若有则在其上增量修订;无则新建近期 horizon" + tags: ["设计.美学纲领与交互范式"] + label: "## 【开头节点 · 美学纲领】用户会在意这张卡的哪几处?用那些承诺选节点(无则先排本步)" - id: accepted-units tier: static tags: ["创作.已验收单位"] - label: "## 【已验收步骤】禁止删除这些 id;只能追加或改未验收步" + label: "## 【已验收步骤】已完成节点的 id 清单(只作覆盖标记,不是各步正文)" + - id: prior-flow + tier: static + tags: ["设计.创作流程"] + label: "## 【已有工作流计划】在其上修订;无则新建" - id: selected-recipe tier: static tags: ["创作.选用配方"] @@ -38,80 +43,66 @@ contextSegments: label: "## 用户表述" --- + + # 创作 · 流程编排 -你只做一件事:根据【用户要求】编排或**增量修订**一份 **DAG 骨架**。要求按先后都有效,冲突时以较新的为准。 +读【开头节点 · 美学纲领】里**用户会在意的部分**,推出要哪些节点、节点建议写什么;对照【已验收步骤】标记,从【能力 · 可选工序】排出一份 **工作流计划 DAG**,写入 tag `设计.创作流程`。无美学卡时用【用户要求】当种子。 -**你不决定**用户下一步先跑哪个——用户在分层图上点选。你只产出:有哪些节点、depends_on、原型槽位(repeatable 能力)、以及建议。 +产出:节点 + `depends_on` +(〔可反复〕)原型槽位与 `suggestion` + 可选顶层 `suggestions`。用户在图上点选下一步;你给出依赖与建议阅读序。 -上下文里会有: +先读【流程进度】(已完成 / 草案已有 / 尚未编入)、【用户已选配方】、【能力 · 可选工序】,再排。要求按先后都有效,冲突时以较新的为准。 -1. **【流程进度】**(程序钉死):已完成哪些步、草案里已有哪些步、原型槽位。必须先读完再排。 -2. **【用户已选配方】**:方法论 + 近期起点——**不是**锁死流水线 -3. **【能力 · 可选工序】**:步骤只能从这里选 -4. **【已有剧本草案】/【已验收步骤】**:在其上追加,**不要**推倒重来 +## 怎么排 -## 增量 DAG(核心) +先当用户看这张美学卡:**我会在意哪几处?** 那几处是本局要兑现的承诺。再问:兑现每一处,要哪些技能节点、节点里建议写什么?已完成 id 表示那一处已经有槽。 -**禁止**一次排完全程固定长链。每次只排出**近期 horizon**(通常 1~4 个节点 + 若干原型),`status` 默认 `"open"`。 +同一题材,卡上在意的东西不同,图和 suggestion 就不同。例如都是丧尸末日: -### 节点类型 +- 核是异能觉醒、升级、对抗(网文)→ 生成规则写异能/等级合同,变量盯等级与觉醒,叙事管打脸与对抗节奏 +- 核是人与人背刺(美式)→ 具体实例锚定开局几个人,叙事管背叛与信任,变量控制管信任度和资源缺口;舞台可以很薄 +- 核是砍砍砍(B 级片)→ 生成规则写可砍的尸群,叙事管血腥动作笔墨;等级、背刺、复杂社会可以不排,反倒是武器生成规则需要仔细斟酌 -| 类型 | JSON | 谁跑 | -|------|------|------| -| 普通一步 | 缺省(无 role) | 用户点上直接 design-step | -| **原型槽位** | `"role": "prototype"` | 用户点上 → 程序增殖 instance → design-step | -| **实例** | `"role": "instance"`, `"from": "<原型 id>"` | 仅程序增殖,**禁止**你在编排层预排 | +题材名(丧尸、都市、宫廷)本身不决定套件。用户会反复感到的那几处才决定。 -**禁止**排 `mode=revise` / 回头修改节点。已完成节点要改:用户在图上点该节点重进,不在 DAG 里加修订步。 +无美学卡:体验尚未钉清,先排「美学纲领与交互范式」;其余只排此刻能从【用户要求】看出用户在意什么。美学已验收之后,按这些承诺把该排的节点写进 `steps`——需要几步排几步。 -### 〔可反复〕= 原型,不是多条 instance +选定节点时对照【能力 · 可选工序】的何时用 / 何时不用 / 边界:这份承诺该由哪个技能兑现。配方 `core` / `process` / `principles` 给方法顺序(默认槽、收成链),不代替「用户在意什么」。含糊或可跳过则不排。已在草案里的 `name` 保留,一次性技能不写第二份。能力池里兑不了那处承诺:不发明新 `name`,askUser 问用户改体验还是放弃那一处。 -生成规则、具体实例等 catalog 标〔可反复〕的能力: +用户要补节点:插在未验收步之前、收口之前,`status: "open"`。新 `name` 只从【流程进度】「尚未编入、仍可调用」里选。 -- 在 `steps` 里写 **`role: "prototype"`** 一条即可(id 通常与 name 相同,如 `"生成规则"`) -- 写 **`suggestion`**:建议这条原型将来生成什么(短句,给用户和实例步参考) -- **禁止**在原型上写 `params` -- **禁止**预排 `role: "instance"` 或 `生成规则#2` 这类实例——用户在图上点原型,程序增殖 +〔可反复〕的 `suggestion` 必须点名这局在意的对象(异能合同 / 开局背刺对象 / 可砍尸群),不要写成空泛的「NPC 与物资」。本局还可能用到、但暂时不写进 `steps` 的:写入顶层 `suggestions`。已在 `steps` 里的不重复。暂时不必则省略。 -### `suggestions`(流程级) +## 节点怎么写 -除 `steps` 里的原型外,可在顶层写 **`suggestions`**:建议用户**还可以**追加哪些原型(尚未编入 steps 时展示在图上)。 -```json -"suggestions": [ - { - "name": "生成规则", - "suggestion": "怪物种群与 NPC 两套规则,各开一条", - "depends_on": ["美学纲领与交互范式"] - } -] -``` +| 类型 | JSON | 进入执行 | +| ---- | ----------------------------------------- | ---------------------------------- | +| 普通一步 | 无 role | 用户点上 → design-step | +| 原型槽位 | `"role": "prototype"` + `suggestion` | 用户点上 → 程序增殖 instance → design-step | +| 实例 | `"role": "instance"`, `"from": "<原型 id>"` | 仅程序增殖 | -若已把该能力编入 `steps` 为 prototype,不必在 suggestions 重复。 -### 〔先验产物〕 +〔可反复〕(生成规则、具体实例等):`steps` 里写一条原型即可(id 通常与 name 相同,如 `"生成规则"`),并写 `suggestion`(建议这条原型将来生成什么)。原型只带 `suggestion`;「写什么」在用户点原型后的实例步内钉。 -生成规则、具体实例:**「写什么」在实例步内钉**,不在编排层 params。原型只带 `suggestion`。 +已完成节点要改:用户在图上点该节点重进。编排只追加未验收步、改未验收依赖;已验收 id 原样留在 `steps`。 -### 选型规则 +〔收口〕「开场白与开场变量」排在 `steps` 最后。选定开场前若要补前序节点,插在收口之前,保持收口为最后一步,`status` 仍为 `"open"`。 -- 跟配方 core / process / principles -- 跟能力 meta 的何时用/不用 -- 用户要补节点 → 插在未验收步之前、收口之前,`status: "open"` +askUser 只问排布(补哪个原型、改依赖)。用户谈到体验正文:当作编排线索;体验细节留到对应技能步。排布已能写清则直接产出。 -## 产出(唯一) +## 产出 -写入 tag `设计.创作流程`。根对象就是下面这份 JSON(必须含 `steps`),不要改写成 `artifact.flat.v1` 的 sections。 +根对象就是下面这份 JSON(必须含 `steps`)。 ```json { - "brief": "一句话体验(可选)", + "brief": "代入觉醒者,反复感到升级碾压与对抗", "status": "open", "suggestions": [ { "name": "具体实例", - "suggestion": "开局 2~3 个重要 NPC", + "suggestion": "开局 1 个对照用的未觉醒同伴", "depends_on": ["生成规则"] } ], @@ -121,41 +112,46 @@ contextSegments: "id": "生成规则", "name": "生成规则", "role": "prototype", - "suggestion": "先写怪物种群生成规则", + "suggestion": "异能觉醒与升级合同", "depends_on": ["美学纲领与交互范式"] }, { - "id": "具体实例", - "name": "具体实例", - "role": "prototype", - "suggestion": "锚定 1~2 个开局 NPC", - "depends_on": ["生成规则"] + "id": "变量设计与更新规则", + "name": "变量设计与更新规则", + "depends_on": ["美学纲领与交互范式"] + }, + { + "id": "叙事指南与故事推进", + "name": "叙事指南与故事推进", + "depends_on": ["美学纲领与交互范式"] + }, + { + "id": "细化终稿", + "name": "细化终稿", + "depends_on": ["生成规则", "变量设计与更新规则", "叙事指南与故事推进"] }, { "id": "开场白与开场变量", "name": "开场白与开场变量", - "depends_on": ["美学纲领与交互范式", "具体实例"] + "depends_on": ["细化终稿"] } ] } ``` -规则: +1. `steps` 顺序 = 建议阅读顺序;`depends_on` 指向更前步骤 id +2. `name` = 能力池固定中文名 +3. `id` 本局唯一;原型 id 稳定(如 `生成规则`);实例 id 由程序增殖(`生成规则#1`…) +4. 具体实例原型依赖生成规则原型(至少一条规则实例验收后才可增殖) +5. `summary`:`流程 · N 步 · open|closed · …` + -1. `steps` 顺序 = 建议阅读顺序;`depends_on` 须指向更前步骤 id -2. `name` = 能力池固定中文名 -3. `id` = 本局唯一;原型 id 稳定(如 `生成规则`);实例 id 由程序增殖(`生成规则#1`…) -4. **禁止**在编排层为 repeatable 预排 instance 或写 params -5. 已验收 id **必须保留** -6. 非反复已完成 → 禁止再排新建,**禁止**排 `mode=revise` -7. 收口「开场白与开场变量」排最后;选定前用户补节点 → 插收口前、`status: "open"` -8. askUser 只问排布:补哪个原型、改依赖。**禁止**问体验正文,**禁止**问要不要回头修改 -9. `summary`:`流程 · N 步 · open|closed · …` ## 自检 -- 只排了骨架,没有替用户决定顺序? -- repeatable 是否都是 `role=prototype` + suggestion,没有 instance/params? -- suggestions 是否简短、可执行? -- depends_on 是否合法(具体实例原型依赖生成规则原型 = 至少一条规则实例验收后才可增殖)? -- 已验收 id 是否都在? +- 节点和 `suggestion` 是否兑现卡上用户会在意的那几处(同一题材换核会换图),而不是题材默认套件? +- 已验收 id 是否都在 `steps` 里? +- 〔可反复〕是否都是 `role=prototype` + suggestion? +- 尚未编入里本局还可能用到的〔可反复〕是否进了 `suggestions`? +- 收口是否在最后?`depends_on` 是否合法? + diff --git a/src/server/agent-view.ts b/src/server/agent-view.ts index 39434e1..e7566ca 100644 --- a/src/server/agent-view.ts +++ b/src/server/agent-view.ts @@ -440,7 +440,7 @@ export function buildFocus( actorType: "user", actorLabel: "你", action: "点选要做的节点", - detail: "点可进入的节点即确认并开始;虚线原型点一下增殖再进去。要改排在底栏写意见再发", + detail: "点图上可进入的节点即开始;要看技能池点上方「技能」。虚线原型点一下增殖。要改排在底栏写意见再发", }; } @@ -485,7 +485,7 @@ export function buildFocus( actorType: "user", actorLabel: "你", action: "点选要做的节点", - detail: "点可进入的节点即确认并开始;虚线原型点一下增殖再进去。要改排在底栏写意见再发", + detail: "点图上可进入的节点即开始;要看技能池点上方「技能」。虚线原型点一下增殖。要改排在底栏写意见再发", }; } const copy = reviewComposerCopy(art?.workerId, { diff --git a/src/server/session-manager.ts b/src/server/session-manager.ts index 5d27ad4..f731266 100644 --- a/src/server/session-manager.ts +++ b/src/server/session-manager.ts @@ -2472,7 +2472,7 @@ export class SessionManager { }); } else if (reason?.kind === "pick_creation_step") { hints.push( - "点可进入的节点即确认并开始。虚线原型点一下会增殖一条实例再进去。要改排在底栏写意见再发。", + "点图上可进入的节点即开始。要看技能池点上方「技能」。虚线原型点一下会增殖一条实例再进去。要改排在底栏写意见再发。", ); actions.push({ type: "replan", label: "发送" }); actions.push({ @@ -2494,7 +2494,7 @@ export class SessionManager { }); if (art?.workerId === DESIGN_FLOW_WORKER_ID) { hints.push( - "点可进入的节点即确认并开始。虚线原型点一下会增殖一条实例再进去。要改排在底栏写意见再发。", + "点图上可进入的节点即开始。要看技能池点上方「技能」。虚线原型点一下会增殖一条实例再进去。要改排在底栏写意见再发。", ); actions.push({ type: "send_message", diff --git a/src/skills/creation-flow.ts b/src/skills/creation-flow.ts index 13c17da..dbc12c7 100644 --- a/src/skills/creation-flow.ts +++ b/src/skills/creation-flow.ts @@ -269,11 +269,21 @@ export type CreationFlowSpawnView = { blockedReason?: string; }; +/** 目录里尚未编入本局 DAG、仍可追加的技能 */ +export type CreationFlowAvailableModule = { + name: string; + declaration?: string; + repeatable?: boolean; + closer?: boolean; +}; + export type CreationFlowUserView = { brief?: string; status?: CreationFlowStatus; /** 规划层建议追加的原型(尚未在 steps 里) */ suggestions?: CreationFlowPrototypeSuggestion[]; + /** 技能目录里尚未编入本局、仍可要求追加 */ + availableModules?: CreationFlowAvailableModule[]; steps: Array<{ order: number; id: string; @@ -1244,12 +1254,14 @@ function slugFromName(name: string): string { 生成规则: "generation-rules", 具体实例: "concrete-instances", 拓扑图谱: "topology", + 回复呈现: "status-bar", 设计状态栏: "status-bar", 设计监控栏: "status-bar", 变量设计与更新规则: "variable-design", 变量控制上下文: "variable-context", 设计回复格式: "reply-format", 正文组成: "reply-format", + 随机范围整理: "random-range", 游玩拓扑: "worker-spec", "Worker 规格": "worker-spec", // 旧称,等同游玩拓扑 细化终稿: "refine", @@ -1318,7 +1330,7 @@ export function formatModuleCatalogForAgent(catalog: ModuleCatalog): string { "按需选用,勿默认全选;步骤名只能从这里选;标〔可反复〕的可多次编入;标〔收口〕的是终节点:排在细化终稿之后作最后一步;尚未选定开场前,用户要补前序节点(如 NPC)时插在收口之前,勿以「收口已排入」拒绝追加;选定后才结束创作并保存;标〔程序步〕的确认编排后直接执行(不抛默认问题、不经同意并开始),产物仍验收。", "标〔先验产物〕(生成规则、具体实例):编排层只排 role=prototype 槽位 + suggestion;禁止在原型写 params、禁止预排 instance。「写什么」在用户点原型增殖后的实例步内钉。", "其它有「编排参数」的步骤:确认开干前写齐必填 params;缺参时用 askUser 选项+其它。", - "选型依据是下方「何时用 / 何时不用 / 边界」(来自各能力 meta)。", + "选型依据是下方「何时用 / 何时不用 / 边界」(来自各能力 meta)。对照用户表述与已验收产物判定:该排才排;可跳过或条件含糊则不排。不要用执行细则补脑。", "〔可反复〕再编入新 id = 彻底新建一条。已完成节点要改:禁止排 mode=revise 新步;用户会在图上点该节点重进。禁止把改旧稿写成又一条 fresh。", "不要把能力执行全文塞进本步;执行由 design-step 注入。", lines.join("\n"), @@ -1534,15 +1546,14 @@ export function formatRecipeCatalogForAgent(catalog: RecipeCatalog): string { return `【可选配方】(须由用户手动选择)\n${lines.join("\n")}`; } -/** 注入 design-flow:用户已选配方(方法论 + 近期起点) */ +/** 注入 design-flow:用户已选配方(方法论 + 开局起点) */ export function formatSelectedRecipeForAgent(detail: RecipeDetail): string { const lines: string[] = [ `【用户已选配方 · ${detail.name}】`, - "这是用户手动选定的设计方法,不是锁死流水线。", - "产出**增量工作流计划(DAG)**:只排近期要做的步骤;已验收步保留,可追加同技能多次调用。", - "按用户表述与配方方法论增删改未验收步骤与依赖;步骤名只能从【能力】选。", + "这是用户手动选定的设计方法。步骤名从【能力】选。", + "对照美学卡上用户会在意的部分与配方方法论,增删改未验收步骤与依赖;已验收步保留。", "能力「何时用 / 何时不用」以【能力 · 可选工序】为准;本配方不重复罗列各能力调用条件。", - "禁止改选其它配方;若用户要换配方,须等用户重新选定后再编排。", + "用户要换配方:等用户在界面重新选定后再编排。", ]; if (detail.declaration) lines.push(`简介:${detail.declaration}`); if (detail.when) lines.push(`适用:${detail.when}`); @@ -1571,12 +1582,12 @@ export function formatSelectedRecipeForAgent(detail: RecipeDetail): string { null, 2, ); - lines.push("建议近期 steps(增量起点,可改;勿一次排完全程):"); + lines.push("开局 steps(配方预置起点,可按美学卡上的承诺增删):"); lines.push("```json"); lines.push(stepsJson); lines.push("```"); } else { - lines.push("建议 steps:(待作者完善 recipe.yaml;可从【能力】自行编排近期 horizon)"); + lines.push("开局 steps:(recipe.yaml 尚未写 steps;可从【能力】按美学卡上的承诺编排)"); } return lines.join("\n"); } @@ -1592,7 +1603,6 @@ function formatRecipeFieldBlock(value: string | string[]): string { export function formatDesignFlowContentBlocks(params: { selectedRecipe?: RecipeDetail | null; modules?: ModuleCatalog | null; - missingSelection?: boolean; flow?: CreationFlow | null; acceptedStepIds?: readonly string[]; filledArtifactTags?: readonly string[]; @@ -1605,15 +1615,7 @@ export function formatDesignFlowContentBlocks(params: { filledArtifactTags: params.filledArtifactTags, }), ]; - if (params.missingSelection) { - blocks.push( - [ - "【配方】用户尚未手动选择。", - "禁止自行猜测或替用户选定配方。", - "请 askUser 请用户从可用配方中选择,或等待用户在界面选定后再编排。", - ].join("\n"), - ); - } else if (params.selectedRecipe) { + if (params.selectedRecipe) { blocks.push(formatSelectedRecipeForAgent(params.selectedRecipe)); } if (params.modules) { @@ -1623,8 +1625,8 @@ export function formatDesignFlowContentBlocks(params: { } /** - * 编排器必须看见的进度:哪些步已做完、草案里已有什么、哪些能力才允许再编入。 - * 裸 JSON id 列表不够;此块由程序钉死。 + * 编排 LLM 必须看见的现场进度:已完成、草案已有、原型槽位、尚未编入。 + * 裸 JSON id 列表不够;此块由程序按现场拼装。 */ export function formatFlowProgressForAgent(params: { flow?: CreationFlow | null; @@ -1655,8 +1657,8 @@ export function formatFlowProgressForAgent(params: { repeatable: boolean, ) => { const flag = repeatable - ? "〔可反复:mode=fresh 再追加 = 彻底新建〕" - : "〔不可反复:禁止再排新建,也禁止排 mode=revise〕"; + ? "〔可反复:再追加 = 彻底新建;改旧的由用户点该实例重进〕" + : "〔一次性:这一面已覆盖;要改则用户点该节点重进〕"; const idBit = id ? `(id: ${id})` : ""; doneLines.push(`- ${name}${idBit} · ${why} ${flag}`); doneNames.add(name); @@ -1702,7 +1704,7 @@ export function formatFlowProgressForAgent(params: { if (isPrototypeStep(step)) continue; if (doneIds.has(step.id) || isStepAccepted(step, accepted)) continue; draftLines.push( - `- ${step.name}(id: ${step.id}) · 已在草案,保留原 id;不要当作新规划再写一遍`, + `- ${step.name}(id: ${step.id}) · 已在草案,保留原 id`, ); } } @@ -1719,7 +1721,7 @@ export function formatFlowProgressForAgent(params: { ? ` · 建议:${step.suggestion.trim()}` : ""; prototypeLines.push( - `- ${step.name}(id: ${step.id},role=prototype)${sug} · 保留;用户在图上点增殖,禁止预排实例或写 params`, + `- ${step.name}(id: ${step.id},role=prototype)${sug} · 保留;用户点此槽增殖 instance`, ); } } @@ -1729,12 +1731,10 @@ export function formatFlowProgressForAgent(params: { ); const lines = [ - "【流程进度】(程序钉死,必须遵守)", - "你只排 DAG 骨架:节点 + depends_on +(repeatable 能力)原型槽位 + suggestions。不决定用户先跑哪个。", - "〔可反复〕须写 role=prototype,可带 suggestion(建议生成什么);禁止预排 instance、禁止在原型上写 params。「写什么」在实例步 design-step 里钉。", - "已完成的非反复技能:禁止再排新建,禁止排 mode=revise。改已完成节点由用户在图上点选重进,不要在 DAG 里加修订步。", - "要改已有实例:用户点该实例重进。点原型增殖 = 全新 instance(role=instance,from=原型 id)。", - "草案里已有的步骤:原样保留,不要重排一遍开局。", + "【流程进度】程序按现场列出:已完成、草案已有、原型槽位、尚未编入。编排以这份清单为准。", + "已完成 = 覆盖标记(原 id 留在 steps);草案已有 = 保留原 id,在其上追加或改未验收依赖;尚未编入 = 新 name 只从这里选。", + "〔可反复〕在 steps 里写一条 role=prototype,带 suggestion(点名这局在意的对象)。「写什么」在用户点原型后的实例步里钉。", + "一次性技能已覆盖的那一面:要改则用户点该节点重进。要改已有实例:用户点该实例重进。点原型增殖 = 全新 instance(role=instance,from=原型 id)。", ]; const closerPending = catalog && flow @@ -1747,7 +1747,7 @@ export function formatFlowProgressForAgent(params: { lines.push( `草案已有〔收口〕${closerPending .map((s) => `「${s.name}」`) - .join("、")}但尚未选定。用户要求补节点(如 NPC、生成规则、具体实例)时:把新步插在收口之前,保持收口为最后一步,并将 status 改回 open。禁止以「收口已排入」为由拒绝追加。`, + .join("、")}但尚未选定。用户要补节点时:把新步插在收口之前,保持收口为最后一步,并将 status 改回 open。收口已排入仍可在它前面加步。`, ); } if (doneLines.length) { @@ -1755,14 +1755,14 @@ export function formatFlowProgressForAgent(params: { } else { lines.push( "", - "已完成:尚无已验收步骤。若草案已有开局步,那是配方预置起点,不是你新规划的。", + "已完成:尚无已验收步骤。草案里的开局步是配方预置起点,保留原 id。", ); } if (draftLines.length) { - lines.push("", "草案已有、尚未验收(保留,勿重排):", ...draftLines); + lines.push("", "草案已有、尚未验收(保留原 id):", ...draftLines); } if (prototypeLines.length) { - lines.push("", "原型槽位(保留,勿改成 instance):", ...prototypeLines); + lines.push("", "原型槽位(保留;用户点增殖):", ...prototypeLines); } if (suggestionLines.length) { lines.push( @@ -1771,6 +1771,33 @@ export function formatFlowProgressForAgent(params: { ...suggestionLines, ); } + const leftover = listCallableCatalogModules({ + flow, + catalog, + acceptedStepIds: accepted, + filledArtifactTags: params.filledArtifactTags, + }); + if (leftover.length) { + lines.push( + "", + "尚未编入、仍可调用(新 name 只从这里选):", + ...leftover.map((m) => { + const flags = [ + m.repeatable ? "〔可反复〕" : "", + m.closer ? "〔收口〕" : "", + ] + .filter(Boolean) + .join(""); + const decl = m.declaration?.trim() ? `:${m.declaration.trim()}` : ""; + return `- ${m.name}${flags}${decl}`; + }), + ); + } else { + lines.push( + "", + "尚未编入、仍可调用:无。用户只能点图上已有节点,或对〔可反复〕原型增殖。", + ); + } lines.push( "", repeatableList.length @@ -2071,6 +2098,37 @@ export function deriveFlowStepTitle(params: { return raw; } +/** 目录里尚未编入本局、且非反复技能也未有产物的条目——用户仍可要求追加。 */ +export function listCallableCatalogModules(params: { + flow?: CreationFlow | null; + catalog?: ModuleCatalog | null; + acceptedStepIds?: readonly string[]; + filledArtifactTags?: readonly string[]; +}): CreationFlowAvailableModule[] { + const catalog = params.catalog ?? null; + if (!catalog?.modules.length) return []; + const scheduled = new Set((params.flow?.steps ?? []).map((s) => s.name)); + const filled = new Set(params.filledArtifactTags ?? []); + const accepted = new Set( + (params.acceptedStepIds ?? []).map((id) => id.trim()).filter(Boolean), + ); + const out: CreationFlowAvailableModule[] = []; + for (const mod of catalog.modules) { + if (scheduled.has(mod.name)) continue; + if (!mod.repeatable) { + if (mod.artifact && filled.has(mod.artifact)) continue; + if (accepted.has(mod.name)) continue; + } + out.push({ + name: mod.name, + ...(mod.declaration ? { declaration: mod.declaration } : {}), + ...(mod.repeatable ? { repeatable: true } : {}), + ...(mod.closer ? { closer: true } : {}), + }); + } + return out; +} + export function formatCreationFlowForUser( flow: CreationFlow, catalog?: ModuleCatalog | null, @@ -2092,10 +2150,17 @@ export function formatCreationFlowForUser( ); const filled = new Set(filledArtifactTags); const byId = new Map(normalized.steps.map((s) => [s.id, s] as const)); + const availableModules = listCallableCatalogModules({ + flow: normalized, + catalog, + acceptedStepIds, + filledArtifactTags, + }); return { brief: normalized.brief, status: normalized.status, ...(pendingSuggestions.length ? { suggestions: pendingSuggestions } : {}), + ...(availableModules.length ? { availableModules } : {}), steps: normalized.steps.map((s, i) => { const revise = isReviseStep(s); const proto = isPrototypeStep(s); diff --git a/src/skills/loader.ts b/src/skills/loader.ts index 912926b..7fca51a 100644 --- a/src/skills/loader.ts +++ b/src/skills/loader.ts @@ -503,7 +503,6 @@ export async function loadWorkerSkillWithContext( const blocks = formatDesignFlowContentBlocks({ selectedRecipe, modules, - missingSelection: !selectedRecipe, flow: parseCreationFlow(opts?.flowRaw), acceptedStepIds: opts?.acceptedStepNames, filledArtifactTags: opts?.filledArtifactTags, @@ -551,6 +550,19 @@ export async function loadWorkerSkillWithContext( const { formatPlayAgentRosterForPrompt } = await import("./play-slots.js"); rosterBlock = `${formatPlayAgentRosterForPrompt()}\n\n`; } + if (binding.module.id === "reply-format") { + const { + loadPresentShellCatalog, + formatPresentShellsForPrompt, + } = await import("./present-shell-catalog.js"); + const shells = await loadPresentShellCatalog( + skill.skillPackRoot, + skillsRoot, + ); + if (shells.length) { + rosterBlock = `${formatPresentShellsForPrompt(shells)}\n\n`; + } + } modulePromptBlock = `${rosterBlock}${paramsBlock}\n\n## 【本步方法 · ${binding.module.name}】\n\n${binding.modulePrompt.trim()}${openingNote}${inheritNote}`; const depTags = inheritTag ? binding.depTags.filter((tag) => tag !== inheritTag) diff --git a/src/skills/present-packet.ts b/src/skills/present-packet.ts index 22f927a..fd872bd 100644 --- a/src/skills/present-packet.ts +++ b/src/skills/present-packet.ts @@ -192,7 +192,8 @@ export function stripPresentSourceFences(raw: string): string { } export const PLAY_VISIBLE_BODY_INSTRUCTION = [ - "用户可见正文(present.v1 的 blocks.body,或纯 Markdown 主读)默认 **500~2000 字**(按汉字计)。", + "用户可见正文(present.v1 的 blocks.body,或纯 Markdown 主读)默认 **1000~2000 字**(按汉字计);以「设计.监控栏/回复呈现」已钉字数为准。", + "采用完整长自然段叙述,不要单句成段。", "不要写成几句气泡短信就结束,除非用户明确要求极短。", "禁止把 tag 名(如「输出.用户展示」)、压缩摘要、过程日志写进正文。", ].join("\n"); diff --git a/src/skills/present-shell-catalog.ts b/src/skills/present-shell-catalog.ts new file mode 100644 index 0000000..840e4a2 --- /dev/null +++ b/src/skills/present-shell-catalog.ts @@ -0,0 +1,116 @@ +/** + * 游玩呈现壳目录:介绍与壳规格写在 present-shells/{id}/prompt.md。 + * 正文组成执行时注入【可选呈现壳】,不在技能 prompt 里写死清单。 + */ +import { readFile } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { parse as parseYaml } from "yaml"; +import { + getModuleSection, + parseModulePromptSections, +} from "./creation-flow.js"; + +const DEFAULT_SKILLS_ROOT = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + "../../skills", +); + +export const PRESENT_SHELL_CATALOG_FILENAME = "present-shells/catalog.yaml"; + +export type PresentShellCatalogEntry = { + id: string; + name: string; + intro: string; + shell: string; +}; + +export function parsePresentShellCatalog( + raw: string, +): Array<{ id: string; name: string }> { + let doc: unknown; + try { + doc = parseYaml(raw); + } catch { + return []; + } + if (!doc || typeof doc !== "object" || Array.isArray(doc)) return []; + const shellsRaw = (doc as Record).shells; + if (!Array.isArray(shellsRaw)) return []; + const out: Array<{ id: string; name: string }> = []; + for (const item of shellsRaw) { + if (!item || typeof item !== "object" || Array.isArray(item)) continue; + const row = item as Record; + const id = typeof row.id === "string" ? row.id.trim() : ""; + const name = typeof row.name === "string" ? row.name.trim() : ""; + if (!id || !name) continue; + out.push({ id, name }); + } + return out; +} + +export async function loadPresentShellCatalog( + skillPackRoot: string, + skillsRoot = DEFAULT_SKILLS_ROOT, +): Promise { + const catalogPath = path.join( + skillsRoot, + skillPackRoot, + PRESENT_SHELL_CATALOG_FILENAME, + ); + let raw: string; + try { + raw = await readFile(catalogPath, "utf8"); + } catch { + return []; + } + const index = parsePresentShellCatalog(raw); + const out: PresentShellCatalogEntry[] = []; + for (const entry of index) { + const promptPath = path.join( + skillsRoot, + skillPackRoot, + "present-shells", + entry.id, + "prompt.md", + ); + let promptMd = ""; + try { + promptMd = await readFile(promptPath, "utf8"); + } catch { + continue; + } + const sections = parseModulePromptSections(promptMd); + const intro = getModuleSection(sections, "intro") ?? ""; + const shell = getModuleSection(sections, "shell") ?? ""; + if (!intro && !shell) continue; + out.push({ + id: entry.id, + name: entry.name, + intro, + shell, + }); + } + return out; +} + +export function formatPresentShellsForPrompt( + shells: readonly PresentShellCatalogEntry[], +): string { + const lines = [ + "## 【可选呈现壳】程序从仓库动态装载", + "", + "只从下列 id 里选一个并做微调。禁止自造目录没有的壳,禁止从零发明布局。介绍与壳规格以各壳自己的文档为准。", + "", + ]; + for (const s of shells) { + lines.push(`### \`${s.id}\` · ${s.name}`, ""); + if (s.intro) { + lines.push("介绍:", "", s.intro, ""); + } + if (s.shell) { + lines.push("壳:", "", "```", s.shell, "```", ""); + } + } + return lines.join("\n").trim(); +} diff --git a/tests/creation-flow.test.ts b/tests/creation-flow.test.ts index b4fd928..74f844e 100644 --- a/tests/creation-flow.test.ts +++ b/tests/creation-flow.test.ts @@ -9,6 +9,7 @@ import { deriveFlowStepTitle, titleFromSuggestion, formatFlowProgressForAgent, + listCallableCatalogModules, formatModuleCatalogForAgent, formatRecipeCatalogForAgent, formatSelectedRecipeForAgent, @@ -328,6 +329,11 @@ describe("creation-flow", () => { expect(view.steps[0]?.layer).toBe(0); expect(view.steps[0]?.ready).toBe(true); expect(view.steps[0]?.selectable).toBe(true); + expect(view.availableModules?.map((m) => m.name)).toEqual([ + "实现机制", + "具体实例", + "开场白与开场变量", + ]); expect(view.steps[1]?.runState).toBe("pending"); expect(view.steps[1]?.layer).toBe(1); expect(view.steps[1]?.ready).toBe(false); @@ -539,7 +545,7 @@ steps: const formatted = formatSelectedRecipeForAgent(detail); expect(formatted).toContain("用户已选配方"); expect(formatted).toContain("核心思路"); - expect(formatted).toContain("增量"); + expect(formatted).toContain("开局 steps"); const seeded = creationFlowFromRecipeSeed(detail); expect(seeded?.steps[0]?.name).toBe("美学纲领与交互范式"); @@ -598,15 +604,7 @@ recipes: ]); }); - it("injects selected director into design-flow; missing selection warns", async () => { - const missing = await loadWorkerSkillWithContext( - "world-simulator", - "design-flow", - ); - expect(missing.promptBody).toContain("用户尚未手动选择"); - expect(missing.promptBody).toContain("【能力"); - expect(missing.promptBody).toContain("禁止自行猜测"); - + it("injects selected recipe into design-flow", async () => { const selected = await loadWorkerSkillWithContext( "world-simulator", "design-flow", @@ -620,9 +618,9 @@ recipes: expect(selected.promptBody).toContain("美学纲领与交互范式"); expect(selected.promptBody).toContain("核心思路"); expect(selected.promptBody).toContain("何时用"); - expect(selected.promptBody).toContain("增量"); + expect(selected.promptBody).toContain("开局 steps"); expect(selected.promptBody).toContain("【流程进度】"); - expect(selected.promptBody).not.toContain("【导演】用户尚未手动选择"); + expect(selected.promptBody).not.toContain("用户尚未手动选择"); }); it("tells design-flow which steps are done and not to reschedule them", async () => { @@ -644,8 +642,8 @@ recipes: expect(loaded.promptBody).toContain("已完成:"); expect(loaded.promptBody).toContain("美学纲领与交互范式"); expect(loaded.promptBody).toContain("已验收"); - expect(loaded.promptBody).toContain("禁止再排新建"); - expect(loaded.promptBody).toContain("禁止排 mode=revise"); + expect(loaded.promptBody).toContain("这一面已覆盖"); + expect(loaded.promptBody).toContain("要改则用户点该节点重进"); expect(loaded.promptBody).toContain("生成规则"); }); @@ -662,8 +660,31 @@ recipes: }); expect(text).toContain("草案已有、尚未验收"); expect(text).toContain("美学纲领与交互范式"); - expect(text).toContain("不要当作新规划再写一遍"); + expect(text).toContain("保留原 id"); expect(text).toContain("目录〔可反复〕:生成规则、具体实例"); + expect(text).toContain("尚未编入、仍可调用"); + expect(text).toContain("实现机制"); + const leftoverAt = text.indexOf("尚未编入、仍可调用"); + expect(leftoverAt).toBeGreaterThan(-1); + expect(text.slice(leftoverAt)).not.toContain("美学纲领与交互范式"); + }); + + it("listCallableCatalogModules skips scheduled names and filled non-repeatable artifacts", () => { + const flow = parseCreationFlow(`{ + "steps": [ + { "name": "美学纲领与交互范式", "depends_on": [] }, + { "name": "生成规则", "role": "prototype", "depends_on": ["美学纲领与交互范式"] } + ] + }`)!; + const leftover = listCallableCatalogModules({ + flow, + catalog: sampleCatalog, + filledArtifactTags: ["设计.实现机制"], + }); + expect(leftover.map((m) => m.name)).toEqual([ + "具体实例", + "开场白与开场变量", + ]); }); it("tells design-flow to insert nodes before an unaccepted closer", () => { diff --git a/tests/declared-worker.test.ts b/tests/declared-worker.test.ts index ec2d386..e34a9bf 100644 --- a/tests/declared-worker.test.ts +++ b/tests/declared-worker.test.ts @@ -129,6 +129,6 @@ describe("buildDeclaredWorkerSkill", () => { expect(promptBody).toContain("残酷但不虐主"); expect(promptBody).toContain("主角免疫"); expect(promptBody).toContain("声明驱动"); - expect(promptBody).toContain("500~2000"); + expect(promptBody).toContain("1000~2000"); }); }); diff --git a/tests/present-shell-catalog.test.ts b/tests/present-shell-catalog.test.ts new file mode 100644 index 0000000..ff50d19 --- /dev/null +++ b/tests/present-shell-catalog.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from "vitest"; +import { + formatPresentShellsForPrompt, + loadPresentShellCatalog, + parsePresentShellCatalog, +} from "../src/skills/present-shell-catalog.js"; + +const PACK = "dialogue/world-simulator"; + +describe("present-shell catalog", () => { + it("parses catalog ids without hardcoding a count", () => { + const entries = parsePresentShellCatalog(` +shells: + - id: prose + name: 纯散文 + - id: extra_shell + name: 新壳 +`); + expect(entries.map((e) => e.id)).toEqual(["prose", "extra_shell"]); + }); + + it("loads intro and shell from each prompt.md", async () => { + const shells = await loadPresentShellCatalog(PACK); + expect(shells.length).toBeGreaterThan(0); + const ids = shells.map((s) => s.id); + expect(new Set(ids).size).toBe(ids.length); + for (const s of shells) { + expect(s.name).toBeTruthy(); + expect(s.intro).toBeTruthy(); + expect(s.shell).toContain(`id: ${s.id}`); + } + }); + + it("formats an injection block that lists loaded ids", async () => { + const shells = await loadPresentShellCatalog(PACK); + const block = formatPresentShellsForPrompt(shells); + expect(block).toContain("【可选呈现壳】"); + expect(block).toContain("动态装载"); + for (const s of shells) { + expect(block).toContain(`\`${s.id}\``); + } + }); +}); diff --git a/web/agent-ui.js b/web/agent-ui.js index efe42d5..15bfe36 100644 --- a/web/agent-ui.js +++ b/web/agent-ui.js @@ -694,9 +694,19 @@ function syncCoordRailChrome() { } } +function scrollCoordDrawerToLatest() { + const body = document.getElementById("coord-drawer-body"); + if (!body || coordRailCollapsed) return; + body.scrollTop = 0; +} + function setCoordRailCollapsed(collapsed) { + const opening = coordRailCollapsed && !collapsed; coordRailCollapsed = Boolean(collapsed); syncCoordRailChrome(); + if (opening) { + requestAnimationFrame(() => scrollCoordDrawerToLatest()); + } } function wireCoordRailChrome() { @@ -4300,6 +4310,87 @@ function wireLeaveStepControl(root, handlers) { }); } +const WORKSPACE_SKILLS_SRC = "/modules.html?embed=1"; +let workspaceSkillsOpen = false; +let workspaceSkillsWired = false; + +function isFlowWorkspace(view) { + return ( + view?.waitingReason?.kind === "pick_creation_step" || isFlowPlanReview(view) + ); +} + +function workspaceViewSwitchHtml(current) { + if (current === "skills") { + return ``; + } + return ``; +} + +function closeWorkspaceSkills() { + workspaceSkillsOpen = false; + const host = document.getElementById("workspace-skills"); + if (host) host.hidden = true; + document.body.classList.remove("workspace-skills-open"); +} + +function openWorkspaceSkills() { + ensureWorkspaceSkillsChrome(); + const host = document.getElementById("workspace-skills"); + const frame = document.getElementById("workspace-skills-frame"); + if (!host || !frame) { + window.location.href = "/modules.html"; + return; + } + if (!frame.getAttribute("src")) { + frame.setAttribute("src", WORKSPACE_SKILLS_SRC); + } + workspaceSkillsOpen = true; + host.hidden = false; + document.body.classList.add("workspace-skills-open"); + host.querySelector("[data-skills-close]")?.focus(); +} + +function ensureWorkspaceSkillsChrome() { + if (workspaceSkillsWired) return; + const host = document.getElementById("workspace-skills"); + if (!host) return; + workspaceSkillsWired = true; + host.addEventListener("click", (e) => { + if (!e.target.closest("[data-skills-close]")) return; + e.preventDefault(); + closeWorkspaceSkills(); + }); + document.addEventListener("keydown", (e) => { + if (e.key !== "Escape" || !workspaceSkillsOpen) return; + const typing = e.target?.closest?.("input, textarea, select, [contenteditable=true]"); + if (typing) return; + e.preventDefault(); + closeWorkspaceSkills(); + }); +} + +function wireWorkspaceSkillsSwitch(root) { + ensureWorkspaceSkillsChrome(); + root?.querySelectorAll("[data-open-skills]").forEach((el) => { + el.addEventListener("click", (e) => { + e.preventDefault(); + openWorkspaceSkills(); + }); + }); +} + +function syncWorkspaceSkills(view) { + ensureWorkspaceSkillsChrome(); + if (workspaceSkillsOpen && !isFlowWorkspace(view)) closeWorkspaceSkills(); +} + function proposedOutputCopy(proposed) { const params = proposed?.params; const target = @@ -4349,7 +4440,7 @@ function renderSpeakWorkspace(view) { : "保存后创作流程仍在;拆出的产物可以单独开玩、存档。"; } else if (wr?.kind === "pick_creation_step" || isFlowPlanReview(view)) { title = "选要做的节点"; - hint = "点可进入的节点即确认并开始;虚线原型点一下增殖再进去。要改排在底栏写意见再发。"; + hint = "点图上可进入的节点即开始;虚线原型点一下增殖。要看技能池点上方「技能」。要改排在底栏写意见再发。"; } else if (showOpening) { title = guide?.stepName || (moduleOpening ? "按引导先说几句" : "开局"); hint = moduleOpening @@ -4421,9 +4512,13 @@ function renderSpeakWorkspace(view) { : ""; return `
- ${ - canOfferSaveProduct(view) ? "落档" : flowInteractive ? "流程" : "说话" - } + ${ + flowInteractive + ? workspaceViewSwitchHtml("flow") + : `${ + canOfferSaveProduct(view) ? "落档" : "说话" + }` + } ${leaveStepControlHtml(view)}

${esc(title)}

@@ -4458,16 +4553,19 @@ function fillCoordRail(visible, view, handlers) { }); const traceCount = history.filter((message) => message.contextTrace).length; const packs = groupCoordTurnPacks(history); + // 侧栏是回看档案:打开先看最近一轮,往下才是更早的对话 + const ordered = [...packs].reverse(); const hiddenIds = new Set( history.filter((message) => !visibleIds.has(message.id)).map((message) => message.id), ); coordRail.hidden = false; if (drawerBody) { - drawerBody.innerHTML = packs.length - ? packs.map((pack) => renderCoordPack(pack, view, { hiddenIds })).join("") + drawerBody.innerHTML = ordered.length + ? ordered.map((pack) => renderCoordPack(pack, view, { hiddenIds })).join("") : `

暂无对话摘要

`; wireMessageFeedActions(drawerBody, handlers); wireMessageContextMenu(drawerBody, handlers); + if (!coordRailCollapsed) scrollCoordDrawerToLatest(); } if (drawerCount) { drawerCount.textContent = packs.length ? String(packs.length) : ""; @@ -4524,6 +4622,8 @@ export function renderMessageFeed(view, loading, handlers = {}) { } wireCoordRailChrome(); + ensureWorkspaceSkillsChrome(); + syncWorkspaceSkills(view); const stage = document.getElementById("workspace-stage"); const panelFeed = document.getElementById("panel-feed"); @@ -4631,6 +4731,7 @@ export function renderMessageFeed(view, loading, handlers = {}) { stage.innerHTML = renderSpeakWorkspace(view); wireCreationFlowGraph(stage, handlers); wireLeaveStepControl(stage, handlers); + wireWorkspaceSkillsSwitch(stage); stage.querySelector("[data-enter-play]")?.addEventListener("click", () => { handlers.onEnterPlay?.(); }); diff --git a/web/app.js b/web/app.js index ea07f80..b27cf26 100644 --- a/web/app.js +++ b/web/app.js @@ -52,11 +52,11 @@ const LIVE_POLL_MS = 280; const $ = (id) => document.getElementById(id); -const PHASE = { idle: "待命", running: "执行�?, waiting_user: "等待�?, done: "已完�?, error: "出错" }; +const PHASE = { idle: "待命", running: "执行中", waiting_user: "等待你", done: "已完成", error: "出错" }; /** 用户任务三态(表层);底层 waitingReason 映射进来 */ const USER_TASK = { - speak: { id: "speak", label: "说话", title: "继续�? }, + speak: { id: "speak", label: "说话", title: "继续说" }, answer: { id: "answer", label: "答题", title: "回答问题" }, review: { id: "review", label: "验收", title: "验收产物" }, }; @@ -73,15 +73,15 @@ function isPlayView(view) { } /** - * �?waitingReason 收成用户三态:说话 / 答题+自由发挥 / 批阅�? + * 把 waitingReason 收成用户三态:说话 / 答题+自由发挥 / 批阅。 * @returns {{ id: 'speak'|'answer'|'review'|'busy'|'idle'|'error', label: string, title: string, hint: string|null }} */ function resolveUserTask(view, loading) { if (loading || isAgentBusy(view, loading)) { return { id: "busy", - label: "执行�?, - title: view.focus?.action ?? "总管�?Worker 执行中�?, + label: "执行中", + title: view.focus?.action ?? "总管或 Worker 执行中…", hint: null, }; } @@ -90,18 +90,18 @@ function resolveUserTask(view, loading) { id: "speak", label: USER_TASK.speak.label, title: "说明意见", - hint: "写完发送即可�?, + hint: "写完发送即可。", }; } if (view.phase === "done") { - return { id: "idle", label: "已完�?, title: "会话已结�?, hint: null }; + return { id: "idle", label: "已完成", title: "会话已结束", hint: null }; } if (view.phase === "error") { return { id: "error", label: "出错", - title: "说明后重�?, - hint: view.hints?.[0] ?? "执行出错,可在下方重�?, + title: "说明后重试", + hint: view.hints?.[0] ?? "执行出错,可在下方重试", }; } @@ -113,28 +113,28 @@ function resolveUserTask(view, loading) { return { id: "speak", label: USER_TASK.speak.label, - title: "继续�?, - hint: "你说一句,世界推进一轮�?, + title: "继续说", + hint: "你说一句,世界推进一轮。", }; } if (canOfferSaveProduct(view)) { return { id: "speak", - label: "可保�?, + label: "可保存", title: "落档产物", hint: view.hasProduct - ? "可再保存一份新定稿,或用已有产物开玩。补节点仍点图�? - : "点「保存定稿」拆出产物。创作流程还在,之后用产物开玩�?, + ? "可再保存一份新定稿,或用已有产物开玩。补节点仍点图。" + : "点「保存定稿」拆出产物。创作流程还在,之后用产物开玩。", }; } if (isFlowPlanReview(view) || wr?.kind === "pick_creation_step") { return { id: "speak", - label: "选节�?, + label: "选节点", title: "选要做的节点", - hint: "点可进入的节点即确认并开始;要改排在底栏写意见再发�?, + hint: "点图上可进入的节点即开始。要看技能池点上方「技能」。", }; } @@ -148,14 +148,14 @@ function resolveUserTask(view, loading) { }; } - // 能力默认问题:对齐美学纲领开局 �?说话面,不进「答题�? + // 能力默认问题:对齐美学纲领开局 → 说话面,不进「答题」 if (moduleOpening) { const stepName = view.openingGuide?.stepName?.trim(); return { id: "speak", label: USER_TASK.speak.label, - title: stepName || "按引导先说几�?, - hint: "想到什么写什么,不必整齐;写完发送即可�?, + title: stepName || "按引导先说几句", + hint: "想到什么写什么,不必整齐;写完发送即可。", }; } @@ -164,7 +164,7 @@ function resolveUserTask(view, loading) { id: "answer", label: USER_TASK.answer.label, title: "回答问题", - hint: "先点选项作答;也可以在底栏自由补充�?, + hint: "先点选项作答;也可以在底栏自由补充。", }; } @@ -176,11 +176,11 @@ function resolveUserTask(view, loading) { title: proposed?.name ? proposed.mode === "revise" ? `回头修改 · ${proposed.name}` - : `接下来生�?· ${proposed.name}` - : "确认下一�?, + : `接下来生成 · ${proposed.name}` + : "确认下一步", hint: proposed ? proposedOutputCopy(proposed) - : view.focus?.detail ?? "确认执行,或说明意见�?, + : view.focus?.detail ?? "确认执行,或说明意见。", }; } @@ -188,8 +188,8 @@ function resolveUserTask(view, loading) { return { id: "speak", label: USER_TASK.speak.label, - title: "下一步想写什�?, - hint: "说说接下来想做什么;可留空,也可说回头改某步。发送后会展示下一节点�?, + title: "下一步想写什么", + hint: "说说接下来想做什么;可留空,也可说回头改某步。发送后会展示下一节点。", }; } @@ -198,7 +198,7 @@ function resolveUserTask(view, loading) { id: "speak", label: USER_TASK.speak.label, title: "说明修改意见", - hint: "写清楚要改哪里;发送后在现有产物上修改�?, + hint: "写清楚要改哪里;发送后在现有产物上修改。", }; } @@ -207,10 +207,10 @@ function resolveUserTask(view, loading) { return { id: "speak", label: USER_TASK.speak.label, - title: hasUser ? "继续补充" : "描述你想创作什�?, + title: hasUser ? "继续补充" : "描述你想创作什么", hint: hasUser - ? "继续说细节,或等信息齐后确认�? - : "用几句话说明题材、玩法或爽点即可�?, + ? "继续说细节,或等信息齐后确认。" + : "用几句话说明题材、玩法或爽点即可。", }; } @@ -218,8 +218,8 @@ function resolveUserTask(view, loading) { return { id: "speak", label: USER_TASK.speak.label, - title: "继续�?, - hint: view.hints?.[0] ?? "直接输入你的想法或补充�?, + title: "继续说", + hint: view.hints?.[0] ?? "直接输入你的想法或补充。", }; } @@ -227,7 +227,7 @@ function resolveUserTask(view, loading) { return { id: "speak", label: USER_TASK.speak.label, - title: "继续�?, + title: "继续说", hint: view.hints?.[0] ?? null, }; } @@ -273,17 +273,17 @@ function proposedOutputCopy(proposed) { : ""; if (proposed?.mode === "revise") { if (targetText) { - return `将在既有�?{targetText}」的${proposed.name}上继续改,不是从零再生成。`; + return `将在既有「${targetText}」的${proposed.name}上继续改,不是从零再生成。`; } - return `将在既有�?{proposed?.name || "该步"}」上继续改,不是从零再生成。`; + return `将在既有「${proposed?.name || "该步"}」上继续改,不是从零再生成。`; } if (targetText) { - return `将生成�?{targetText}」的${proposed.name}。`; + return `将生成「${targetText}」的${proposed.name}。`; } - return `接下来将生成�?{proposed?.name || "下一项内�?}。`; + return `接下来将生成:${proposed?.name || "下一项内容"}。`; } -/** 确认下一步:给人看「生成什么」;�?target 时顺带露出后�?id,便于改对象时同步�?*/ +/** 确认下一步:给人看「生成什么」;有 target 时顺带露出后台 id,便于改对象时同步。 */ function proposeVisibleFields(proposed) { if (proposed?.kind === "prior-artifact") return []; const missing = new Set(proposed?.paramsMissing || []); @@ -298,7 +298,7 @@ function proposeVisibleFields(proposed) { if (byKey.has("target")) { push("target"); - // 对象与后�?id 绑定:改女租客→丧尸时,rule_id 也要换成 zombies 一类英�? + // 对象与后台 id 绑定:改女租客→丧尸时,rule_id 也要换成 zombies 一类英文 if (byKey.has("rule_id")) push("rule_id"); } else if (byKey.has("rule_id") && (missing.has("rule_id") || proposed?.name === "具体实例")) { push("rule_id"); @@ -315,7 +315,7 @@ function proposeFieldLabel(field) { function proposeFieldHint(field, proposed) { if (field.key === "rule_id" && proposed?.paramSpecs?.some((s) => s.key === "target")) { - return "英文 kebab-case,须与上方对象对应;改对象时一并改(如丧尸→zombies�?; + return "英文 kebab-case,须与上方对象对应;改对象时一并改(如丧尸→zombies)"; } return field.hint || field.key; } @@ -324,7 +324,7 @@ function statusFor(view, loading) { const task = resolveUserTask(view, loading); if (task.id === "busy") return { cls: "running", text: task.title }; if (task.id === "error") return { cls: "", text: task.label }; - if (task.id === "idle" && view.phase === "done") return { cls: "done", text: "已完�? }; + if (task.id === "idle" && view.phase === "done") return { cls: "done", text: "已完成" }; if (task.id === "speak" || task.id === "answer" || task.id === "review") { return { cls: "waiting", text: task.label }; } @@ -344,7 +344,7 @@ function resolveComposer(view, loading) { return { mode: "waiting", text: task.title, task }; } if (view.phase === "done") { - return { mode: "idle", text: "会话已结�?, task }; + return { mode: "idle", text: "会话已结束", task }; } if (view.phase === "error") { const send = view.actions?.find((a) => a.type === "send_message"); @@ -353,7 +353,7 @@ function resolveComposer(view, loading) { task, taskTitle: task.title, taskHint: task.hint, - placeholder: send?.placeholder ?? "说明后重试,或直接发送继续�?, + placeholder: send?.placeholder ?? "说明后重试,或直接发送继续…", hint: null, }; } @@ -363,11 +363,11 @@ function resolveComposer(view, loading) { return { mode: "input", task, - taskTitle: task.title || "继续�?, + taskTitle: task.title || "继续说", taskHint: task.hint, - placeholder: send?.placeholder ?? "说你要做什么�?, + placeholder: send?.placeholder ?? "说你要做什么…", hint: null, - submitLabel: "发�?, + submitLabel: "发送", }; } @@ -384,7 +384,7 @@ function resolveComposer(view, loading) { intakePrompt: hasUser ? view.intakePrompt : null, showIntakePanel: hasUser, confirmIntake, - placeholder: send?.placeholder ?? "描述你想创作什么�?, + placeholder: send?.placeholder ?? "描述你想创作什么…", }; } @@ -418,7 +418,7 @@ function resolveComposer(view, loading) { mode: "action", task, taskTitle: "验收产物", - taskHint: "同意就接受;要改可先点「说明意见」�?, + taskHint: "同意就接受;要改可先点「说明意见」。", primary: accept, primaryType: "accept", hint: null, @@ -437,10 +437,10 @@ function resolveComposer(view, loading) { mode: "pick_step", task, taskTitle: "选要做的节点", - taskHint: "点可进入的节点即确认并开始;虚线原型点一下增殖。要改排在底栏写意见再发�?, - placeholder: send?.placeholder ?? "例如:补舞台骨架、把某步改到开场白之前�?, + taskHint: "点图上可进入的节点即开始;虚线原型点一下增殖。要看技能池点上方「技能」。要改排在底栏写意见再发。", + placeholder: send?.placeholder ?? "例如:补舞台骨架、把某步改到开场白之前…", hint: null, - submitLabel: "发�?, + submitLabel: "发送", requiresText: true, }; } @@ -477,9 +477,9 @@ function resolveComposer(view, loading) { task, taskTitle: task.title, taskHint: task.hint, - placeholder: send?.placeholder ?? "也可在此自由补充�?, + placeholder: send?.placeholder ?? "也可在此自由补充…", hint: null, - submitLabel: "补充并发�?, + submitLabel: "补充并发送", }; } @@ -493,27 +493,27 @@ function resolveComposer(view, loading) { composerForceInput ) { const wr = view.waitingReason; - let placeholder = send?.placeholder ?? "输入你想说的�?; - let submitLabel = "发�?; + let placeholder = send?.placeholder ?? "输入你想说的…"; + let submitLabel = "发送"; if (wr?.kind === "next_intent") { - placeholder = send?.placeholder ?? "下一步想写什么?(可留空)�?; + placeholder = send?.placeholder ?? "下一步想写什么?(可留空)…"; submitLabel = "继续"; } else if (wr?.kind === "approve_step" && composerForceInput) { placeholder = - "例如:补开局 NPC、改成丧尸怪物规则(后�?id 也换�?zombies)�?; - submitLabel = "发送意�?; + "例如:补开局 NPC、改成丧尸怪物规则(后台 id 也换成 zombies)…"; + submitLabel = "发送意见"; } else if (wr?.kind === "revision") { - placeholder = "说明要改哪里�?; - submitLabel = "按意见修�?; + placeholder = "说明要改哪里…"; + submitLabel = "按意见修改"; } else if (wr?.kind === "worker_questions" && !hasQuestionsCard) { placeholder = isModuleOpeningWaiting(view) - ? "想到什么写什么�? - : "直接回答问题�?; + ? "想到什么写什么…" + : "直接回答问题…"; } else if ( view.openingGuide?.text && !(view.messages ?? []).some((m) => m.role === "user") ) { - placeholder = "按上方引导写几句�?; + placeholder = "按上方引导写几句…"; } return { mode: "input", @@ -546,10 +546,9 @@ function resolveComposer(view, loading) { function composerModeChip(spec) { const id = spec.task?.id; - /* 说话由左�?emoji「更多」承担,不再显示文字 chip */ - if (id !== "answer" && id !== "review") return ""; + if (id !== "speak" && id !== "answer" && id !== "review") return ""; const label = spec.task.label || ""; - const tip = [spec.taskTitle, spec.taskHint].filter(Boolean).join(" �?"); + const tip = [spec.taskTitle, spec.taskHint].filter(Boolean).join(" — "); const tone = spec.acceptAction?.tone ? ` data-tone="${esc(spec.acceptAction.tone)}"` : ""; return `${esc(label)}`; } @@ -574,7 +573,7 @@ function syncThemeMenuUi() { const chromeMeta = chromeById(chromeId); const sum = $("theme-menu-sum"); if (sum) { - sum.title = `主题 · ${colorMeta.name} · ${chromeMeta.name}`; + sum.title = `${colorMeta.name} · ${chromeMeta.name}`; if (!sum.querySelector(".hamburger-icon")) { sum.innerHTML = ``; } @@ -595,7 +594,10 @@ function leaveStepButtonHtml(spec) { } function stashComposerDraftFromDom() { - if (skipComposerStash) return; + if (skipComposerStash) { + skipComposerStash = false; + return; + } const input = $("composer-input"); if (!input) return; const v = String(input.value ?? ""); @@ -617,13 +619,24 @@ function dropComposerDraft() { pendingComposerDraftSeq = 0; } -/** 发送成功前调用,避�?loading 重绘把已发内容又填回输入�?*/ function clearComposerInput() { - dropComposerDraft(); const input = $("composer-input"); if (!input) return; input.value = ""; autosizeComposerInput(input); + syncPickReplanButton(input); + refreshReviewComposerChrome(); +} + +/** 正文已提交:立刻清空底栏,且后续重绘不要把刚发出去的字再塞回来。 */ +function beginComposerSubmit() { + dropComposerDraft(); + clearComposerInput(); + skipComposerStash = true; +} + +function endComposerSubmit() { + skipComposerStash = false; } function renderComposer(view, loading) { @@ -648,7 +661,7 @@ function renderComposer(view, loading) { if (spec.mode === "waiting") { root.innerHTML = `
${esc(spec.text)} -
`; root.querySelector("[data-act=retry_run]")?.addEventListener("click", () => retryRun()); return; @@ -669,7 +682,7 @@ function renderComposer(view, loading) { : ""; const shell = composerInputShell(spec, { textareaHtml: ``, - trailing: ``, }); root.innerHTML = ` ${intakePanel} @@ -683,7 +696,7 @@ function renderComposer(view, loading) { if (spec.mode === "action") { const reject = spec.showReject - ? ` + ? ` ` : ""; const chip = composerModeChip(spec); @@ -728,23 +741,23 @@ function renderComposer(view, loading) { .join(""); const syncHint = visible.some((f) => f.key === "target") && visible.some((f) => f.key === "rule_id") - ? `

改生成对象时,后�?id 也要改成对应英文(如丧尸怪物 �?zombies)�?/p>` + ? `

改生成对象时,后台 id 也要改成对应英文(如丧尸怪物 → zombies)。

` : ""; const planHint = p.kind === "prior-artifact" ? `

${ originalTarget - ? "编排器已规划对象,步骤内可修订�? - : "具体写什么在步骤内确定�? + ? "编排器已规划对象,步骤内可修订。" + : "具体写什么在步骤内确定。" }

` : ""; const closerHint = p.closer - ? `

这是收口步。若还没�?NPC 等前序节点,点「改意见」说明要补什么,会回到流程编排�?/p>` + ? `

这是收口步。若还没做 NPC 等前序节点,点「改意见」说明要补什么,会回到流程编排。

` : ""; root.innerHTML = `
- ${p.mode === "revise" ? "回头修改" : "下一�?} + ${p.mode === "revise" ? "回头修改" : "下一步"} ${esc(p.name)}

${esc(proposedOutputCopy(p))}

@@ -755,7 +768,7 @@ function renderComposer(view, loading) {
-
`; const targetInput = root.querySelector('[data-param-key="target"]'); @@ -801,7 +814,7 @@ function renderComposer(view, loading) { originalRuleId && nextRuleId === originalRuleId ) { - alert("生成对象已改,请把后�?id 改成对应英文(例如丧尸怪物 �?zombies),不要沿用�?id�?); + alert("生成对象已改,请把后台 id 改成对应英文(例如丧尸怪物 → zombies),不要沿用旧 id。"); ruleIdInput?.focus(); markRuleIdSync(); return; @@ -824,7 +837,7 @@ function renderComposer(view, loading) { : ""; const enterPlay = canOfferEnterPlay(view) ? `` : ""; const sendCls = @@ -833,7 +846,7 @@ function renderComposer(view, loading) { : "btn btn-primary composer-btn"; const shell = composerInputShell(spec, { textareaHtml: ``, - trailing: `${saveProduct}${enterPlay}`, }); root.innerHTML = `
${shell}
`; wireComposerForm({ requiresText: true }); @@ -854,14 +867,14 @@ function renderComposer(view, loading) { acceptTone === "accept" ? " composer-btn-review" : "" }${acceptOnEmpty ? " btn-primary" : ""}" data-act="accept" title="${esc( spec.acceptAction.disabled - ? spec.acceptAction.disabledTitle || "暂不可确�? + ? spec.acceptAction.disabledTitle || "暂不可确认" : spec.acceptAction.title || spec.acceptAction.label )}" ${spec.acceptAction.disabled ? "disabled" : ""}>${esc(spec.acceptAction.label)}` : ""; - const submitLabel = spec.submitLabel || "发�?; + const submitLabel = spec.submitLabel || "发送"; const sendIsPrimary = !acceptOnEmpty; const placeholder = acceptOnEmpty - ? `${spec.placeholder || "修改意见�?}�?{spec.emptyEnterHint || "�?Enter=确�?})` + ? `${spec.placeholder || "修改意见…"}(${spec.emptyEnterHint || "空 Enter=确认"})` : spec.placeholder; const shell = composerInputShell(spec, { textareaHtml: ``, @@ -869,8 +882,8 @@ function renderComposer(view, loading) { sendIsPrimary ? " btn-primary" : "" }" data-act="revise" title="${esc( acceptOnEmpty - ? `有字或已选追问时 Enter�?{submitLabel}` - : "Enter 发�? + ? `有字或已选追问时 Enter=${submitLabel}` + : "Enter 发送" )}">${esc(submitLabel)}${acceptBtn}`, }); root.innerHTML = `
${shell}
`; @@ -887,7 +900,7 @@ function composerTextareaMaxPx(el) { return Math.min(window.innerHeight * 0.42, 360); } -/** SillyTavern 式:高度随内容上长,触顶后框内滚�?*/ +/** SillyTavern 式:高度随内容上长,触顶后框内滚动 */ function autosizeComposerInput(el) { if (!el) return; const max = composerTextareaMaxPx(el); @@ -918,7 +931,7 @@ function applyPendingComposerDraft() { refreshReviewComposerChrome(); } -/** 无输入框的确认态:Enter = 主按�?*/ +/** 无输入框的确认态:Enter = 主按钮 */ function wireComposerActionEnter(action, opts = {}) { const root = $("composer"); if (!root) return; @@ -953,8 +966,8 @@ function refreshReviewComposerChrome() { const empty = !String(input.value ?? "").trim(); const hasAnswers = selectedQuestionAnswers(lastView).answered.length > 0; input.placeholder = hasAnswers && empty - ? `${copy.placeholder}(Enter�?{copy.submitLabel})` - : `${copy.placeholder}�?{copy.emptyEnterHint})`; + ? `${copy.placeholder}(Enter=${copy.submitLabel})` + : `${copy.placeholder}(${copy.emptyEnterHint})`; } function syncDualComposerPrimary(input, acceptBtn, sendBtn) { @@ -973,7 +986,7 @@ function syncPickReplanButton(input) { btn.disabled = !hasText; btn.title = hasText ? "发送改编排意见" - : "写下意见后再发;点图上节点即确认并进�?; + : "写下意见后再发;点图上节点即确认并进入"; } function wireComposerForm(opts = {}) { @@ -1140,7 +1153,7 @@ function refreshBookMenuLabels() { const del = $("book-menu-delete"); if (del) del.textContent = n > 1 ? `删除 ${n} 项` : "删除"; const sel = $("book-menu-select"); - if (sel) sel.textContent = bookSelectMode ? "取消多�? : "多�?; + if (sel) sel.textContent = bookSelectMode ? "取消多选" : "多选"; } function showBookMenu(bookId, x, y) { @@ -1184,7 +1197,7 @@ function pathSep() { li.setAttribute("aria-hidden", "true"); const sep = document.createElement("span"); sep.className = "path-sep"; - sep.textContent = "�?; + sep.textContent = "›"; li.appendChild(sep); return li; } @@ -1317,7 +1330,7 @@ function renderExplorerRow({ if (bookId) row.dataset.bookId = bookId; if (title) row.title = title; row.innerHTML = ` - ${twistie ? `${expanded ? "�? : "�?}` : ""} + ${twistie ? `${expanded ? "▾" : "▸"}` : ""} ${esc(name)} ${meta ? `${esc(meta)}` : ""} @@ -1367,7 +1380,7 @@ function renderProductContents(book, product, list) { if (loading && saves === undefined) { const hint = document.createElement("p"); hint.className = "explorer-hint"; - hint.textContent = "加载存档�?; + hint.textContent = "加载存档…"; list.appendChild(hint); return; } @@ -1381,7 +1394,7 @@ function renderProductContents(book, product, list) { list.appendChild( renderExplorerRow({ name: "当前游玩", - meta: playHere && !activePlaySaveId ? "进行�? : "工作副本", + meta: playHere && !activePlaySaveId ? "进行中" : "工作副本", active: playHere && !activePlaySaveId, onClick: () => void openCurrentPlay(book.id), }), @@ -1391,7 +1404,7 @@ function renderProductContents(book, product, list) { if (!runs.length && !hasWorking) { const hint = document.createElement("p"); hint.className = "explorer-hint"; - hint.textContent = "还没有游玩存�?; + hint.textContent = "还没有游玩存档"; list.appendChild(hint); } @@ -1424,7 +1437,7 @@ function renderBookContents(book, list) { list.appendChild( renderExplorerRow({ name: "继续创作", - meta: designing ? "进行�? : "", + meta: designing ? "进行中" : "", active: designing, onClick: () => void openBookDesign(book.id), }), @@ -1435,7 +1448,7 @@ function renderBookContents(book, list) { if (loading && saves === undefined) { const hint = document.createElement("p"); hint.className = "explorer-hint"; - hint.textContent = "加载存档�?; + hint.textContent = "加载存档…"; list.appendChild(hint); return; } @@ -1445,8 +1458,8 @@ function renderBookContents(book, list) { const hint = document.createElement("p"); hint.className = "explorer-hint"; hint.textContent = bookPlayReady(book.id) - ? "还没有定稿。可在更多菜单里保存定稿�? - : "验收后可保存定稿�?; + ? "还没有定稿。可在更多菜单里保存定稿。" + : "验收后可保存定稿。"; list.appendChild(hint); return; } @@ -1460,13 +1473,13 @@ function renderBookContents(book, list) { for (const product of products) { const bits = []; - if (product.id === latestId) bits.push("最�?); - if (playingInstanceId === product.id) bits.push("游玩�?); + if (product.id === latestId) bits.push("最新"); + if (playingInstanceId === product.id) bits.push("游玩中"); list.appendChild( renderExplorerRow({ name: product.label, meta: bits.join(" · "), - title: "打开定稿,双击改�?, + title: "打开定稿,双击改名", onClick: () => navigateToProduct(book.id, product.id), onRename: () => void renamePlaySave(book.id, product.id, product.label), onDelete: () => void deletePlaySave(book.id, product.id, product.label, "定稿"), @@ -1502,7 +1515,7 @@ function renderBookList() { if (loading) { const hint = document.createElement("p"); hint.className = "explorer-hint"; - hint.textContent = "加载存档�?; + hint.textContent = "加载存档…"; list.appendChild(hint); return; } @@ -1611,7 +1624,7 @@ async function deleteSelectedBooks() { if (!ids.length) return; const label = ids.length === 1 - ? `�?{books.find((b) => b.id === ids[0])?.title ?? "该作�?}」` + ? `「${books.find((b) => b.id === ids[0])?.title ?? "该作品"}」` : `${ids.length} 个作品`; if (!confirm(`删除 ${label}?不可恢复。`)) return; try { @@ -1741,7 +1754,7 @@ async function renamePlaySave(bookId, saveId, currentLabel) { } async function deletePlaySave(bookId, saveId, label, kindLabel = "游玩存档") { - if (!confirm(`删除${kindLabel}�?{label}」?`)) return; + if (!confirm(`删除${kindLabel}「${label}」?`)) return; try { await api( `/api/books/${encodeURIComponent(bookId)}/saves/${encodeURIComponent(saveId)}`, @@ -1761,7 +1774,7 @@ async function deletePlaySave(bookId, saveId, label, kindLabel = "游玩存档") async function startNewPlayForBook(bookId, instanceId) { const thisView = lastView?.bookId === bookId ? lastView : null; if (!bookPlayReady(bookId) && !thisView?.hasProduct && !canOfferEnterPlay(thisView)) { - alert("请先保存产物,或完成收口后再开�?); + alert("请先保存产物,或完成收口后再开玩"); return; } try { @@ -1830,7 +1843,7 @@ async function openCurrentPlay(bookId) { function renderHeader(view, loading) { const st = statusFor(view, loading); - const title = view.bookTitle ?? "未命名作�?; + const title = view.bookTitle ?? "未命名作品"; document.title = `${title} · Writing Agent`; $("status-dot").className = `status-dot ${st.cls}`; $("status-text").textContent = st.text; @@ -1855,13 +1868,15 @@ function closeWorkspace({ emptyCopy = "" } = {}) { composerForceInput = false; document.title = "Writing Agent"; $("status-dot").className = "status-dot"; - $("status-text").textContent = "�?; + $("status-text").textContent = "—"; const btnPlay = $("btn-save-play"); if (btnPlay) btnPlay.hidden = true; const btnInst = $("btn-save-instance"); if (btnInst) btnInst.hidden = true; const btnExport = $("btn-export"); if (btnExport) btnExport.disabled = true; + const toggle = $("lifecycle-toggle"); + if (toggle) toggle.hidden = true; $("message-feed").innerHTML = emptyCopy ? `

${emptyCopy}

` : ""; const stage = $("workspace-stage"); if (stage) { @@ -1894,7 +1909,7 @@ function closeWorkspace({ emptyCopy = "" } = {}) { hideBookMenu(); document.body.dataset.lifecycle = "design"; const composerMain = $("composer-main"); - if (composerMain) composerMain.innerHTML = `
暂无打开的作�?/div>`; + if (composerMain) composerMain.innerHTML = `
暂无打开的作品
`; } function renderEmpty() { @@ -2032,7 +2047,7 @@ async function messageAction(kind, messageId, body = {}) { } } -/** 询问卡已选中的追问作答(不要求卡仍标 is-open;未选则为空�?*/ +/** 询问卡已选中的追问作答(不要求卡仍标 is-open;未选则为空) */ function selectedQuestionAnswers(view) { const qHost = $("questions-card-host"); const activeQs = getActiveQuestions(view); @@ -2046,11 +2061,11 @@ function selectedQuestionAnswers(view) { return { collected, answered }; } -/** �?Enter=接受;有字或已选追问则按意见改。点「按意见修改」不走这条�?*/ +/** 空 Enter=接受;有字或已选追问则按意见改。点「按意见修改」不走这条。 */ async function submitComposer(text, { acceptOnEmpty, requiresText } = {}) { const trimmed = String(text ?? "").trim(); if (requiresText && !trimmed) { - alert("点图上节点即确认并进入;要改编排请先写下意见�?); + alert("点图上节点即确认并进入;要改编排请先写下意见。"); return; } if (acceptOnEmpty && !trimmed) { @@ -2077,20 +2092,20 @@ async function sendText(text) { activeQs?.questions?.length && qHost?.classList.contains("is-open"), ); - // 能力默认问题:对齐美学纲领,须自由书写,不能空发/跳过当答�? + // 能力默认问题:对齐美学纲领,须自由书写,不能空发/跳过当答复 if (isModuleOpeningWaiting(lastView) && !trimmed) { - alert("请先按主栏引导写几句再发送�?); + alert("请先按主栏引导写几句再发送。"); return; } - // 核对/验收:有选中追问或修改意�?�?写回产物;点「按意见修改」绝不等于接�? + // 核对/验收:有选中追问或修改意见 ⇒ 写回产物;点「按意见修改」绝不等于接受 if (reviewing) { const { collected, answered } = selectedQuestionAnswers(lastView); if (!trimmed && answered.length === 0) { alert( isFlowPlanReview(lastView) - ? "点图上节点即确认并进入;要改编排请先写下意见�? - : "请选择追问选项或填写修改意见;满意请点「接受」收下产物�?, + ? "点图上节点即确认并进入;要改编排请先写下意见。" + : "请选择追问选项或填写修改意见;满意请点「接受」收下产物。", ); return; } @@ -2100,7 +2115,7 @@ async function sendText(text) { body.answers = collected.answers; } clearQuestionCardState(qHost, lastView); - clearComposerInput(); + beginComposerSubmit(); renderSession(lastView, true); const view = await api(`/api/sessions/${encodeURIComponent(sessionId)}/messages`, { method: "POST", @@ -2111,9 +2126,11 @@ async function sendText(text) { renderSession(view, false); } catch (err) { if (isStaleUiRequest(seq)) return; - if (trimmed) keepComposerDraft(trimmed); + keepComposerDraft(trimmed); if (qHost) qHost._qDismissed = null; if (lastView) renderSession({ ...lastView, hints: [err.message] }, false); + } finally { + endComposerSubmit(); } return; } @@ -2123,7 +2140,7 @@ async function sendText(text) { const answered = collected.ok ? collected.answers.filter((a) => a.text && a.text !== "(未答)") : []; - // 必答题未选:拦住发�? + // 必答题未选:拦住发送 if (!collected.ok && !activeQs.optional) { if (typeof collected.page === "number" && qHost._qState) { qHost._qState.page = collected.page; @@ -2134,11 +2151,11 @@ async function sendText(text) { alert(collected.error); return; } - // 有选中 �?�?答拼接发送,并收起卡 + // 有选中 → 问+答拼接发送,并收起卡 if (collected.ok && answered.length) { try { clearQuestionCardState(qHost, lastView); - clearComposerInput(); + beginComposerSubmit(); renderSession(lastView, true); const body = { answers: collected.answers }; if (trimmed) body.note = trimmed; @@ -2151,16 +2168,23 @@ async function sendText(text) { renderSession(view, false); } catch (err) { if (isStaleUiRequest(seq)) return; - if (trimmed) keepComposerDraft(trimmed); + keepComposerDraft(trimmed); if (qHost) qHost._qDismissed = null; if (lastView) renderSession({ ...lastView, hints: [err.message] }, false); + } finally { + endComposerSubmit(); } return; } - // 未选中:不带问;点发送仍算答�?�?收起�? + // 未选中:不带问;点发送仍算答复 → 收起卡 if (!trimmed) { clearQuestionCardState(qHost, lastView); - await runAction("skip_questions"); + beginComposerSubmit(); + try { + await runAction("skip_questions"); + } finally { + endComposerSubmit(); + } return; } clearQuestionCardState(qHost, lastView); @@ -2171,7 +2195,7 @@ async function sendText(text) { lastView?.waitingReason?.kind === "pick_creation_step" || isFlowPlanReview(lastView) ) { - alert("点图上节点即确认并进入;要改编排请先写下意见�?); + alert("点图上节点即确认并进入;要改编排请先写下意见。"); return; } if ( @@ -2179,7 +2203,7 @@ async function sendText(text) { resolveComposer(lastView, false)?.allowEmpty ) { try { - clearComposerInput(); + beginComposerSubmit(); renderSession(lastView, true); const view = await api(`/api/sessions/${encodeURIComponent(sessionId)}/messages`, { method: "POST", @@ -2191,12 +2215,14 @@ async function sendText(text) { } catch (err) { if (isStaleUiRequest(seq)) return; if (lastView) renderSession({ ...lastView, hints: [err.message] }, false); + } finally { + endComposerSubmit(); } } return; } try { - clearComposerInput(); + beginComposerSubmit(); renderSession(lastView, true); const view = await api(`/api/sessions/${encodeURIComponent(sessionId)}/messages`, { method: "POST", @@ -2210,6 +2236,8 @@ async function sendText(text) { keepComposerDraft(trimmed); if (cardOpen && qHost) qHost._qDismissed = null; if (lastView) renderSession({ ...lastView, hints: [err.message] }, false); + } finally { + endComposerSubmit(); } } @@ -2273,7 +2301,7 @@ async function setLifecycle(stage) { } } if (stage === "play" && !lastView?.playReady && !canOfferEnterPlay(lastView) && !lastView?.hasProduct) { - alert("请先保存产物,或完成收口后再开�?); + alert("请先保存产物,或完成收口后再开玩"); return; } try { @@ -2315,7 +2343,7 @@ async function populateDirectorSelect() { sel.innerHTML = ``; if (desc) { desc.hidden = false; - desc.textContent = "尚未配置配方选项(recipes/catalog.yaml)�?; + desc.textContent = "尚未配置配方选项(recipes/catalog.yaml)。"; } return; } @@ -2348,7 +2376,7 @@ async function populateDirectorSelect() { } async function createBook() { - const title = $("input-book-title").value.trim() || "未命名作�?; + const title = $("input-book-title").value.trim() || "未命名作品"; const recipeId = $("select-director")?.value?.trim(); if (!recipeId) { alert("请选择配方"); @@ -2401,7 +2429,7 @@ async function openBook(bookId) { async function deleteBookById(bookId) { const book = books.find((b) => b.id === bookId); if (!book) return; - if (!confirm(`删除�?{book.title}」?不可恢复。`)) return; + if (!confirm(`删除「${book.title}」?不可恢复。`)) return; try { await api(`/api/books/${encodeURIComponent(bookId)}`, { method: "DELETE" }); books = books.filter((b) => b.id !== bookId); @@ -2422,7 +2450,7 @@ async function deleteBookById(bookId) { } async function saveCurrentPlay() { - if (!activeBookId || !lastView?.playReady) return alert("须先验收 Worker �?); + if (!activeBookId || !lastView?.playReady) return alert("须先验收 Worker 集"); if (lastView.lifecycleStage !== "play" || !lastView.playLayerActive) { return alert("请先进入游玩"); } @@ -2449,7 +2477,7 @@ function defaultArchiveLabel() { async function saveCurrentInstance() { if (!activeBookId || (!lastView?.playReady && !canOfferSaveProduct(lastView))) { - return alert("须先完成收口或验�?Worker �?); + return alert("须先完成收口或验收 Worker 集"); } const label = prompt("落档名称", defaultArchiveLabel()); if (!label?.trim()) return; @@ -2568,6 +2596,11 @@ function exportSession() { downloadMarkdown(`${name}.md`, sessionToMarkdown(lastView)); } +$("lifecycle-toggle")?.addEventListener("click", (e) => { + const stage = e.target.closest("[data-stage]")?.getAttribute("data-stage"); + if (stage === "play") enterPlayNow(); + else if (stage === "design") void setLifecycle("design"); +}); $("btn-new-book")?.addEventListener("click", openNewBookDialog); $("btn-cancel-new")?.addEventListener("click", () => $("dialog-new-book").close()); $("book-action-menu")?.addEventListener("click", (e) => { diff --git a/web/index.html b/web/index.html index d78683d..a9c227b 100644 --- a/web/index.html +++ b/web/index.html @@ -145,6 +145,19 @@
+
diff --git a/web/shells.js b/web/shells.js index 1bca6ce..b952a80 100644 --- a/web/shells.js +++ b/web/shells.js @@ -1,6 +1,6 @@ /** * 呈现壳预览:主工作面 = 壳画布。 - * 按「要同时看见什么」选壳;正文按 500~2000 字撑高滚动。 + * 按「要同时看见什么」选壳;正文按 1000~2000 字撑高滚动。 */ import { PRESENT_SHELL_IDS, diff --git a/web/styles.css b/web/styles.css index 47f1632..0cd7661 100644 --- a/web/styles.css +++ b/web/styles.css @@ -450,6 +450,7 @@ body.design-workspace.coord-rail-collapsed .main-body { min-height: 0; min-width: 0; overflow: hidden; + position: relative; } /* 验收态:协调流收窄,产物占主工作面 */ @@ -952,6 +953,9 @@ body.design-workspace .review-worker-set { margin-bottom: 8px; max-width: 46rem; } +.workspace-intent-head:has(.workspace-view-switch) { + align-items: center; +} .workspace-intent-head .workspace-surface-kicker { margin-bottom: 0; } @@ -1134,6 +1138,78 @@ body.design-workspace .flow-status { font-size: 12px; color: var(--muted); } +.workspace-view-switch { + display: inline-flex; + align-items: stretch; + border: 1px solid var(--border); + border-radius: 7px; + overflow: hidden; + background: var(--bg); + flex-shrink: 0; +} +.workspace-view-switch a, +.workspace-view-switch button, +.workspace-view-switch span { + appearance: none; + display: inline-flex; + align-items: center; + margin: 0; + padding: 4px 11px; + border: none; + border-radius: 0; + background: transparent; + color: var(--muted); + font: inherit; + font-size: 12px; + font-weight: 650; + line-height: 1.2; + text-decoration: none; + cursor: pointer; +} +.workspace-view-switch span.is-current { + cursor: default; + color: var(--text); + background: var(--surface); +} +.workspace-view-switch a:hover, +.workspace-view-switch button:hover { + color: var(--text); + background: color-mix(in srgb, var(--accent) 8%, var(--surface)); +} +.workspace-view-switch a:focus-visible, +.workspace-view-switch button:focus-visible { + outline: 2px solid var(--accent); + outline-offset: -2px; +} +.workspace-skills { + position: absolute; + inset: 0; + z-index: 8; + display: flex; + flex-direction: column; + min-height: 0; + background: var(--bg); +} +.workspace-skills[hidden] { + display: none !important; +} +.workspace-skills-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + flex: 0 0 auto; + padding: 12px var(--workspace-pad-x, 24px); + border-bottom: 1px solid var(--border); + background: var(--surface); +} +.workspace-skills-frame { + flex: 1 1 auto; + width: 100%; + min-height: 0; + border: 0; + background: var(--bg); +} body.design-workspace .flow-dag { position: relative; overflow: auto; @@ -4941,7 +5017,7 @@ body.design-workspace .af-mosaic { .dialog-head-row { display: flex; justify-content: space-between; align-items: center; } /* —— 游玩呈现壳 present.v1 —— - * 主工作面 = body(随 500~2000 字撑高)。 + * 主工作面 = body(随 1000~2000 字撑高)。 * 视觉:少盒子、少渐变;层级靠字号/间距/对比,不靠装饰抢注意力。 */ .present-shell { @@ -5012,7 +5088,7 @@ body.design-workspace .af-mosaic { .present-region-body > p:last-child { margin-bottom: 0; } -/* P0:正文舞台 —— 随字数伸展(500~2000 靠外层滚动,不塞进小框) */ +/* P0:正文舞台 —— 随字数伸展(1000~2000 靠外层滚动,不塞进小框) */ .present-stage { flex: 1 1 auto; min-height: 0;