完善配方驱动的创作编排

为可重复技能补充参数校验与展示,统一配方、编排器和执行单元术语。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
moran
2026-07-30 17:59:20 +08:00
parent e670a5129c
commit 6392af54b4
49 changed files with 1671 additions and 626 deletions

View File

@@ -2,9 +2,9 @@
## 1. 文档定位 ## 1. 文档定位
本文档描述**系统级运行内核**:模块边界、创作定义与运行实例如何分离、总管 / Worker / Skill / 上下文如何协作、数据如何持久化,以及外部项目按层借鉴的原则。 本文档描述**系统级运行内核**:模块边界、创作定义与运行实例如何分离、编排器 / 执行单元 / Skill / 上下文如何协作、数据如何持久化,以及外部项目按层借鉴的原则。
本文档**不**设计具体剧本 Skill 的提示词、步骤或字段。剧本与创作方法见独立文档(如 `design-orchestrator-guide.md`Skill 包格式见 `skill-format.md` 系列。 本文档**不**设计具体技能包的提示词、步骤或字段。工作流计划与创作方法见独立文档(如 `design-orchestrator-guide.md`Skill 包格式见 `skill-format.md` 系列。
--- ---
@@ -14,7 +14,7 @@
这些模式共享同一运行内核,区别来自: 这些模式共享同一运行内核,区别来自:
- 装载哪些 Skill / 能 - 装载哪些 Skill / 能包
- 实例规格Worker 声明)如何配置 - 实例规格Worker 声明)如何配置
- 上下文如何按契约编译 - 上下文如何按契约编译
- 对状态读写实施什么权限 - 对状态读写实施什么权限
@@ -36,13 +36,13 @@
语义上:`instance` 快照 ≈ 已发布的规格版本;`run` 快照 ≈ 运行过程存档。正式 `DefinitionVersion` 发布与迁移协议在现有快照之上增量补齐,不另起一套推倒重写。 语义上:`instance` 快照 ≈ 已发布的规格版本;`run` 快照 ≈ 运行过程存档。正式 `DefinitionVersion` 发布与迁移协议在现有快照之上增量补齐,不另起一套推倒重写。
### 3.2 总管只负责任务调配 ### 3.2 编排器只负责任务调配
总管 AgentMain Agent负责判断目标是否完成、决定下一项任务、选择 Worker、必要时询问用户或结束。 编排器Main Agent负责判断目标是否完成、决定下一项任务、选择 Worker、必要时询问用户或结束。
总管**不**负责:直接创作最终正文、临场拼接完整上下文、绕过权限读私有信息、直接改正式状态、同时兼创作与评测、把隐藏推理写入长期状态。 编排器**不**负责:直接创作最终正文、临场拼接完整上下文、绕过权限读私有信息、直接改正式状态、同时兼创作与评测、把隐藏推理写入长期状态。
任务所需信息由总管**声明意图**(如 invoke 哪个 worker真正发给 Worker 的上下文由 Runtime 的上下文编译器按 Skill / 声明契约生成。 任务所需信息由编排器**声明意图**(如 invoke 哪个 worker真正发给 Worker 的上下文由 Runtime 的上下文编译器按 Skill / 声明契约生成。
### 3.3 Agent 决策与程序控制分离 ### 3.3 Agent 决策与程序控制分离
@@ -59,7 +59,7 @@
「下一步 invoke 哪个 skill」由 agent tool loop 决定。 「下一步 invoke 哪个 skill」由 agent tool loop 决定。
**5 相位阶段机**`idle` / `running` / `waiting_user` / `done` / `error`)是并发与权限模型——谁可动、何时等用户、产物何时算事实——**不是**流水线剧本。详见 `runtime-state-machine.md``tool-contracts.md` **5 相位阶段机**`idle` / `running` / `waiting_user` / `done` / `error`)是并发与权限模型——谁可动、何时等用户、产物何时算事实——**不是**流水线计划。详见 `runtime-state-machine.md``tool-contracts.md`
确定性后台流程(导入导出、索引、迁移、批量评测)可用固定步骤;整场 AIRP / 小说创作流程不固化为完整 DAG。 确定性后台流程(导入导出、索引、迁移、批量评测)可用固定步骤;整场 AIRP / 小说创作流程不固化为完整 DAG。
@@ -97,7 +97,7 @@
合成边界: 合成边界:
> Book/规格描述可以运行什么Session/快照保存实际发生了什么,相位机决定谁可动,总管决定下一步 invoke 谁Context Compiler 决定 Worker 看见什么Runtime 决定哪些修改正式生效。剧本 Skill 是可装载能力,不是系统固定流水线。 > Book/规格描述可以运行什么Session/快照保存实际发生了什么,相位机决定谁可动,编排器决定下一步 invoke 谁Context Compiler 决定执行单元看见什么Runtime 决定哪些修改正式生效。技能包是可装载能力,不是系统固定流水线。
--- ---
@@ -125,7 +125,7 @@
### 5.4 Phase RuntimeDynamic Scheduler 的具体形态) ### 5.4 Phase RuntimeDynamic Scheduler 的具体形态)
执行总管决定并维护相位边界: 执行编排器决定并维护相位边界:
1. 校验 Worker id ∈ 声明 1. 校验 Worker id ∈ 声明
2. 编译上下文 2. 编译上下文
@@ -147,7 +147,7 @@
- **包 / Orchestrator manifest**:能力发现、验收与进 play 门槛 - **包 / Orchestrator manifest**:能力发现、验收与进 play 门槛
- **Worker 契约**:声明驱动的输入输出、上下文段、工具边界 - **Worker 契约**:声明驱动的输入输出、上下文段、工具边界
注册、加载、版本与磁盘格式见 Skill 系列文档;**具体剧本步骤不在本文**。 注册、加载、版本与磁盘格式见 Skill 系列文档;**具体工作流计划步骤不在本文**。
### 5.7 Context Compiler ### 5.7 Context Compiler
@@ -192,7 +192,7 @@ Worker 不直接改「当前事实」。路径:输出 → 声明/schema 校验
## 7. 信息隔离 ## 7. 信息隔离
隔离由 Runtime 强制Worker 只看到契约允许的 tag / 段。多角色模拟时,角色 Worker 不得看到他角私有记忆、未公开事件、总管隐藏调度信息。 隔离由 Runtime 强制Worker 只看到契约允许的 tag / 段。多角色模拟时,角色 Worker 不得看到他角私有记忆、未公开事件、编排器隐藏调度信息。
Context Trace 是排查泄漏的主工具(契约已定,实现渐进)。 Context Trace 是排查泄漏的主工具(契约已定,实现渐进)。
@@ -206,7 +206,7 @@ Context Trace 是排查泄漏的主工具(契约已定,实现渐进)。
| Agent Runtime | 自研main-agent、phase-runtime、llm | 领域对象不绑定外部 Agent 框架内部类型Mastra 等仅可作按层参考或远期适配 | | Agent Runtime | 自研main-agent、phase-runtime、llm | 领域对象不绑定外部 Agent 框架内部类型Mastra 等仅可作按层参考或远期适配 |
| 前端 | `web/` + Electron | 不强制 Next.js / assistant-ui可借鉴交互模式 | | 前端 | `web/` + Electron | 不强制 Next.js / assistant-ui可借鉴交互模式 |
| 存储 | 文件系统 Book JSON | SQLite/Drizzle 非近端前提 | | 存储 | 文件系统 Book JSON | SQLite/Drizzle 非近端前提 |
| Skill | `skills/` + registry | 包内剧本与系统内核分离 | | Skill | `skills/` + registry | 包内工作流计划与系统内核分离 |
外部仓库按模块借鉴,见 `references.md`;许可证见仓库根 `THIRD_PARTY_NOTICES.md` 外部仓库按模块借鉴,见 `references.md`;许可证见仓库根 `THIRD_PARTY_NOTICES.md`
@@ -216,24 +216,26 @@ Context Trace 是排查泄漏的主工具(契约已定,实现渐进)。
| 规划用语(抽象) | 本仓库用语(实现) | | 规划用语(抽象) | 本仓库用语(实现) |
|------------------|-------------------| |------------------|-------------------|
| CreationDefinition / DefinitionVersion | `设计.worker集` 截面;`instance` / `opening` 快照 | | CreationDefinition / DefinitionVersion / 运行规格 | `设计.worker集` 截面;`instance` / `opening` 快照 |
| RunInstance | Book + Session + 黑板 + `run` 快照 | | RunInstance / 运行实例 | Book + Session + 黑板 + `run` 快照 |
| 导演 Skill / 能力包 | `orchestrator.md`UI 可选registry 一项) | | Recipe / 配方 | `recipes/`UI 选一层);黑板 `创作.选用配方` |
| 剧本层(动态) | 对话谈成的 Worker 集 + play 期 tool loop 调度(非死板选单) | | Orchestrator / 编排器 | Main Agenttool loop+ `orchestrator.md` manifest |
| Supervisor | Main Agenttool loop | | Workflow Plan / 工作流计划 | `设计.创作流程`(增量 DAG非死板选单 |
| Skill / 技能 | `modules/` 工序池 |
| Worker / 执行单元 | 一次 `run_worker` invoke |
| Dynamic Scheduler | Phase Machine + Phase Runtime | | Dynamic Scheduler | Phase Machine + Phase Runtime |
| Worker Factory | `run_worker` → 声明校验 → executor | | Worker Factory | `run_worker` → 声明校验 → executor |
| Context Compiler | `assembleWorkerContext` / contextSegments | | Context Compiler | `assembleWorkerContext` / contextSegments |
| Blackboard | tag 黑板(`BlackboardItem` | | Blackboard | tag 黑板(`BlackboardItem` |
| Commit Layer | 写入校验、表 rev 合并、acceptance | | Commit Layer / 人工审批 | 写入校验、表 rev 合并、acceptance |
| Skill Registry | `skills/` loader + orchestrator manifest | | Skill Registry | `skills/` loader + orchestrator manifest |
用户可见中文口径(禁止裸露内部 id`ui-glossary.md` 用户可见中文口径(禁止裸露内部 id`ui-glossary.md`
| 词 | 含义 | | 词 | 含义 |
|----|------| |----|------|
| **Worker 声明** | accept 后的 `设计.worker集` | | **Worker 声明 / 运行规格** | accept 后的 `设计.worker集` |
| **worker** | 一次 `run_worker` invoke | | **worker / 执行单元** | 一次 `run_worker` invoke |
| **stage** | `design``play``done`(创作 → 游玩 → 已完成) | | **stage** | `design``play``done`(创作 → 游玩 → 已完成) |
| **phase** | `idle` \| `running` \| `waiting_user` \| `done` \| `error` | | **phase** | `idle` \| `running` \| `waiting_user` \| `done` \| `error` |
@@ -251,19 +253,20 @@ Context Trace 是排查泄漏的主工具(契约已定,实现渐进)。
| **产品体验路线** | **`px-roadmap.md`**PX0PX5 交付与 DoD | | **产品体验路线** | **`px-roadmap.md`**PX0PX5 交付与 DoD |
| **日常场景 → P0** | **`daily-use-p0.md`**场景、功能表、P0 工作包) | | **日常场景 → P0** | **`daily-use-p0.md`**场景、功能表、P0 工作包) |
| 外部参考 | `references.md` | | 外部参考 | `references.md` |
| **剧本 / 创作方法(非系统架构)** | `design-orchestrator-guide.md``creation-playbook.md` | | **工作流计划 / 创作方法(非系统架构)** | `design-orchestrator-guide.md``creation-playbook.md``world-simulator-modules.md` |
| **Skill 包格式(非系统架构)** | `skill-format.md``orchestrator-skill-format.md``worker-skill-format.md``skill-design-guide.md``preset-format.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` |
--- ---
## 11. 在现有内核上补齐(路线) ## 11. 在现有内核上补齐(路线)
已具备相位机、Agent tool loop、Skill loader、design-intake、Worker 声明、上下文拼装、表 rev、Web UI、快照 API。 已具备相位机、Agent tool loop、Skill loader、design-flow/stepmodules/recipes、Worker 声明、上下文拼装、表 rev、Web UI、快照 API。
1. **PX0**导演选择 UIAIRP + 长文/爽文主路径;**存档/续作硬稳定**剧本层保持动态 1. **PX0**配方选择 UIAIRP + 长文/爽文主路径;**存档/续作硬稳定**工作流计划保持动态
2. **PX1PX2**:创作/游玩体验(可抄 UI副作用与多 run 线 2. **PX1PX2**:创作/游玩体验(可抄 UI副作用与多 run 线
3. **PX3**Context Trace、调度预算、规格钉版本、E2E 3. **PX3**Context Trace、调度预算、规格钉版本、E2E
4. **PX4PX5**:长文加深;隔离模拟 + 调试(新方法边界可用新导演包 4. **PX4PX5**:长文加深;隔离模拟 + 调试(新方法边界可用新配方
5. SQLite / 框架适配仅当痛点单开,不插入 PX0 关键路径 5. SQLite / 框架适配仅当痛点单开,不插入 PX0 关键路径
权威表:[`px-roadmap.md`](./px-roadmap.md)。 权威表:[`px-roadmap.md`](./px-roadmap.md)。
@@ -286,16 +289,16 @@ Context Trace 是排查泄漏的主工具(契约已定,实现渐进)。
```text ```text
✅ phase-machine、phase-runtime、skills loader ✅ phase-machine、phase-runtime、skills loader
✅ design-intake + Worker 声明校验 ✅ design-flow / design-step + modules/recipes + Worker 声明校验
✅ 声明驱动 worker 执行 + acceptance ✅ 声明驱动 worker 执行 + acceptance
✅ 表字段格 rev 合并 ✅ 表字段格 rev 合并
✅ Book session / run-snapshots / message branch ✅ Book session / run-snapshots / message branch
导演选择 UI新建作品instance/run 存档人话 kind 配方选择 UI新建作品instance/run 存档人话 kind
✅ 长文模板 outline / chapter-writer引导覆盖爽文/分段 ✅ 长文模板 outline / chapter-writer引导覆盖爽文/分段
✅ 失败/revision/error 出口;黑板用户手改 API ✅ 失败/revision/error 出口;黑板用户手改 API
Context Trace 🟡 Context Trace(有基础 trace UI编译器装载检查未齐
⬜ 规格版本发布与迁移协议 ⬜ 规格版本发布与迁移协议
⬜ 调度嵌套 / 重复任务 / Token 预算补齐 ⬜ 调度嵌套 / 重复任务 / Token 预算补齐
边沿副作用完整调度器 🟡 边沿副作用(有 table-side-effects完整可观测 fixture 未齐)
⬜ 标准 fixture E2E双线黄金路径自动化 ⬜ 标准 fixture E2E双线黄金路径自动化
``` ```

View File

@@ -1,5 +1,9 @@
# Book 存储模型 # Book 存储模型
> **状态:目标愿景(未完全实现)。**
> **现行实现**以 `src/types/book.ts`、`src/book/store.ts`、`src/types/book-session.ts` 与 [`run-snapshot.md`](./run-snapshot.md) 为准(扁平 `books/{id}.json` + `session.json` + run/instance 快照)。
> 下文 CardBook / PlayBook / designTrace 等为远期形态,**不要**按本文当当前磁盘契约写代码。
## 1. 定位 ## 1. 定位
Book = **长期项目容器**。Session = 一次打开的运行进程。黑板 = Session 内运行时 tag。 Book = **长期项目容器**。Session = 一次打开的运行进程。黑板 = Session 内运行时 tag。

View File

@@ -1,11 +1,11 @@
# 能撰写交接简报(泛用) # 能撰写交接简报(泛用)
> **用途**:把本文**整份**交给另一 AI / 作者,用于撰写任意【能】的 `modules/{id}/prompt.md`。 > **用途**:把本文**整份**交给另一 AI / 作者,用于撰写任意【能】的 `modules/{id}/prompt.md`。
> **本文是自洽规范**:不依赖读者已熟悉本仓库。 > **本文是自洽规范**:不依赖读者已熟悉本仓库。
> **不要**让撰写方改程序代码;**不要**只写某一能的特例而不遵守通用格式。 > **不要**让撰写方改程序代码;**不要**只写某一能的特例而不遵守通用格式。
范例(深度与结构对齐):`skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md` 范例(深度与结构对齐):`skills/dialogue/world-simulator/modules/aesthetics-interaction/prompt.md`
池清单(选题用):`docs/world-simulator-modules.md` 能池清单(选题用):`docs/world-simulator-modules.md`
术语权威:`docs/ui-glossary.md` §0 术语权威:`docs/ui-glossary.md` §0
--- ---
@@ -14,91 +14,93 @@
## 1.1 一句话 ## 1.1 一句话
**writing-agent** 是本地运行的多 Agent **文本创作 / 游玩**系统:用户选一个【导演】,在【创作】期谈成【剧本】,再在【游玩】期让【演员】按剧本上场,产出可读文本(角色扮演、长文/爽文、扩写、思想实验等共用同一内核)。 **writing-agent** 是本地运行的多 Agent **文本创作 / 游玩**系统:用户选一个【配方】,在【创作】期谈成【工作流计划】与【运行规格】,再在【游玩】期让【执行单元】按规格上场,产出可读文本(角色扮演、长文/爽文、扩写、思想实验等共用同一内核)。
## 1.2 要解决什么问题 ## 1.2 要解决什么问题
| 要 | 不要 | | 要 | 不要 |
|----|------| |----|------|
| 用程序控制「每一步注入什么上下文」 | 把整本长说明书一次塞进 LLM | | 用程序控制「每一步注入什么上下文」 | 把整本长说明书一次塞进 LLM |
| 用 Agent 按用户体验**编排**用哪些能、什么顺序 | 死板选单 DAG或全程让 LLM 自由发明工序 | | 用编排器按用户体验**编排**用哪些能、什么顺序 | 死板选单 DAG或全程让 LLM 自由发明工序 |
| 产物可解析、可渲染、对人可读 | 产物里堆满英文变量名让用户难受 | | 产物可解析、可渲染、对人可读 | 产物里堆满英文变量名让用户难受 |
| 规格(能复用的声明)与一局游玩过程分离 | 每种玩法重写一套运行时 | | 运行规格(能复用的声明)与一局游玩过程分离 | 每种玩法重写一套运行时 |
## 1.3 两段生命周期 ## 1.3 两段生命周期
```text ```text
【创作 design】选导演 → 编排剧本(步骤=能)→ 逐步执行能 → 谈成运行规格 【创作】选配方 → 编排工作流计划(步骤=能)→ 逐步执行能 → 谈成运行规格
▼ 用户手动进入 ▼ 用户手动进入
【游玩 play】用户输入 → 演员按规格上场 → 可见终稿;可存档 / 重 roll 【游玩】用户输入 → 执行单元按规格上场 → 可见终稿;可存档 / 重 roll
``` ```
- **创作**:谈清「这局要什么体验、用哪些能钉成什么产物」。 - **创作**:谈清「这局要什么体验、用哪些能钉成什么产物」。
- **游玩**:按已验收规格跑;用户新输入通常视为认可上一轮展示(否则重 roll - **游玩**:按已验收运行规格跑;用户新输入通常视为认可上一轮展示(否则重 roll
## 1.4 运行时怎么分工(撰写能时必须懂) ## 1.4 运行时怎么分工(撰写能时必须懂)
| 角色 | 做什么 | 不做什么 | | 角色 | 做什么 | 不做什么 |
|------|--------|----------| |------|--------|----------|
| **导演Agent** | 决定下一步调哪个演员;编排剧本步骤 | 不直接写小说正文;不私自改相位 | | **编排器** | 决定下一步调哪个执行单元;编排工作流计划步骤 | 不直接写小说正文;不私自改相位 |
| **程序Runtime** | 校验权限;按契约拼上下文;切步;发 opening验收门控 | 不替用户发明体验 | | **程序Runtime** | 校验权限;按契约拼上下文;切步;发 opening验收门控 | 不替用户发明体验 |
| **能modules** | 某一步「怎么和用户谈、产出什么形状」的方法正文 | 不是整场流水线 | | **modules** | 某一步「怎么和用户谈、产出什么形状」的方法正文 | 不是整场流水线 |
| **演员Worker** | 一次 LLM 执行(创作期跑能,或游玩期跑声明内 ref | 不决定全局调度 | | **执行单元Worker** | 一次 LLM 执行(创作期跑能,或游玩期跑声明内 ref | 不决定全局调度 |
关键路径: 关键路径:
```text ```text
用户选【导演】(如世界模拟器) 用户选【配方】(如世界模拟器)
→ design-flow从【能】排出**近期**步骤,写出 设计.创作流程 → design-flow从【能】排出**近期**步骤,写出 设计.创作流程(工作流计划)
(可变增量 DAG每步 id + 固定中文名 + depends_onstatus=open|closed (可变增量 DAG每步 id + 固定中文名 + depends_onstatus=open|closed
→ 用户验收近期流程 → 用户验收近期流程
→ 反复 design-step程序注入「当前能」的 prompt 切片 + 依赖产物 → 反复 design-step程序注入「当前能」的 prompt 切片 + 依赖产物
→ 步骤做完仍 open → 再 design-flow可追加同能多次,如生成规则 / 具体实例) → 步骤做完仍 open → 再 design-flow可追加同能多次,如生成规则 / 具体实例)
→ closed 后收成可进游玩的规格,如 设计.worker集 → closed 后收成可进游玩的运行规格,如 设计.worker集
→ 用户手动进游玩 → 用户手动进游玩
``` ```
## 1.5 磁盘上两层内容(作者视角) ## 1.5 磁盘上两层内容(作者视角)
```text ```text
导演】recipes/{导演id}/recipe.yaml 方法的建议近期起点 / 调味说明 配方】recipes/{配方id}/recipe.yaml 方法论(适用/核心思路/设计流程/原则)+ 近期起点
【能】modules/{能id}/prompt.md 共用工序;多导演可选用同一能力 能】modules/{能id}/prompt.md 共用工序;编排读 meta 选型,执行读方法全文
modules/catalog.yaml 能目录:中文名 + 短声明 + 产物 tag+ 可选 repeatable modules/catalog.yaml 能目录:中文名 + 短声明 + 产物 tag+ 可选 repeatable
``` ```
- 新建作品**只选导演一层**,不再叠「能力包 + 配方」 - 新建作品**只选配方一层**,不再叠第二层选型
- 导演给出的步骤是**近期起点**;本局可增量追加、可反复调用标了 `repeatable` 的能;验收的是本局【剧本】,不是磁盘死菜谱。 - 配方给出的步骤是**近期起点**;本局可增量追加、可反复调用标了 `repeatable`能;验收的是本局【工作流计划】与【运行规格】,不是磁盘死菜谱。
--- ---
# 第二部分:称呼定义(必须统一) # 第二部分:称呼定义(必须统一)
对用户与能正文,优先用**拍摄隐喻**。括号内为内部/旧称,撰写时勿当用户主词。 对用户与能正文,优先用下表中文。括号内为业界叫法 / 内部 id,撰写时勿当用户主词堆砌
## 2.1 个核心词 ## 2.1 个核心词
| 称呼 | 含义 | 内部大致对应 | 禁止对用户说 | | 称呼 | 业界叫法 | 含义 | 内部大致对应 | 禁止对用户说 |
|------|------|--------------|--------------| |------|----------|------|--------------|--------------|
| **导演** | 新建时选一次的方法起点(世界模拟器、扩写助手…);② 会话里负责调度的 Agent | `recipes/`、Main Agent / orchestrator | 总管、配方(作选型主词)、能力包(作第二层选项) | | **配方** | Recipe | 新建时选一次的方法起点(世界模拟器、扩写助手…) | `recipes/` | 导演(旧)、能力包(作第二层选项) |
| **剧本** | 本局谈成的流程与规格(活的) | `设计.创作流程` + 各能力产物 + 终稿 `设计.worker集` 等 | 「剧本 Skill 菜单」、死板流程卡 | | **编排器** | Orchestrator | 会话里负责调度的 Agent | Main Agent / orchestrator | 导演、总管(旧) |
| **演员** | 上场执行的一次单元 | Worker / `run_worker` | 对用户堆 `Worker · english-id` | | **工作流计划** | Workflow Plan / Horizon DAG | 本局谈成的近期增量步骤图 | `设计.创作流程` | 剧本(旧,流程部分)、死板流程卡 |
| **能力** | 共用工序模块;导演从池里选型编排 | `modules/{id}/` | 组件池、模块(作者文档可用;用户文案用「能力」 | | **运行规格** | Runtime Spec | 可进游玩的执行声明 | `设计.worker集` 等 | 剧本(旧,规格部分 |
| **执行单元** | Worker | 上场执行的一次单元 | Worker / `run_worker` | 演员(旧);对用户堆 english-id |
| **技能** | Skill | 共用工序模块;编排器从池里选型编排 | `modules/{id}/` | 能力(旧)、组件池 |
关系口诀: 关系口诀:
```text ```text
导演 → 用能编排 → 谈成剧本 → 演员按剧本上场 配方 → 用能编排 → 谈成工作流计划 → 收成运行规格 → 执行单元按规格上场
``` ```
## 2.2 阶段与界面 ## 2.2 阶段与界面
| 称呼 | 含义 | | 称呼 | 含义 |
|------|------| |------|------|
| **创作** | lifecycle `design`:谈剧本 | | **创作** | lifecycle `design`:谈工作流计划与运行规格 |
| **游玩** | lifecycle `play`演员上场 | | **游玩** | lifecycle `play`执行单元上场 |
| **产物** | 某步待验收输出(写入黑板 tag | | **产物** | 某步待验收输出(写入黑板 tag |
| **验收 / 接受** | 用户确认产物算数 | | **验收 / 接受** | 用户确认产物算数(人工审批) |
| **黑板** | 按 tag 存正文的上下文板 | | **黑板** | 按 tag 存正文的上下文板 |
| **询问卡** | 结构化提问(选项可改写) | | **询问卡** | 结构化提问(选项可改写) |
@@ -106,11 +108,11 @@
| 内部 id | 用户可见 | 含义 | | 内部 id | 用户可见 | 含义 |
|---------|----------|------| |---------|----------|------|
| `design-flow` | 创作 · 流程编排 | 编排/增量修订可变 DAG`设计.创作流程` | | `design-flow` | 创作 · 流程编排 | 编排/增量修订工作流计划`设计.创作流程` |
| `design-step` | 创作 · 执行步骤 | 执行剧本中当前那一个能 | | `design-step` | 创作 · 执行步骤 | 执行工作流计划中当前那一个能 |
| `opening-generator` | 开局 · 开场白 | 可选;规格收成后的开场白 | | `opening-generator` | 开局 · 开场白 | 可选;规格收成后的开场白 |
## 2.4 剧本流程 JSON编排产物增量 DAG ## 2.4 工作流计划 JSON编排产物增量 DAG
```json ```json
{ {
@@ -128,52 +130,53 @@
|------|------| |------|------|
| `status` | `open` = 还可追加;`closed` = 不再扩步。缺省兼容旧稿视为已收口 | | `status` | `open` = 还可追加;`closed` = 不再扩步。缺省兼容旧稿视为已收口 |
| `steps` 顺序 | 建议执行顺序 | | `steps` 顺序 | 建议执行顺序 |
| `id` | 本局步骤唯一键;同能多次必须不同 | | `id` | 本局步骤唯一键;同能多次必须不同 |
| `name` | 必须与能目录中的**固定中文名**完全一致(可重复) | | `name` | 必须与能目录中的**固定中文名**完全一致(可重复) |
| `depends_on` | 依赖的其它步骤 **id**(若某 name 在本流程唯一,也可写 name | | `depends_on` | 依赖的其它步骤 **id**(若某 name 在本流程唯一,也可写 name |
程序用中文 `name` 映射到 `artifact` tag流程 JSON **不写**英文模块 id / tag。 程序用中文 `name` 映射到 `artifact` tag流程 JSON **不写**英文模块 id / tag。
**禁止**一次排死全程固定长链;「生成规则」「具体实例」等标了 `repeatable` 的能应允许多次编入。 **禁止**一次排死全程固定长链;「生成规则」「具体实例」等标了 `repeatable`能应允许多次编入。
## 2.5 已合并能(勿拆回) ## 2.5 已合并能(勿拆回)
| 错误拆法 | 正确能 | | 错误拆法 | 正确能 |
|----------|----------| |----------|----------|
| 「交互范式」+「美学纲领」两步 | **美学纲领与交互范式**`aesthetics-interaction`)一步 | | 「交互范式」+「美学纲领」两步 | **美学纲领与交互范式**`aesthetics-interaction`)一步 |
询问相近则合并为一步;不要在新能里建议再拆开。 询问相近则合并为一步;不要在新能里建议再拆开。
## 2.6 命名纪律 ## 2.6 命名纪律
| 种类 | 规则 | 例 | | 种类 | 规则 | 例 |
|------|------|-----| |------|------|-----|
| 能中文名 | 稳定、给人看、进流程 JSON | `实现机制` | | 能中文名 | 稳定、给人看、进流程 JSON | `实现机制` |
| 能 id | 英文 kebab= 文件夹名 | `mechanism` | | 能 id | 英文 kebab= 文件夹名 | `mechanism` |
| 产物 tag | 通常 `设计.{中文名或约定名}` | `设计.实现机制` | | 产物 tag | 通常 `设计.{中文名或约定名}` | `设计.实现机制` |
| 游玩演员 ref | 英文 kebab | `narrator` | | 游玩执行单元 ref | 英文 kebab | `narrator` |
| 游玩演员展示名 | 中文 `name` | `叙事转述` | | 游玩执行单元展示名 | 中文 `name` | `叙事转述` |
| UI | 禁止裸露内部英文 id | 不要写 `design-step` 给用户 | | UI | 禁止裸露内部英文 id | 不要写 `design-step` 给用户 |
--- ---
# 第三部分:什么是「能」(泛用定义) # 第三部分:什么是「能」(泛用定义)
## 3.1 定义 ## 3.1 定义
**能** = 创作期可被编排进剧本的**一步工序** **** = 创作期可被编排进工作流计划的**一步工序**
1. 有固定中文名与产物 tag 1. 有固定中文名与产物 tag
2. 有一份程序可切割的方法文档(`prompt.md` 2. 有一份程序可切割的方法文档(`prompt.md`
3. 执行时只注入**本能**方法 + **依赖产物** + 用户表述; 3. 执行时只注入**本能**方法 + **依赖产物** + 用户表述;
4. 与用户对话后产出**可验收**的结构化结果。 4. 与用户对话后产出**可验收**的结构化结果。
**不是**:整场游戏引擎、游玩期每轮演员、也不是导演本身。 能**不是**:整场游戏引擎、游玩期每轮执行单元、也不是配方/编排器本身。
## 3.2 能力在系统中的生命周期 ## 3.2 能力在系统中的生命周期
```text ```text
catalog 登记(短声明给编排看;可选 repeatable catalog 登记(短声明给编排看;可选 repeatable
导演/编排增量选入 设计.创作流程(可同能多次) → 编排增量选入 设计.创作流程(可同能多次)
→ 用户验收流程(或后续扩步后再验) → 用户验收流程(或后续扩步后再验)
→ 轮到该步:若有 opening → 程序先发出 → 轮到该步:若有 opening → 程序先发出
→ 用户首答 → LLM 按能力方法谈/写 → 用户首答 → LLM 按能力方法谈/写
@@ -185,25 +188,25 @@ catalog 登记(短声明给编排看;可选 repeatable
| 交付物 | 路径 | 给谁看 | | 交付物 | 路径 | 给谁看 |
|--------|------|--------| |--------|------|--------|
| 目录行 | `modules/catalog.yaml` 一行 | 编排:只看短 `declaration` | | 目录行 | `modules/catalog.yaml` 一行 | 索引、`repeatable`、编排 `params` |
| 方法全文 | `modules/{id}/prompt.md` | 执行该步的 LLM + 程序切割 | | 方法全文 | `modules/{id}/prompt.md` | 执行该步的 LLM + 程序切割**编排读 `meta` 的 when/when_not/boundary** |
编排时**禁止**把全文 prompt 塞进导演上下文;执行时才注入切割后的方法块。 编排时注入能力 **meta 选型字段**(非全文 prompt;执行时才注入切割后的方法块。
## 3.4 能力之间如何相处 ## 3.4 能力之间如何相处
- **正推**:需要 [体验/产物] → 才纳入某能;勿默认全选池内能力。 - **正推**:需要 [体验/产物] → 才纳入某能;勿默认全选池内能力。
- **边界**:每个能力在 `meta.boundary` 写清「本步定什么 / 不定什么 / 交给谁」。 - **边界**:每个能力在 `meta.boundary` 写清「本步定什么 / 不定什么 / 交给谁」。
- **依赖**:由剧本 `depends_on` 声明;执行期程序注入对应产物。 - **依赖**:由工作流计划 `depends_on` 声明;执行期程序注入对应产物。
- **合并**:询问主题高度重叠 → 合成一个能力(如美学+交互)。 - **合并**:询问主题高度重叠 → 合成一个能力(如美学+交互)。
- **缩减**:每增必问能否删、能否常驻替代、能否合并。 - **缩减**:每增必问能否删、能否常驻替代、能否合并。
## 3.5 方法层硬禁止(写任何能力都适用) ## 3.5 方法层硬禁止(写任何能力都适用)
- 题材 → 固定演员清单。 - 题材 → 固定执行单元清单。
- 否定式路由(「因为是 X 所以不需要 Y」应写「需要 A 体验 → 用 B 手段」。 - 否定式路由(「因为是 X 所以不需要 Y」应写「需要 A 体验 → 用 B 手段」。
- 把「世界模拟」当成一切开场的默认答案。 - 把「世界模拟」当成一切开场的默认答案。
- 为排版/格式单独发明演员;能程序拼则程序拼。 - 为排版/格式单独发明执行单元;能程序拼则程序拼。
- 临时发明 tool。 - 临时发明 tool。
- 一次 burst 写齐全部能力产物。 - 一次 burst 写齐全部能力产物。
- 在能力产物里堆大量用户看不懂的英文变量名(机器 id 可有,但须有中文展示字段)。 - 在能力产物里堆大量用户看不懂的英文变量名(机器 id 可有,但须有中文展示字段)。
@@ -251,7 +254,7 @@ when: |
when_not: | when_not: |
{什么情况下不要进来} {什么情况下不要进来}
boundary: | boundary: |
本能:… 能:…
邻接能力:…(点名其它能力中文名,说明分工) 邻接能力:…(点名其它能力中文名,说明分工)
``` ```
@@ -306,7 +309,7 @@ boundary: |
| `id` | 英文 id= 目录名) | | `id` | 英文 id= 目录名) |
| `artifact` | 本步写入的黑板 tag | | `artifact` | 本步写入的黑板 tag |
| `declaration` | 给编排看的短声明(不是全文) | | `declaration` | 给编排看的短声明(不是全文) |
| `when` / `when_not` | 何时该/不该入选剧本 | | `when` / `when_not` | 何时该/不该入选工作流计划 |
| `boundary` | 与邻接能力的分工 | | `boundary` | 与邻接能力的分工 |
## 4.4 `catalog.yaml` 一行 ## 4.4 `catalog.yaml` 一行
@@ -321,11 +324,11 @@ boundary: |
| 字段 | 谁用 | | 字段 | 谁用 |
|------|------| |------|------|
| `declaration` | 插入导演/编排提示,选型 | | `declaration` | 插入编排提示,选型 |
| `name` / `artifact` | 流程与执行映射 | | `name` / `artifact` | 流程与执行映射 |
| `opening` | 可选覆盖;一般只写在 prompt 的 `opening` 块 | | `opening` | 可选覆盖;一般只写在 prompt 的 `opening` 块 |
改 `name` 会破坏已有剧本 JSON尽量不改。 改 `name` 会破坏已有工作流计划 JSON尽量不改。
## 4.5 opening 节奏(通用) ## 4.5 opening 节奏(通用)
@@ -348,7 +351,7 @@ task 必须写:禁止重复同一开场;在首答上补洞。
- **键名对人友好**(中文或稳定中文标签)。 - **键名对人友好**(中文或稳定中文标签)。
- 机器 id如 `ref`)若需要,与中文名成对出现。 - 机器 id如 `ref`)若需要,与中文名成对出现。
- 写清「本步完成的定义」;未决放 `开放问题`,不要假完备。 - 写清「本步完成的定义」;未决放 `开放问题`,不要假完备。
- 不要在本能产物里偷偷交下游能力该交的终稿(除非本能就是收成步)。 - 不要在本能产物里偷偷交下游能力该交的终稿(除非本能就是收成步)。
## 4.8 追问(`probe`)通用要求 ## 4.8 追问(`probe`)通用要求
@@ -373,7 +376,7 @@ task 必须写:禁止重复同一开场;在首答上补洞。
# 第六部分:给撰写 AI 的通用任务指令(粘贴用) # 第六部分:给撰写 AI 的通用任务指令(粘贴用)
请撰写(或重写)一个【能】文档: 请撰写(或重写)一个【能】文档:
`skills/dialogue/world-simulator/modules/{id}/prompt.md` `skills/dialogue/world-simulator/modules/{id}/prompt.md`
(具体中文名 / id / 边界由出题方在指令末行指定。) (具体中文名 / id / 边界由出题方在指令末行指定。)
@@ -381,7 +384,7 @@ task 必须写:禁止重复同一开场;在首答上补洞。
1. 本文**第一部分~第四部分**的项目理解、称呼与格式契约。 1. 本文**第一部分~第四部分**的项目理解、称呼与格式契约。
2. 只使用规定的 fence 块;不要发明新 fence 名。 2. 只使用规定的 fence 块;不要发明新 fence 名。
3. 对用户话术使用导演/剧本/演员/能力;不要写「总管调度 design-xxx」。 3. 对用户话术使用配方/编排器/工作流计划/执行单元/技能;不要写「编排器调度 design-xxx」。
4. 正推:体验 → 手段;禁止题材套件与否定式路由。 4. 正推:体验 → 手段;禁止题材套件与否定式路由。
5. 交互与美学已合并为「美学纲领与交互范式」;禁止建议拆回两步。 5. 交互与美学已合并为「美学纲领与交互范式」;禁止建议拆回两步。
6. 不要修改程序代码;默认只交付 `prompt.md`(除非出题方要求改 catalog 6. 不要修改程序代码;默认只交付 `prompt.md`(除非出题方要求改 catalog
@@ -400,27 +403,27 @@ artifact
--- ---
# 第七部分:当前能池速查(选题,非本文重点) # 第七部分:当前能池速查(选题,非本文重点)
世界模拟器常用(编排按需,勿默认全选): 世界模拟器常用(编排按需,勿默认全选):
| 能力 | id | 状态(以仓库为准) | | 能力 | id | 状态(以仓库为准) |
|------|-----|-------------------| |------|-----|-------------------|
| 美学纲领与交互范式 | `aesthetics-interaction` | 范例 | | 美学纲领与交互范式 | `aesthetics-interaction` | 范例 |
| 实现机制 | `mechanism` | 待细写 | | 实现机制 | `mechanism` | 写 |
| 世界蓝图与人文地理 | `world-blueprint` | 已写 | | 世界蓝图与人文地理 | `world-blueprint` | 已写 |
| 生成规则 | `generation-rules` | 待细写 | | 生成规则 | `generation-rules` | 已写(可反复) |
| 具体实例 | `concrete-instances` | 待细写 | | 具体实例 | `concrete-instances` | 已写(可反复) |
| 叙事指南 | `narrative` | 已写 |
| 拓扑图谱 | `topology` | 待细写 | | 拓扑图谱 | `topology` | 待细写 |
| 叙事指南 | `narrative` | 待细写 |
| 变量设计与更新规则 | `variable-design` | 待细写 | | 变量设计与更新规则 | `variable-design` | 待细写 |
| 变量控制上下文 | `variable-context` | 待细写 | | 变量控制上下文 | `variable-context` | 待细写 |
| 设计状态栏 | `status-bar` | 待细写 | | 设计状态栏 | `status-bar` | 待细写 |
| 设计回复格式 | `reply-format` | 待细写 | | 设计回复格式 | `reply-format` | 待细写 |
| Worker 规格 | `worker-spec` | 待细写 | | Worker 规格 | `worker-spec` | 已写(可反复) |
| 细化终稿 | `refine` | 待细写 | | 细化终稿 | `refine` | 写 |
导演示例:世界模拟器、扩写助手(见 `recipes/`)。 配方:世界模拟器、扩写助手(见 `recipes/`;写 `core`/`process`/`principles` + 起步 steps)。
--- ---
@@ -432,4 +435,4 @@ artifact
| `world-simulator-modules.md` | 仓库内清单与格式摘要 | | `world-simulator-modules.md` | 仓库内清单与格式摘要 |
| `ui-glossary.md` | 用户可见文案权威 | | `ui-glossary.md` | 用户可见文案权威 |
| `architecture.md` | 运行内核;写能力时不必复述实现细节 | | `architecture.md` | 运行内核;写能力时不必复述实现细节 |
| 旧 `capability-mechanism-handoff.md` | 已过时为「单能力特例」;以本文为准 | | (已删)单能力特例简报 | 以本文为准;勿再恢复特例交接文 |

View File

@@ -1,20 +0,0 @@
# (已迁移)实现机制单能力简报
本文件原先只讲「实现机制」特例,**已废弃**。
请改用泛用交接简报:
**[`capability-authoring-brief.md`](./capability-authoring-brief.md)**
其中包含:项目概述、导演/剧本/演员/能力称呼、泛用能力格式规范,以及可粘贴给其它 AI 的任务指令。
若要写「实现机制」,在泛用简报第六部分末行填写:
```text
能力中文名:实现机制
idmechanism
artifact设计.实现机制
上游依赖(常见):美学纲领与交互范式
明确不做(交给谁):拓扑图谱 / Worker 规格 / 变量* / 状态栏 / 回复格式 / 细化终稿
特殊产物要求(可选):总览最小可运行结构;含「为何需要」「未纳入与原因」;正推禁止默认世界模拟套件
```

View File

@@ -1,31 +1,31 @@
# 创作流程指南Creation Playbook # 创作流程指南Creation Playbook
> **文档层级:剧本 / 创作流程概念(非系统架构)。** > **文档层级:工作流计划 / 创作流程概念(非系统架构)。**
> 系统模块与边界见 [`architecture.md`](./architecture.md)。 > 系统模块与边界见 [`architecture.md`](./architecture.md)。
## 0. 内容在哪 ## 0. 内容在哪
**设计方法(正推、三大步、表与副作用)****`design-orchestrator-guide.md`**(权威)。 **设计方法(正推、三大步、表与副作用)****`design-orchestrator-guide.md`**(权威)。
**流程落地**在 skill 包`orchestrator.md` + `design-intake` **流程落地**在 skill 包`orchestrator.md` + `design-flow` / `design-step` + `modules/` / `recipes/`
写新包 → `skill-design-guide.md`(包格式薄层)→ `skills/.../orchestrator.md` 写新包 → `skill-design-guide.md`(包格式薄层)→ `skills/.../orchestrator.md`;清单见 `world-simulator-modules.md`
--- ---
## 1. 定位 ## 1. 定位
```text ```text
Orchestrator 包 能库 + manifest静态 Orchestrator 包 能库 + manifest静态
黑板 tag 一次 Session 的实参(动态) 黑板 tag 一次 Session 的实参(动态)
Book 跨 Session过程、资产、游玩 Book 跨 Session过程、资产、游玩
设计.worker集 实例规格JSONaccept 后 = Worker 声明) 设计.worker集 运行规格JSONaccept 后 = 执行单元声明)
``` ```
| 层 | 管什么 | | 层 | 管什么 |
|----|--------| |----|--------|
| **运行相位** | `idle` / `running` / `waiting_user` — 系统在等什么 | | **运行相位** | `idle` / `running` / `waiting_user` — 系统在等什么 |
| **业务 stage** | `design`(创作)→ `play`(游玩)→ `done` | | **业务 stage** | `design`(创作)→ `play`(游玩)→ `done` |
| **Agent** | tool loop 内 invoke 哪个 worker | | **编排器** | tool loop 内 invoke 哪个执行单元 |
| **声明** | play 可调度哪些 refexecutor 读声明(非题材管道) | | **运行规格** | play 可调度哪些 refexecutor 读声明(非题材管道) |
| **Book** | 长期存储,见 `book-storage.md` | | **Book** | 长期存储,见 `book-storage.md` |
--- ---
@@ -33,18 +33,16 @@ Book 跨 Session过程、资产、游玩
## 2. 默认包创作流 ## 2. 默认包创作流
```text ```text
新建作品 → UI 引导 → 用户首句 → 创作单位逐步谈 新建作品 → UI 选配方 → 用户首句
phase:core → 纲领类 fixed:* → worker:* → refine design-flow排出近期 设计.创作流程(工作流计划 / 增量 DAGstatus=open|closed
(非死管道;可穿插,但禁止默认「先写完 worker 再填上下文」) → 反复 design-step注入当前技能 modules/{id}/prompt.md + 依赖产物
单位 = 已写出的 fixed:* / resident:* | worker:*(示例话题可问用户,非填空) 不够则再 design-flow可追加 / 反复调用 repeatable 技能)→ closed
单位跑:只写 设计.worker集.草稿;讨论进 messages 收成 设计.worker集(运行规格)→ 验收后才可进 play
用户接受 → 删本单位交互消息,只留产物;草稿保留 可选opening-generator → 用户手动进游玩
……谈完后终稿写 设计.worker集 → 验收后才可进 play run执行单元按契约从黑板重装acceptance=review 处停、压缩过程 tag
→ (可选)开局 · 开场白 → 用户手动进游玩
→ runworker 按契约从黑板重装acceptance=review 处停、压缩过程 tag
``` ```
固定上下文 tag 的主收益是 **跨 worker 复用同一份正文**;写下游时仍依赖上游定稿(不能只报 tag 名省掉正文)。能省的是扯皮过程(验收折叠)。 固定上下文 tag 的主收益是 **跨执行单元复用同一份正文**;写下游时仍依赖上游定稿(不能只报 tag 名省掉正文)。能省的是扯皮过程(验收折叠)。
不再要求用户选择 skill 包;默认 orchestrator 见 `src/config/default-orchestrator.ts` 不再要求用户选择 skill 包;默认 orchestrator 见 `src/config/default-orchestrator.ts`
方法细节见 **`design-orchestrator-guide.md` §7.2**。不要以「世界模拟器」为默认总形态。 方法细节见 **`design-orchestrator-guide.md` §7.2**。不要以「世界模拟器」为默认总形态。

View File

@@ -15,37 +15,39 @@
|---|------| |---|------|
| 1 | 日常包含 **两类**AIRP/交互扮演 **与** 长文/爽文创作(同一运行内核) | | 1 | 日常包含 **两类**AIRP/交互扮演 **与** 长文/爽文创作(同一运行内核) |
| 2 | **UI 不自研美学**:布局/控件直接抄参考产品即可;**存档与续作稳定是硬指标** | | 2 | **UI 不自研美学**:布局/控件直接抄参考产品即可;**存档与续作稳定是硬指标** |
| 3 | **导演**:新建时用 UI **选一个**(世界模拟器 / 扩写助手…;初期可只有 1 项) | | 3 | **配方**:新建时用 UI **选一个**(世界模拟器 / 扩写助手…;初期可只有 1 项) |
| 4 | **剧本动态**:不在 UI 里点选死板「剧本菜单」;选定导演后,由导演Agent听用户说话谈出本局剧本创作流程 / Worker 集)调度 | | 4 | **工作流计划动态**:不在 UI 里点选死板「流程菜单」;选定配方后,由编排器听用户说话谈出本局工作流计划(创作流程)与运行规格(Worker 集)调度 |
用户侧拍摄术语权威对照:**`ui-glossary.md` §0**导演 / 剧本 / 演员 / 能力)。 用户侧术语权威对照:**`ui-glossary.md` §0**配方 / 编排器 / 技能 / 工作流计划 / 运行规格 / 执行单元)。
### 0.2 导演 vs 剧本(动态) ### 0.2 配方 vs 工作流计划 / 运行规格(动态)
```text ```text
导演 = 用户 UI 选一次的方法起点(可调味) 配方 = 用户 UI 选一次的方法起点(可调味)
= 内部 recipes / 原「能力包·配方」合一 = 内部 recipes/
= 例:世界模拟器、扩写助手 = 例:世界模拟器、扩写助手
剧本 ≠ 再选一张固定流程卡 工作流计划 ≠ 再选一张固定流程卡
= 选定导演之后:用户说话 → 导演调度创作 = 选定配方之后:用户说话 → 编排器调度创作
→ 产出 设计.创作流程 + 设计.worker集本局活剧本 → 产出 设计.创作流程(近期增量 DAG
→ 游玩再按声明让【演员】上场
能力 = 共用工序(美学纲领与交互范式…);导演从中编排 运行规格 = 谈成的 设计.worker集 等可进游玩声明
演员 = 实际上场的 Worker → 游玩再按声明让【执行单元】上场
技能 = 共用工序(美学纲领与交互范式…);编排器从中编排
执行单元 = 实际上场的 Worker
``` ```
| | 导演 | 剧本(动态) | | | 配方 | 工作流计划 / 运行规格(动态) |
|--|------|----------------| |--|------|----------------|
| 谁选 | **用户 UI**(显式,一层) | **导演 Agent + 用户对话**(隐式) | | 谁选 | **用户 UI**(显式,一层) | **编排器 + 用户对话**(隐式) |
| 变不变 | 选项相对稳定 | 每局流程、Worker 集、回合调度都可变 | | 变不变 | 选项相对稳定 | 每局流程、运行规格、回合调度都可变 |
| 忌讳 | 再叠一层「配方」选择 | 固化成死 DAG / 死选单 | | 忌讳 | 再叠一层选型 | 固化成死 DAG / 死选单 |
| 本仓库对应 | `recipes/` + 默认 skill 包 | `设计.创作流程` / `设计.worker集` | | 本仓库对应 | `recipes/` + 默认 skill 包 | `设计.创作流程` / `设计.worker集` |
因此:**只给导演一个选择 UI****不要**再给「剧本 / 配方」做第二层死板选择器。 因此:**只给配方一个选择 UI****不要**再给「工作流计划」做第二层死板选择器。
**多导演**才有意义的情况:方法边界真不同(世界模拟 vs 扩写助手),而不是同一导演内的题材分化——后者留在剧本层动态谈成。 **多配方**才有意义的情况:方法边界真不同(世界模拟 vs 扩写助手),而不是同一配方内的题材分化——后者留在工作流计划层动态谈成。
--- ---
@@ -88,7 +90,7 @@ A4 / B4 **共用**同一套存档语义(`session.json` + `instance`/`run` 快
|----|------| |----|------|
| N2 | 狼人杀级信息隔离 | | N2 | 狼人杀级信息隔离 |
| N3 | Context Trace 专业调试台 | | N3 | Context Trace 专业调试台 |
| N4 | 多导演**运营商店**P0 只要选择 UI可仅 1 项) | | N4 | 多配方**运营商店**P0 只要选择 UI可仅 1 项) |
| N5 | DefinitionVersion 完整发布迁移协议 | | N5 | DefinitionVersion 完整发布迁移协议 |
| N6 | SillyTavern 卡批量导入导出 | | N6 | SillyTavern 卡批量导入导出 |
| N7 | 自研精美 UI / 按 `ui-design` 大改布局(**抄参考即可** | | N7 | 自研精美 UI / 按 `ui-design` 大改布局(**抄参考即可** |
@@ -103,8 +105,8 @@ A4 / B4 **共用**同一套存档语义(`session.json` + `instance`/`run` 快
| 功能 | 现状 | P0? | | 功能 | 现状 | P0? |
|------|------|-----| |------|------|-----|
| 新建作品 → 选导演(能力包;初期可仅一项) | ✅/🟡 | **必做**(有选择 UI一项时默认选中即可 | | 新建作品 → 选配方(能力包;初期可仅一项) | ✅/🟡 | **必做**(有选择 UI一项时默认选中即可 |
| 意图可走扮演 **或** 写手/爽文(剧本层动态,不另选死板剧本卡) | 🟡 | **必做** | | 意图可走扮演 **或** 写手/爽文(工作流计划层动态,不另选死板流程卡) | 🟡 | **必做** |
| 验收出口无死胡同 | 🟡 | **必做** | | 验收出口无死胡同 | 🟡 | **必做** |
| 进入游玩/写作阶段门槛清晰 | 🟡 | **必做** | | 进入游玩/写作阶段门槛清晰 | 🟡 | **必做** |
| UI 自研打磨 | — | **不做**;缺块就抄参考产品交互 | | UI 自研打磨 | — | **不做**;缺块就抄参考产品交互 |
@@ -138,14 +140,14 @@ A4 / B4 **共用**同一套存档语义(`session.json` + `instance`/`run` 快
## 3. P0 详细路径 ## 3. P0 详细路径
**P0 一句话**:用户用 UI 选好**导演 Skill**初期可只有一个AIRP 与长文/爽文都在**剧本层动态**谈成并跑起来,且 **存档/续作稳定**UI 抄参考即可。 **P0 一句话**:用户用 UI 选好**配方**初期可只有一个AIRP 与长文/爽文都在**工作流计划层动态**谈成并跑起来,且 **存档/续作稳定**UI 抄参考即可。
### 3.1 黄金路径(两条都要绿) ### 3.1 黄金路径(两条都要绿)
**线 A扮演** **线 A扮演**
```text ```text
A-GP1 新建 → UI 选导演(可仅一项)→ 描述扮演/交互意图 A-GP1 新建 → UI 选配方(可仅一项)→ 描述扮演/交互意图
A-GP2 验收至可进游玩 A-GP2 验收至可进游玩
A-GP3 ≥3 回合输入→终稿 A-GP3 ≥3 回合输入→终稿
A-GP4 存 run 档 → 刷新/重开续作成功 A-GP4 存 run 档 → 刷新/重开续作成功
@@ -155,7 +157,7 @@ A-GP5 加载 earlier 档或新开一条线之一可用
**线 B长文/爽文)** **线 B长文/爽文)**
```text ```text
B-GP1 新建 → UI 选导演 → 描述爽文/长篇意图(写手或分段助手) B-GP1 新建 → UI 选配方 → 描述爽文/长篇意图(写手或分段助手)
B-GP2 验收至可进写作Worker 集含大纲/写章类能力,勿只能聊天扮演) B-GP2 验收至可进写作Worker 集含大纲/写章类能力,勿只能聊天扮演)
B-GP3 连续生成 ≥2 段(章)正文 B-GP3 连续生成 ≥2 段(章)正文
B-GP4 存档含已生成正文 → 续作能接着写下一段 B-GP4 存档含已生成正文 → 续作能接着写下一段
@@ -174,12 +176,12 @@ B-GP5 回到 earlier 档重 roll 某段 或 等价恢复可用
| S4 | 回归:线 A、线 B 各完整存读一轮,不手改 `books/` | 双线绿 | | S4 | 回归:线 A、线 B 各完整存读一轮,不手改 `books/` | 双线绿 |
| S5 | 已知「存档丢正文 / 续作进死相位」类 bug 清零 | 无阻断 | | S5 | 已知「存档丢正文 / 续作进死相位」类 bug 清零 | 无阻断 |
#### WP-D 导演选择(与存档并列早做) #### WP-D 配方选择(与存档并列早做)
| # | 项 | 验收 | | # | 项 | 验收 |
|---|-----|------| |---|-----|------|
| D0 | 新建作品可选导演registry仅 1 项时默认选中并可确认 | 进入该包创作 | | D0 | 新建作品可选配方registry仅 1 项时默认选中并可确认 | 进入该包创作 |
| D1 | 人话展示导演名/简介,不暴露路径 | 可选懂 | | D1 | 人话展示配方名/简介,不暴露路径 | 可选懂 |
#### WP-A 进出与失败出口(文案够用即可) #### WP-A 进出与失败出口(文案够用即可)
@@ -202,7 +204,7 @@ B-GP5 回到 earlier 档重 roll 某段 或 等价恢复可用
| # | 项 | 验收 | | # | 项 | 验收 |
|---|-----|------| |---|-----|------|
| L1 | 启动引导明确支持「写爽文/长篇/先大纲再写」 | B-GP1 | | L1 | 启动引导明确支持「写爽文/长篇/先大纲再写」 | B-GP1 |
| L2 | design 能稳定收到写手向 Worker 集(补 template 或 design 提示,**同一导演内动态谈成** | B-GP2 | | L2 | design 能稳定收到写手向 Worker 集(补 template 或 design 提示,**同一配方内动态谈成** | B-GP2 |
| L3 | play 连续 ≥2 段正文 | B-GP3 | | L3 | play 连续 ≥2 段正文 | B-GP3 |
| L4 | 正文在存档/续作中仍在 | B-GP4 | | L4 | 正文在存档/续作中仍在 | B-GP4 |
@@ -222,7 +224,7 @@ B-GP5 回到 earlier 档重 roll 某段 或 等价恢复可用
### 3.3 P0 明确不做 ### 3.3 P0 明确不做
- 第二套死板「剧本选单」/ 固定题材 DAG - 第二套死板「流程选单」/ 固定题材 DAG
- 自研精美 UI、工作台大改 - 自研精美 UI、工作台大改
- 隔离模拟、Trace 台、完整副作用调度、版本迁移协议 - 隔离模拟、Trace 台、完整副作用调度、版本迁移协议
- 为文采大改全套提示词(仅修**阻断线 B 收不成写手规格**的引导/模板) - 为文采大改全套提示词(仅修**阻断线 B 收不成写手规格**的引导/模板)
@@ -231,19 +233,19 @@ B-GP5 回到 earlier 档重 roll 某段 或 等价恢复可用
```text ```text
1. WP-S 存档稳定(先修已知腐档) 1. WP-S 存档稳定(先修已知腐档)
2. WP-D 导演选择 UI可仅一项 2. WP-D 配方选择 UI可仅一项
3. WP-A 失败出口 / 进出 3. WP-A 失败出口 / 进出
4. WP-R 线 A 回合 4. WP-R 线 A 回合
5. WP-L 线 B 长文最小闭环(引导 + template + 存档验正文) 5. WP-L 线 B 长文最小闭环(引导 + template + 存档验正文)
6. WP-U 仅补抄来的缺口控件(含选导演/存档若未齐) 6. WP-U 仅补抄来的缺口控件(含选配方/存档若未齐)
7. WP-E 双线验收闸门 → P0 完成 7. WP-E 双线验收闸门 → P0 完成
``` ```
### 3.5 P0 DoD ### 3.5 P0 DoD
- [ ] 线 AA-GP15 通过(含选导演、续作/读档) - [ ] 线 AA-GP15 通过(含选配方、续作/读档)
- [ ] 线 BB-GP15 通过(含选导演、正文不丢) - [ ] 线 BB-GP15 通过(含选配方、正文不丢)
- [ ] 导演选择 UI 可用(可仅一项) - [ ] 配方选择 UI 可用(可仅一项)
- [ ] 无等待死胡同;失败可重试 - [ ] 无等待死胡同;失败可重试
- [ ] 不依赖手改磁盘文件 - [ ] 不依赖手改磁盘文件
- [ ] UI 无大改承诺;存档稳定优先于观感 - [ ] UI 无大改承诺;存档稳定优先于观感
@@ -254,13 +256,13 @@ B-GP5 回到 earlier 档重 roll 某段 或 等价恢复可用
| 日常能力 | 阶段 | | 日常能力 | 阶段 |
|----------|------| |----------|------|
| 导演选择 UI可仅一项剧本层动态谈规格、AIRP+长文主路径、**存档续作硬稳定** | **P0** | | 配方选择 UI可仅一项工作流计划层动态谈规格、AIRP+长文主路径、**存档续作硬稳定** | **P0** |
| 抄来的 UI 缺口补齐 | **P0U** / 不够再后补 | | 抄来的 UI 缺口补齐 | **P0U** / 不够再后补 |
| 表编辑精修、改规格心流、副作用完整 | **PX1/PX2** | | 表编辑精修、改规格心流、副作用完整 | **PX1/PX2** |
| Trace、预算、版本协议、E2E | **PX3** | | Trace、预算、版本协议、E2E | **PX3** |
| 长文「专业编辑器 / 评测 / 多卷」加深 | **原 PX4 收窄**P0 已含最小长文) | | 长文「专业编辑器 / 评测 / 多卷」加深 | **原 PX4 收窄**P0 已含最小长文) |
| 隔离 + 专业调试 | **PX5** | | 隔离 + 专业调试 | **PX5** |
| 多个导演包(方法真不同时再加) | **需要时再加**;非「剧本菜单」 | | 多个配方包(方法真不同时再加) | **需要时再加**;非「流程菜单」 |
--- ---
@@ -270,5 +272,5 @@ B-GP5 回到 earlier 档重 roll 某段 或 等价恢复可用
|---|--------|------| |---|--------|------|
| 1 | 仅 AIRP | **已订正**+ 长文/爽文 | | 1 | 仅 AIRP | **已订正**+ 长文/爽文 |
| 2 | UI 要按设计稿打磨 | **已订正**:抄参考;存档稳定优先 | | 2 | UI 要按设计稿打磨 | **已订正**:抄参考;存档稳定优先 |
| 3 | 永远自动加载、无选包 UI | **已订正**UI 选**导演**剧本层保持动态 | | 3 | 永远自动加载、无选包 UI | **已订正**UI 选**配方**工作流计划层保持动态 |
| 4 | 单包 = 不能多种玩法 | **已澄清**:一个导演内剧本动态分化 | | 4 | 单包 = 不能多种玩法 | **已澄清**:一个配方内工作流计划动态分化 |

View File

@@ -1,6 +1,6 @@
# 创作设计指导(总管 / 分步 design skills # 创作设计指导(编排器 / 分步 design skills
> **文档层级:剧本 / 创作方法(非系统架构)。** > **文档层级:工作流计划 / 创作方法(非系统架构)。**
> 运行内核边界见 [`architecture.md`](./architecture.md);本文不定义相位机、持久化或 Context Compiler。 > 运行内核边界见 [`architecture.md`](./architecture.md);本文不定义相位机、持久化或 Context Compiler。
权威说明:如何从用户意图收成 **实例规格(`设计.worker集` JSON**,并指导 play 期声明调度。 权威说明:如何从用户意图收成 **实例规格(`设计.worker集` JSON**,并指导 play 期声明调度。
@@ -8,18 +8,20 @@
相关:`context-assembly.md`(拼装)、`preset-format.md`(全局预设)、`tag-blackboard.md`(黑板)、`run-snapshot.md`(快照)。 相关:`context-assembly.md`(拼装)、`preset-format.md`(全局预设)、`tag-blackboard.md`(黑板)、`run-snapshot.md`(快照)。
包内落地: 包内落地(现行 `skills/dialogue/world-simulator/`
| 文件 | 角色 | | 文件 | 角色 |
|------|------| |------|------|
| `orchestrator.md` | 总管调度 | | `orchestrator.md` | 编排器调度 |
| `design-common.md` | 创作共同开头(注入各 design-* | | `recipes/` | 配方选项(新建 UI 选一层 |
| `workers/design-core/` | A 核心(开放,不拆 A1→A2→A3 管道 | | `modules/{id}/prompt.md` | 技能正文design-step 注入 |
| `workers/design-worker/` | 一次一个 worker | | `workers/design-flow/` | 编排近期 `设计.创作流程` |
| `workers/design-fixed/` | 一次一块固定上下文 | | `workers/design-step/` | 执行当前能力步 |
| `workers/design-refine/` | C 细化 / 终稿 | | `workers/opening-generator/` | 可选开场白 |
| `worker-templates/` | play 执行单元默认契约 |
**运行时以各 SKILL + design-common 为准**;本文是方法长文,改方法时与 skill 切片一起改。 `design-core` / `design-fixed` / `design-worker` / `design-refine` / `design-common.md` / `design-intake` **已移除**
**运行时以包内 SKILL + modules 为准**;本文是方法长文,改方法时与 skill / 能力切片一起改。清单见 `world-simulator-modules.md`
--- ---
@@ -42,7 +44,7 @@
- 把「世界模拟」当成开场默认答案 - 把「世界模拟」当成开场默认答案
- 固定 instantiate 管道world-blueprint 等) - 固定 instantiate 管道world-blueprint 等)
**预设**:凡 LLM 请求(总管 / agent / worker均插入用户预设。 **预设**:凡 LLM 请求(编排器 / agent / worker均插入用户预设。
**进 play**:用户手动满意后进入(程序不强制开局锁定)。 **进 play**:用户手动满意后进入(程序不强制开局锁定)。
**Play 回合**:用户新输入 = 认可上一轮最终展示;否则重 roll / 编辑后重 roll。表维护可延后。 **Play 回合**:用户新输入 = 认可上一轮最终展示;否则重 roll / 编辑后重 roll。表维护可延后。
@@ -89,7 +91,7 @@
对当前理解与「现有 worker/上下文草案」打分或文字判定。 对当前理解与「现有 worker/上下文草案」打分或文字判定。
**对内**:可只在思维链里过一遍。 **对内**:可只在思维链里过一遍。
**对外**总管 `ask_user.assessment`,或关键分叉复述):写成用户可读的完备度评价,再据此出题。 **对外**编排器 `ask_user.assessment`,或关键分叉复述):写成用户可读的完备度评价,再据此出题。
**首要(必须检)** **首要(必须检)**
@@ -304,7 +306,7 @@ value, rev, updatedAt, source # source: user | worker:<id> | system
### 6.1 用法(重要:不是填空) ### 6.1 用法(重要:不是填空)
§6.2 里的名称 **只是示例话题**:告诉 design / 总管——**可以向用户询问类似内容**,再收成固定上下文。 §6.2 里的名称 **只是示例话题**:告诉 design / 编排器——**可以向用户询问类似内容**,再收成固定上下文。
```text ```text
不是:按表逐项填空、默认必谈、谈完才算过关 不是:按表逐项填空、默认必谈、谈完才算过关
@@ -478,7 +480,7 @@ Worker 规格应回答:职责是什么、读哪些已有 tag、写哪些 tag
| 交互 / RP | 产出用户可见终稿的转述(如 narrator`review`;世界裁决等中间层 → `continue` | | 交互 / RP | 产出用户可见终稿的转述(如 narrator`review`;世界裁决等中间层 → `continue` |
创作期按 **§7.2 创作单位** 分块验收worker 与固定上下文同级),与上表正交。 创作期按 **§7.2 创作单位** 分块验收worker 与固定上下文同级),与上表正交。
design-intake / 创作调度必须为 **每个** run worker 写出 `acceptance`;缺省时不得假设「全都不用验收」——面向用户的可读输出默认倾向 `review`,纯中间层倾向 `continue`,吃不准就 ask_user。 design-flow / design-step / 创作调度必须为 **每个** run worker 写出 `acceptance`;缺省时不得假设「全都不用验收」——面向用户的可读输出默认倾向 `review`,纯中间层倾向 `continue`,吃不准就 ask_user。
--- ---
@@ -502,7 +504,7 @@ design-intake / 创作调度必须为 **每个** run worker 写出 `acceptance`
--- ---
## 8. Play / Run 边界(给总管;运行时按声明执行) ## 8. Play / Run 边界(给编排器;运行时按声明执行)
-`run_worker` 声明内的 ref -`run_worker` 声明内的 ref
-`acceptance: review` → 停、给人看、接受后压缩再继续 -`acceptance: review` → 停、给人看、接受后压缩再继续

View File

@@ -20,7 +20,7 @@
|---|---|---| |---|---|---|
| **系统架构** | **`architecture.md`** | 模块边界、定义/实例、调度、上下文、持久化原则、风险 | | **系统架构** | **`architecture.md`** | 模块边界、定义/实例、调度、上下文、持久化原则、风险 |
| 运行内核 | `runtime-state-machine.md` | 5 相位、tool 边界、burst | | 运行内核 | `runtime-state-machine.md` | 5 相位、tool 边界、burst |
| 运行内核 | `tool-contracts.md` | 总管 / worker tool | | 运行内核 | `tool-contracts.md` | 编排器 / worker tool |
| 运行内核 | `context-assembly.md` | 上下文拼接:上半固定、下半动态 | | 运行内核 | `context-assembly.md` | 上下文拼接:上半固定、下半动态 |
| 运行内核 | `tag-blackboard.md` | 标签黑板 | | 运行内核 | `tag-blackboard.md` | 标签黑板 |
| 持久化 | `book-storage.md` | Book、CardAsset、PlayBook、过程存储 | | 持久化 | `book-storage.md` | Book、CardAsset、PlayBook、过程存储 |
@@ -33,11 +33,13 @@
| **日常 → P0** | **`daily-use-p0.md`** | 日常场景、功能映射、P0 详细工作包 | | **日常 → P0** | **`daily-use-p0.md`** | 日常场景、功能映射、P0 详细工作包 |
| **剧本 / 方法(非系统架构)** | `design-orchestrator-guide.md` | 创作三大步、表/副作用、自检 | | **剧本 / 方法(非系统架构)** | `design-orchestrator-guide.md` | 创作三大步、表/副作用、自检 |
| **剧本 / 方法(非系统架构)** | `creation-playbook.md` | 创作流程概念(指向指导) | | **剧本 / 方法(非系统架构)** | `creation-playbook.md` | 创作流程概念(指向指导) |
| **剧本 / 方法(非系统架构)** | `world-simulator-modules.md` | 编排器/能力清单与现行包布局 |
| **Skill 格式(非系统架构)** | `orchestrator-skill-format.md` | manifest 写法(非编排表) | | **Skill 格式(非系统架构)** | `orchestrator-skill-format.md` | manifest 写法(非编排表) |
| **Skill 格式(非系统架构)** | `worker-skill-format.md` | SKILL.md、contextSegments | | **Skill 格式(非系统架构)** | `worker-skill-format.md` | SKILL.md、contextSegments |
| **Skill 格式(非系统架构)** | `skill-format.md` | 包存储、registry | | **Skill 格式(非系统架构)** | `skill-format.md` | 包存储、registry(示例以 world-simulator 为准) |
| **Skill 格式(非系统架构)** | `skill-design-guide.md` | 包格式薄层 | | **Skill 格式(非系统架构)** | `skill-design-guide.md` | 包格式薄层 |
| **Skill 格式(非系统架构)** | `preset-format.md` | 预设导入 | | **Skill 格式(非系统架构)** | `preset-format.md` | 预设导入 |
| **能力撰写** | `briefs/capability-authoring-brief.md` | 外部 AI 写 modules 交接 |
许可证占位:仓库根 `THIRD_PARTY_NOTICES.md` 许可证占位:仓库根 `THIRD_PARTY_NOTICES.md`
@@ -53,14 +55,16 @@
| 路线阶段 | 目标 | 备注 | | 路线阶段 | 目标 | 备注 |
|----------|------|------| |----------|------|------|
| **PX0当前** | 导演 UI + 双线主路径 + 存档硬稳定 | 详见 `daily-use-p0.md` / `px-roadmap.md` | | **PX0当前** | 编排器 UI + 双线主路径 + 存档硬稳定 | 详见 `daily-use-p0.md` / `px-roadmap.md` |
| PX1PX2 | 创作/游玩体验打磨;副作用 | UI 仍可抄 | | PX1PX2 | 创作/游玩体验打磨;副作用 | UI 仍可抄 |
| PX3 | Trace、预算、规格版本、E2E | — | | PX3 | Trace、预算、规格版本、E2E | — |
| PX4 | 长文加深P0 已含最小闭环) | — | | PX4 | 长文加深P0 已含最小闭环) | — |
| PX5 | 隔离 + 调试;必要时新导演包 | — | | PX5 | 隔离 + 调试;必要时新配方包 | — |
| 延后 | SQLite / 事件溯源 / Mastra·Next | — | | 延后 | SQLite / 事件溯源 / Mastra·Next | — |
历史分期 A0E 见下节(多数已 done作文件职责索引,不再当作「当前从零启动」路线)。 历史分期 A0E 见下节(**多数已 done作文件职责索引**;进度与验收以 [`px-roadmap.md`](./px-roadmap.md) 为准,勿再按 §9「未开始」判断现状)。
> §3b / §9 中仍可能出现 `design-intake`、`skills/novel/`、缺失文件路径等**历史表述**;磁盘真相见 `skills/dialogue/world-simulator/README.md`。
--- ---
@@ -85,7 +89,7 @@ npm run phase-demo # 交互,手动 /decide /approve /worker-ask
npm run phase-demo -- --auto # worker 自动占位完成 npm run phase-demo -- --auto # worker 自动占位完成
``` ```
### Phase A1 — 总管 LLM 接入(阶段机之上) ### Phase A1 — 编排器 LLM 接入(阶段机之上)
目标:在 PhaseRuntime 之上接 Main Agent不改动 phase-machine 规则。 目标:在 PhaseRuntime 之上接 Main Agent不改动 phase-machine 规则。
@@ -96,7 +100,7 @@ npm run phase-demo -- --auto # worker 自动占位完成
### Phase A2 — Skill 层(创作指南) ### Phase A2 — Skill 层(创作指南)
目标:`skills/` 批量存储 SKILL.md启动第一个询问是选 skill总管读 activeSkill。 目标:`skills/` 批量存储 SKILL.md启动第一个询问是选 skill编排器读 activeSkill。
| # | 文件 | 状态 | 干嘛的 | | # | 文件 | 状态 | 干嘛的 |
|---|---|---|---| |---|---|---|---|
@@ -107,7 +111,7 @@ npm run phase-demo -- --auto # worker 自动占位完成
| S04 | `src/skills/loader.ts` | todo | 解析 SKILL.md | | S04 | `src/skills/loader.ts` | todo | 解析 SKILL.md |
| S05 | `src/skills/registry.ts` | todo | listSkills() | | S05 | `src/skills/registry.ts` | todo | listSkills() |
| S06 | `src/skills/resolver.ts` | todo | 推断当前 stage | | S06 | `src/skills/resolver.ts` | todo | 推断当前 stage |
| S07 | `src/main-agent/skill-context.ts` | todo | 注入总管 prompt | | S07 | `src/main-agent/skill-context.ts` | todo | 注入编排器 prompt |
| S08 | `src/runtime/phase-machine.ts` | todo | 增加 skill_selection / skill_selected | | S08 | `src/runtime/phase-machine.ts` | todo | 增加 skill_selection / skill_selected |
| S09 | `src/cli/phase-demo.ts` | todo | 启动时 /select-skill | | S09 | `src/cli/phase-demo.ts` | todo | 启动时 /select-skill |
@@ -115,7 +119,7 @@ npm run phase-demo -- --auto # worker 自动占位完成
### Phase B — Tool Call 化 ### Phase B — Tool Call 化
目标:总管 / worker 从 JSON 决策改为 tool callRuntime 做 tool 校验与事件转换。 目标:编排器 / worker 从 JSON 决策改为 tool callRuntime 做 tool 校验与事件转换。
### Phase C — 真实 Worker ### Phase C — 真实 Worker
@@ -167,7 +171,7 @@ npm run phase-demo -- --auto # worker 自动占位完成
|---|---|---|---|---| |---|---|---|---|---|
| A06 | `src/types/runtime.ts` | done | 相位、事件、会话、产物、ResumeContext | `runtime-state-machine.md` §25 | | A06 | `src/types/runtime.ts` | done | 相位、事件、会话、产物、ResumeContext | `runtime-state-machine.md` §25 |
| A07 | `src/types/blackboard.ts` | done | BlackboardItem、TagIndex | `tag-blackboard.md` §2 | | A07 | `src/types/blackboard.ts` | done | BlackboardItem、TagIndex | `tag-blackboard.md` §2 |
| A08 | `src/types/tools.ts` | todo | 总管 tool、worker tool 的参数与结果类型 | `tool-contracts.md` | | A08 | `src/types/tools.ts` | todo | 编排器 tool、worker tool 的参数与结果类型 | `tool-contracts.md` |
**A06 职责:** **A06 职责:**
- 定义 `RuntimePhase`5 种) - 定义 `RuntimePhase`5 种)
@@ -178,7 +182,7 @@ npm run phase-demo -- --auto # worker 自动占位完成
**A07 职责Phase E 迁移后):** **A07 职责Phase E 迁移后):**
- 定义 `BlackboardItem`id、tag、content、source、metadata - 定义 `BlackboardItem`id、tag、content、source、metadata
- 定义 `BlackboardTagIndex`(给总管tag + source无 content - 定义 `BlackboardTagIndex`(给编排器tag + source无 content
- 定义 `BlackboardWrite`worker 写回) - 定义 `BlackboardWrite`worker 写回)
**A08 职责Phase B 再写):** **A08 职责Phase B 再写):**
@@ -218,7 +222,7 @@ npm run phase-demo -- --auto # worker 自动占位完成
| A11 | `src/blackboard/blackboard.ts` | done | listTagIndex、queryByPatterns、write | `tag-blackboard.md` §2 | | A11 | `src/blackboard/blackboard.ts` | done | listTagIndex、queryByPatterns、write | `tag-blackboard.md` §2 |
**A11 职责:** **A11 职责:**
- `listTagIndex()` — 给总管 - `listTagIndex()` — 给编排器
- `queryByPatterns()` — 给 worker 注入 - `queryByPatterns()` — 给 worker 注入
- `write()` — 按 tag 写回 - `write()` — 按 tag 写回
- `getContentByTag()` / `getLatestByTag()` - `getContentByTag()` / `getLatestByTag()`
@@ -244,12 +248,12 @@ npm run phase-demo -- --auto # worker 自动占位完成
--- ---
### 4.6 总管 LLM ### 4.6 编排器 LLM
| # | 文件 | 状态 | 干嘛的 | 对应文档 | | # | 文件 | 状态 | 干嘛的 | 对应文档 |
|---|---|---|---|---| |---|---|---|---|---|
| A14 | `src/main-agent/main-agent.ts` | done | 总管:只选 worker读 tag 索引 | `tag-blackboard.md` §6 | | 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 | | A15 | `src/main-agent/prompts.ts` | todo | 编排器 prompt 拆分 | `tag-blackboard.md` §6 |
**A14 职责:** **A14 职责:**
- `MainAgent.decide(context)` — 调 LLM返回 `MainAgentDecision` - `MainAgent.decide(context)` — 调 LLM返回 `MainAgentDecision`
@@ -258,8 +262,8 @@ npm run phase-demo -- --auto # worker 自动占位完成
- `DEFAULT_WORKERS` — 第一版可用 worker 列表 - `DEFAULT_WORKERS` — 第一版可用 worker 列表
**约束:** **约束:**
- 总管不读黑板 value - 编排器不读黑板 value
- 总管不直接改 phase - 编排器不直接改 phase
- 不含 question-worker提问是 worker 能力) - 不含 question-worker提问是 worker 能力)
**A15 职责(可选拆分):** 把 prompt 从 main-agent.ts 抽出来,方便迭代。 **A15 职责(可选拆分):** 把 prompt 从 main-agent.ts 抽出来,方便迭代。
@@ -275,12 +279,12 @@ npm run phase-demo -- --auto # worker 自动占位完成
**A16 职责:** **A16 职责:**
- `RuntimeOrchestrator` — 对外 APIstart、submitUserInput、approve、accept 等 - `RuntimeOrchestrator` — 对外 APIstart、submitUserInput、approve、accept 等
- `dispatch(event)` — 调 `applyEvent`,处理 `PhaseEffect` - `dispatch(event)` — 调 `applyEvent`,处理 `PhaseEffect`
- `runMainAgent()` — phase=running 时调总管 - `runMainAgent()` — phase=running 时调编排器
- `runStubWorker()` — 第一版占位 workerPhase C 替换) - `runStubWorker()` — 第一版占位 workerPhase C 替换)
- `resumeStubWorker()` — worker 中途提问后恢复 - `resumeStubWorker()` — worker 中途提问后恢复
**约束:** **约束:**
- 唯一调用阶段机和总管的地方 - 唯一调用阶段机和编排器的地方
- user 事件approve / accept只从 CLI / API 进入,不从 LLM 进入 - user 事件approve / accept只从 CLI / API 进入,不从 LLM 进入
--- ---
@@ -307,7 +311,7 @@ npm run phase-demo -- --auto # worker 自动占位完成
| B01 | `src/types/tools.ts` | tool 类型定义 | | B01 | `src/types/tools.ts` | tool 类型定义 |
| B02 | `src/runtime/tool-registry.ts` | 注册 tool、校验参数、tool → event | | B02 | `src/runtime/tool-registry.ts` | 注册 tool、校验参数、tool → event |
| B03 | `src/main-agent/main-agent.ts` | 改为 tool calling 模式 | | B03 | `src/main-agent/main-agent.ts` | 改为 tool calling 模式 |
| B04 | `src/runtime/tool-handlers/main-agent.ts` | 总管 tool 处理器 | | B04 | `src/runtime/tool-handlers/main-agent.ts` | 编排器 tool 处理器 |
| B05 | `src/runtime/tool-handlers/worker.ts` | worker tool 处理器ask_user / submit | | B05 | `src/runtime/tool-handlers/worker.ts` | worker tool 处理器ask_user / submit |
**B02 职责:** **B02 职责:**
@@ -372,7 +376,7 @@ type WorkerRunOutcome =
Phase A0可运行阶段机 ✅ 完成 Phase A0可运行阶段机 ✅ 完成
phase-machine + phase-runtime + phase-demo + 测试 phase-machine + phase-runtime + phase-demo + 测试
Phase A1总管 LLM ✅ 有初版orchestrator + run.ts Phase A1编排器 LLM ✅ 有初版orchestrator + run.ts
下一步orchestrator 应基于 PhaseRuntime 重构 下一步orchestrator 应基于 PhaseRuntime 重构
Phase Btool call 未开始 Phase Btool call 未开始

View File

@@ -1,27 +1,30 @@
# 总管 Skill 格式Orchestrator / Manifest # 编排器 Skill 格式Orchestrator / Manifest
> **文档层级Skill 包 manifest 格式(非系统架构)。** > **文档层级Skill 包 manifest 格式(非系统架构)。**
> 总管与相位机边界见 [`architecture.md`](./architecture.md)、[`runtime-state-machine.md`](./runtime-state-machine.md)。 > 编排器与相位机边界见 [`architecture.md`](./architecture.md)、[`runtime-state-machine.md`](./runtime-state-machine.md)。
> **现行包落地**见 [`skills/dialogue/world-simulator/README.md`](../skills/dialogue/world-simulator/README.md)、[`world-simulator-modules.md`](./world-simulator-modules.md)。
## 1. 定位 ## 1. 定位
**orchestrator.md** = 本包的 **manifest**:注册有哪些 capability、如何验收、何时可进 play。 **orchestrator.md** = 本包的 **manifest**:注册有哪些 design worker、如何验收、何时可进 play。
**不**写逐步流水线剧本 **不**写逐步流水线工作流计划
**创作方法**见 **`design-orchestrator-guide.md`**(三大步、表、自检)。 **创作方法**见 **`design-orchestrator-guide.md`**(三大步、表、自检)。
```text ```text
新建作品 → 默认包 新建作品 → UI 选配方recipes/)→ 默认包
→ designdesign-intake → 设计.worker集 JSON实例声明 → design-flow → 设计.创作流程(工作流计划 / 近期步骤 DAG
→ 反复 design-step注入 modules/{id}/prompt.md→ 收成 设计.worker集运行规格
→ 用户验收 → 用户手动进 play → 用户验收 → 用户手动进 play
→ playAgent 按 Worker 声明 invoke worker → play编排器按运行规格 invoke 执行单元
``` ```
| 谁决定 | 什么 | | 谁决定 | 什么 |
|--------|------| |--------|------|
| **Agent** | 何时 invoke 哪个 worker idtool loop | | **编排器** | 何时 invoke 哪个 worker idtool loop |
| **Manifest** | design worker 列表、验收策略、readiness | | **Manifest** | design worker 列表、验收策略、readiness |
| **Worker 集** | 本实例启哪些 worker、表、常驻上下文、副作用 | | **运行规格** | 本实例启哪些执行单元、表、常驻上下文、副作用 |
| **templates** | design-intake 合并用的可选默认契约(非运行时权威) | | **templates** | design 缺省时合并用的可选默认契约(非运行时权威) |
| **recipes / modules** | 配方起点 / 技能工序正文 |
`architecture.md``creation-playbook.md``design-orchestrator-guide.md` `architecture.md``creation-playbook.md``design-orchestrator-guide.md`
@@ -32,15 +35,20 @@
```text ```text
skills/dialogue/world-simulator/ skills/dialogue/world-simulator/
├── orchestrator.md ├── orchestrator.md
├── shared-context.md # 可选 ├── recipes/ # 配方选项
├── modules/ # 技能 prompt 切片
├── worker-templates/ # 可选 ref 模板design 缺省) ├── worker-templates/ # 可选 ref 模板design 缺省)
└── workers/ └── workers/
── design-intake/SKILL.md ── design-flow/SKILL.md
├── design-step/SKILL.md
└── opening-generator/SKILL.md
``` ```
- 文件固定名 **`orchestrator.md`**。 - 文件固定名 **`orchestrator.md`**。
- `registry.yaml``path` 指向它。 - `registry.yaml``path` 指向它。
旧名 `design-intake` / `design-core`**已移除**;勿再写回磁盘。
--- ---
## 3. Frontmatter ## 3. Frontmatter
@@ -49,11 +57,13 @@ skills/dialogue/world-simulator/
--- ---
name: world-simulator name: world-simulator
description: > description: >
默认能力库Worker 集即实例声明 默认技能库:用户选配方 → 编排工作流计划 → 逐步执行技能
category: dialogue category: dialogue
bookKind: dialogue bookKind: dialogue
workers: workers:
- design-intake - design-flow
- design-step
- opening-generator
demandTag: 用户.需求 demandTag: 用户.需求
startupMode: agent-first startupMode: agent-first
uiPrompt: | uiPrompt: |
@@ -69,11 +79,11 @@ uiPrompt: |
## Skill 注册表 ## Skill 注册表
## Instance Ready / 进入游玩 ## Instance Ready / 进入游玩
## 验收策略 ## 验收策略
## 总管优先行为 ## 编排器优先行为
## 禁用行为 ## 禁用行为
``` ```
**不应包含:** 「第 N 步必须跑某 worker」管道剧本 **不应包含:** 「第 N 步必须跑某 worker」管道计划
方法细节指向 `design-orchestrator-guide.md`,勿在 manifest 重复长文。 方法细节指向 `design-orchestrator-guide.md`,勿在 manifest 重复长文。
--- ---
@@ -84,8 +94,9 @@ uiPrompt: |
| id | 说明 | | id | 说明 |
|----|------| |----|------|
| design-intake | 产出 设计.worker集 JSON | | design-flow | 编排近期 `设计.创作流程`(增量 DAG |
| (可选)开局赋初值 | 创作末尾可选,非每轮 | | design-step | 执行当前能力步;注入 `modules/{id}/prompt.md` |
| opening-generator | (可选)开场白,非每轮 |
### Play ### Play
@@ -105,7 +116,9 @@ uiPrompt: |
| skill | requiresApproval | acceptanceMode | | skill | requiresApproval | acceptanceMode |
|-------|------------------|----------------| |-------|------------------|----------------|
| design-intake | true | user_confirmed | | design-flow | true | user_confirmed(流程骨架) |
| design-step | true | user_confirmed能力产物 |
| opening-generator | true | user_confirmed |
play**无**每轮强制验收;用户新输入 = 认可上轮终稿;重 roll 替代 reject。 play**无**每轮强制验收;用户新输入 = 认可上轮终稿;重 roll 替代 reject。

View File

@@ -11,20 +11,20 @@
| 项 | 决定 | | 项 | 决定 |
|----|------| |----|------|
| 日常玩法 | **AIRP/交互** + **长文/爽文**(同一内核) | | 日常玩法 | **AIRP/交互** + **长文/爽文**(同一内核) |
| 导演 Skill | 新建时 **UI 选择**能包;初期可只有 1 项(默认选中) | | 编排器 Skill | 新建时 **UI 选择**能包;初期可只有 1 项(默认选中) |
| 剧本层 | **动态**:听用户说话谈 Worker 集 + tool loop不做死板剧本选单/DAG | | 工作流计划层 | **动态**:听用户说话谈 Worker 集 + tool loop不做死板流程选单/DAG |
| UI | **抄参考**即可,不自研美学 | | UI | **抄参考**即可,不自研美学 |
| 硬指标 | **存档 / 续作稳定** | | 硬指标 | **存档 / 续作稳定** |
| 多导演 | 仅当方法边界真不同时再加包;爽文≠新导演 | | 多配方 | 仅当方法边界真不同时再加包;爽文≠新配方 |
### 0.2 成功标尺 ### 0.2 成功标尺
| 级别 | 含义 | | 级别 | 含义 |
|------|------| |------|------|
| **L1 可演示** | 带路能跑通一轮 | | **L1 可演示** | 带路能跑通一轮 |
| **L2 可自助** | 选导演 → 创作 → 玩/写,少踩坑 | | **L2 可自助** | 选配方 → 创作 → 玩/写,少踩坑 |
| **L3 可日常** | 双线存档续作可靠;少死循环 | | **L3 可日常** | 双线存档续作可靠;少死循环 |
| **L4 可扩展** | 新导演包或隔离模式不改内核边界 | | **L4 可扩展** | 新配方包或隔离模式不改内核边界 |
--- ---
@@ -32,7 +32,7 @@
| 阶段 | 名称 | 目标标尺 | 核心交付 | 状态 | | 阶段 | 名称 | 目标标尺 | 核心交付 | 状态 |
|------|------|----------|----------|------| |------|------|----------|----------|------|
| **PX0** | 双线可日常最小集 | L2→摸 L3 | 导演选择 UI线 A 扮演 + 线 B 长文/爽文主路径;**存档硬稳定**失败出口UI 只抄缺口 | **进行中(核心已落地)** | | **PX0** | 双线可日常最小集 | L2→摸 L3 | 配方选择 UI线 A 扮演 + 线 B 长文/爽文主路径;**存档硬稳定**失败出口UI 只抄缺口 | **进行中(核心已落地)** |
| **PX1** | 创作体验 | L3 design | 规格可读可改、进度可见、表/黑板可手改、instance 改规格 | **进行中(定稿存读+黑板改+进度面板已有)** | | **PX1** | 创作体验 | L3 design | 规格可读可改、进度可见、表/黑板可手改、instance 改规格 | **进行中(定稿存读+黑板改+进度面板已有)** |
| **PX2** | 游玩/写作体验 | L3 play | 阅读主舞台(抄)、状态抽屉、重 roll 顺手、副作用调度、多 run 线打磨 | 未开始 | | **PX2** | 游玩/写作体验 | L3 play | 阅读主舞台(抄)、状态抽屉、重 roll 顺手、副作用调度、多 run 线打磨 | 未开始 |
| **PX3** | 运行可信 | L3 加固 | Context Trace、调度预算、规格钉版本、mock E2E | 未开始 | | **PX3** | 运行可信 | L3 加固 | Context Trace、调度预算、规格钉版本、mock E2E | 未开始 |
@@ -40,7 +40,7 @@
| **PX5** | 隔离 + 调试 | L4 | 私有上下文、泄漏测试Trace/成本/分支调试台 | 未开始 | | **PX5** | 隔离 + 调试 | L4 | 私有上下文、泄漏测试Trace/成本/分支调试台 | 未开始 |
```text ```text
现在 → PX0存档+双线+导演UI 现在 → PX0存档+双线+编排器UI
→ PX1创作好改 → PX1创作好改
→ PX2玩/写好用) → PX2玩/写好用)
→ PX3可信可测 → PX3可信可测
@@ -63,32 +63,32 @@
| 序 | 工作包 | 内容 | 验收要点 | | 序 | 工作包 | 内容 | 验收要点 |
|----|--------|------|----------| |----|--------|------|----------|
| 1 | **WP-S** 存档稳定 | 续作相位正确;手动存/列表/加载;正文与关键 tag 不丢 | 线 A、B 各存读一轮,不手改磁盘 | | 1 | **WP-S** 存档稳定 | 续作相位正确;手动存/列表/加载;正文与关键 tag 不丢 | 线 A、B 各存读一轮,不手改磁盘 |
| 2 | **WP-D** 导演选择 | 新建作品 UI 选导演registry 列表;仅 1 项时默认选中 | 能选中并进入该包创作 | | 2 | **WP-D** 配方选择 | 新建作品 UI 选配方registry 列表;仅 1 项时默认选中 | 能选中并进入该包创作 |
| 3 | **WP-A** 进出与失败 | glossary 底线;`waiting_user` 有主按钮LLM/worker 失败可重试 | 无死胡同、无裸 id 挡路 | | 3 | **WP-A** 进出与失败 | glossary 底线;`waiting_user` 有主按钮LLM/worker 失败可重试 | 无死胡同、无裸 id 挡路 |
| 4 | **WP-R** 线 A | 扮演 ≥3 回合不卡 | A-GP15 | | 4 | **WP-R** 线 A | 扮演 ≥3 回合不卡 | A-GP15 |
| 5 | **WP-L** 线 B | 引导+template 能谈成写手规格≥2 段正文;续作不丢文 | B-GP15 | | 5 | **WP-L** 线 B | 引导+template 能谈成写手规格≥2 段正文;续作不丢文 | B-GP15 |
| 6 | **WP-U** UI 抄补 | 仅补存档/确认/选导演等缺口控件 | 不按 ui-design 大重构 | | 6 | **WP-U** UI 抄补 | 仅补存档/确认/选配方等缺口控件 | 不按 ui-design 大重构 |
| 7 | **WP-E** 闸门 | 双线冷启动+续作验收;勾选 DoD | 全绿才出 PX0 | | 7 | **WP-E** 闸门 | 双线冷启动+续作验收;勾选 DoD | 全绿才出 PX0 |
### 2.2 黄金路径(摘要) ### 2.2 黄金路径(摘要)
- **线 A**:选导演 → 扮演意图 → 验收 → ≥3 回合 → 存档 → 续作/读档 - **线 A**:选配方 → 扮演意图 → 验收 → ≥3 回合 → 存档 → 续作/读档
- **线 B**:选导演 → 爽文/长篇意图 → 验收写手规格 → ≥2 段正文 → 存档含正文 → 续作/读档 - **线 B**:选配方 → 爽文/长篇意图 → 验收写手规格 → ≥2 段正文 → 存档含正文 → 续作/读档
### 2.3 非范围 ### 2.3 非范围
死板剧本选单;自研精美 UITrace隔离完整副作用导演商店列表可扩展P0 不追求多包运营)。 死板流程选单;自研精美 UITrace隔离完整副作用配方商店列表可扩展P0 不追求多包运营)。
### 2.4 DoD ### 2.4 DoD
- [ ] WP-SE 完成 - [ ] WP-SE 完成
- [ ] 线 A、线 B 黄金路径各冷启动 + 续作通过 - [ ] 线 A、线 B 黄金路径各冷启动 + 续作通过
- [ ] 导演选择 UI 可用(可仅一项) - [ ] 配方选择 UI 可用(可仅一项)
- [ ] 更新本文状态列 + `architecture.md` §13 - [ ] 更新本文状态列 + `architecture.md` §13
### 2.5 挂载 ### 2.5 挂载
`web/`(新建选导演、saves`session-manager``skill-catalog` / registry、`phase-runtime`、引导与 `worker-templates` `web/`(新建选配方、saves`session-manager``skill-catalog` / registry、`phase-runtime`、引导与 `worker-templates`
--- ---
@@ -149,7 +149,7 @@ P0 已要求最小长文/爽文闭环。本阶段加深:
| 隔离 | 私有上下文、公私事件、泄漏测试(依 Trace | | 隔离 | 私有上下文、公私事件、泄漏测试(依 Trace |
| 调试 | 调度时间线、Trace 检查器、Token/成本、分支树 | | 调试 | 调度时间线、Trace 检查器、Token/成本、分支树 |
若隔离需要**不同方法边界**,以**新导演包**形式加入UI 多一项),仍保持包内剧本动态。 若隔离需要**不同方法边界**,以**新配方包**形式加入UI 多一项),仍保持包内工作流计划动态。
--- ---
@@ -157,7 +157,7 @@ P0 已要求最小长文/爽文闭环。本阶段加深:
- Mastra / LangGraph 换相位机Next 重写前端 - Mastra / LangGraph 换相位机Next 重写前端
- 完整事件溯源 + SQLite 近端必达 - 完整事件溯源 + SQLite 近端必达
- 题材固定 instantiate 管道;死板剧本选单 - 题材固定 instantiate 管道;死板流程选单
- 把创作方法长文塞回系统架构文 - 把创作方法长文塞回系统架构文
--- ---
@@ -166,7 +166,7 @@ P0 已要求最小长文/爽文闭环。本阶段加深:
| 里程碑 | 退出 | 产出 | | 里程碑 | 退出 | 产出 |
|--------|------|------| |--------|------|------|
| **M0** | PX0 DoD | 双线验收记录;导演 UI存档稳定 | | **M0** | PX0 DoD | 双线验收记录;编排器 UI存档稳定 |
| **M1** | PX1+PX2 DoD | 内部「可日常」说明 | | **M1** | PX1+PX2 DoD | 内部「可日常」说明 |
| **M2** | PX3 DoD | Trace/预算/E2E 绿灯 | | **M2** | PX3 DoD | Trace/预算/E2E 绿灯 |
| **M3** | PX4 或 PX5 | 长文加深或隔离/调试演示 | | **M3** | PX4 或 PX5 | 长文加深或隔离/调试演示 |

View File

@@ -2,11 +2,16 @@
> **文档层级Skill 包格式薄层(非系统架构)。** > **文档层级Skill 包格式薄层(非系统架构)。**
> 运行内核见 [`architecture.md`](./architecture.md);创作方法见下。 > 运行内核见 [`architecture.md`](./architecture.md);创作方法见下。
> **现行磁盘布局**见 [`skills/dialogue/world-simulator/README.md`](../skills/dialogue/world-simulator/README.md)。
**创作方法(三大步、表、自检、正推)** 的权威文档是: **创作方法(三大步、表、自检、正推)** 的权威文档是:
**[`design-orchestrator-guide.md`](./design-orchestrator-guide.md)** **[`design-orchestrator-guide.md`](./design-orchestrator-guide.md)**
能力 / 编排器清单:
**[`world-simulator-modules.md`](./world-simulator-modules.md)**
本文只保留:**如何在仓库里建包、Worker 集弱结构示例、与旧概念对照**。不要在本文重复长方法文。 本文只保留:**如何在仓库里建包、Worker 集弱结构示例、与旧概念对照**。不要在本文重复长方法文。
格式字段见 `orchestrator-skill-format.md``worker-skill-format.md`;上下文见 `context-assembly.md` 格式字段见 `orchestrator-skill-format.md``worker-skill-format.md`;上下文见 `context-assembly.md`
@@ -14,10 +19,11 @@
**设计顺序(概念):** **设计顺序(概念):**
```text ```text
1. 用户意图 → design-intake按 design-orchestrator-guide→ 设计.worker集 JSON 1. 用户选配方 → design-flow 排出近期 设计.创作流程
2. 需要时合并 worker-templates 默认契约(仅 design 缺省) 2. 反复 design-stepmodules 能力切片)→ 收成 设计.worker集 JSON
3. 用户验收 → 用户手动进 play 3. 需要时合并 worker-templates 默认契约(仅 design 缺省)
4. play按声明调度表维护/副作用边沿触发 4. 用户验收 → 用户手动进 play
5. play按声明调度表维护/副作用边沿触发
``` ```
--- ---
@@ -36,9 +42,11 @@
Worker 集不是闭集枚举,也不是逐步管道。方法见 `design-orchestrator-guide.md` Worker 集不是闭集枚举,也不是逐步管道。方法见 `design-orchestrator-guide.md`
### 0.2 design-intake ### 0.2 design-flow / design-step
与用户对话增量更新草稿accept 后即实例规格。进 play **由用户手动决定** 与用户对话,经编排器能力编排与逐步执行,增量更新草稿accept 后即实例规格。进 play **由用户手动决定**
旧名 `design-intake` 仅作兼容别名出现在部分代码注释中,**磁盘上已不存在**。
### 0.3 弱结构示例JSON ### 0.3 弱结构示例JSON

View File

@@ -2,6 +2,10 @@
> **文档层级Skill 包格式(非系统架构)。** > **文档层级Skill 包格式(非系统架构)。**
> 系统级模块与调度边界见 [`architecture.md`](./architecture.md)。 > 系统级模块与调度边界见 [`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` 已废弃)。
## 1. 定位:两层 Skill ## 1. 定位:两层 Skill
@@ -9,50 +13,50 @@
| 类型 | 路径 | 消费者 | 写什么 | | 类型 | 路径 | 消费者 | 写什么 |
|------|------|--------|--------| |------|------|--------|--------|
| **总管 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**、怎么做 | | **Worker Skill** | `workers/{workerId}/SKILL.md` | Worker Agent | **inputTags/outputTags**、怎么做 |
```text ```text
选 weird-rules-short总管 Skill 选 weird-rules-short编排器 Skill
总管brief 齐了 → run ruleset-workerinput=[project.brief] 编排器brief 齐了 → run ruleset-workerinput=[project.brief]
→ Worker读 workers/ruleset-worker/SKILL.md → 写 core / rules / commentary → Worker读 workers/ruleset-worker/SKILL.md → 写 core / rules / commentary
总管rules accepted → run review-worker 编排器rules accepted → run review-worker
→ Worker读 workers/review-worker/SKILL.md → 评估怎么做 → Worker读 workers/review-worker/SKILL.md → 评估怎么做
``` ```
**何时评估** = 总管 Skill 的 Worker 编排表。 **何时评估** = 编排器 Skill 的 Worker 编排表。
**如何评估** = review-worker 的 Worker Skill。 **如何评估** = review-worker 的 Worker Skill。
详细规范: 详细规范:
- 总管 Skill → `docs/orchestrator-skill-format.md` - 编排器 Skill → `docs/orchestrator-skill-format.md`
- Worker Skill → `docs/worker-skill-format.md` - Worker Skill → `docs/worker-skill-format.md`
旧称「Skill = 创作说明书」仍成立,但说明书 **拆成编排(总管与执行worker两份** 旧称「Skill = 创作说明书」仍成立,但说明书 **拆成编排(编排器与执行worker两份**
```text ```text
会话开始 会话开始
→ 询问 1选哪个总管 Skillskills/{bookKind}/{name}/orchestrator.md → 询问 1选哪个编排器 Skillskills/{bookKind}/{name}/orchestrator.md
→ 加载总管 Skill → 加载编排器 Skill
→ 询问 2总管 Skill「## 启动询问」 → 询问 2编排器 Skill「## 启动询问」
→ 之后总管按「Worker 编排」调度Worker 读本 skill 包内 workers/{id}/SKILL.md → 之后编排器按「Worker 编排」调度Worker 读本 skill 包内 workers/{id}/SKILL.md
``` ```
--- ---
## 2. 存储位置 ## 2. 存储位置
Skill 以 **Skill 包skill pack** 为单位:一个总管 + 其专属 workers**同包绑定,不跨包复用 worker**。 Skill 以 **Skill 包skill pack** 为单位:一个编排器 + 其专属 workers**同包绑定,不跨包复用 worker**。
```text ```text
skills/ skills/
├── registry.yaml ├── registry.yaml
├── novel/ # Book 形态 ├── novel/ # Book 形态
│ ├── basic/ │ ├── basic/
│ │ └── orchestrator.md # 总管 Skill │ │ └── orchestrator.md # 编排器 Skill
│ ├── weird-rules-short/ │ ├── weird-rules-short/
│ │ ├── orchestrator.md # 总管:何时调谁、黑板 key │ │ ├── orchestrator.md # 编排器:何时调谁、黑板 key
│ │ └── workers/ # 本总管专属,不与其他 skill 共享 │ │ └── workers/ # 本编排器专属,不与其他 skill 共享
│ │ ├── write-rules/ │ │ ├── write-rules/
│ │ │ └── SKILL.md # 规则怪谈:怎么写规则+解析 │ │ │ └── SKILL.md # 规则怪谈:怎么写规则+解析
│ │ └── review/ │ │ └── review/
@@ -74,13 +78,13 @@ skills/
```text ```text
第一层文件夹 = bookKindnovel | dialogue决定 Book 存储结构 第一层文件夹 = bookKindnovel | dialogue决定 Book 存储结构
第二层文件夹 = 一个 skill 包,名与 frontmatter.name 一致 第二层文件夹 = 一个 skill 包,名与 frontmatter.name 一致
orchestrator.md 总管 Skill编排、启动询问、验收 orchestrator.md 编排器 Skill编排、启动询问、验收
workers/{id}/ 本包专属 workerid 在包内唯一即可 workers/{id}/ 本包专属 workerid 在包内唯一即可
Worker 不复用novel-standard 的 outline worker ≠ weird-rules-short 的任何 worker Worker 不复用novel-standard 的 outline worker ≠ weird-rules-short 的任何 worker
registry.yaml 的 path 指向 orchestrator.md如 novel/weird-rules-short/orchestrator.md registry.yaml 的 path 指向 orchestrator.md如 novel/weird-rules-short/orchestrator.md
``` ```
**为何不复用 worker** 同一「产出形状」(如规则表)在不同总管下的写法、Rubric、自检完全不同共享 worker 会把体裁细节塞进总管或搞混上下文。需要相似流程时 **复制 worker 包再改**,而不是引用全局 worker。 **为何不复用 worker** 同一「产出形状」(如规则表)在不同编排器下的写法、Rubric、自检完全不同共享 worker 会把体裁细节塞进编排器或搞混上下文。需要相似流程时 **复制 worker 包再改**,而不是引用全局 worker。
与 Cursor skill 的区别: 与 Cursor skill 的区别:
@@ -89,7 +93,7 @@ registry.yaml 的 path 指向 orchestrator.md如 novel/weird-rules-short/orch
| 位置 | `.cursor/skills/` | `skills/` | | 位置 | `.cursor/skills/` | `skills/` |
| 触发 | Agent 自动或显式引用 | **会话开始必须选一个** | | 触发 | Agent 自动或显式引用 | **会话开始必须选一个** |
| 内容 | 通用任务指南 | **创作流程 + 思维链 + 询问策略** | | 内容 | 通用任务指南 | **创作流程 + 思维链 + 询问策略** |
| 消费者 | Cursor Agent | 总管 LLM | | 消费者 | Cursor Agent | 编排器 LLM |
--- ---
@@ -163,9 +167,9 @@ tags: [novel, outline, draft]
## 创作总纲 ## 创作总纲
(给总管:这类内容是什么、总体顺序、禁忌) (给编排器:这类内容是什么、总体顺序、禁忌)
## 总管思维链 ## 编排器思维链
(每轮决策前先检查什么、如何选 worker (每轮决策前先检查什么、如何选 worker
@@ -175,7 +179,7 @@ tags: [novel, outline, draft]
## 询问策略 ## 询问策略
### 总管应先问 ### 编排器应先问
### 交给 Worker 问 ### 交给 Worker 问
## 推荐 Worker ## 推荐 Worker
@@ -188,7 +192,7 @@ tags: [novel, outline, draft]
```yaml ```yaml
--- ---
name: novel-standard # 必需,唯一 id[a-z0-9-] name: novel-standard # 必需,唯一 id[a-z0-9-]
description: > # 必需,供启动时向用户展示、供总管匹配 description: > # 必需,供启动时向用户展示、供编排器匹配
第三人称描述 WHAT + WHEN。 第三人称描述 WHAT + WHEN。
category: novel # 必需Book 形态,见 §3.0 category: novel # 必需Book 形态,见 §3.0
bookKind: novel # 建议与 category 对齐;选定后 Book 结构固定 bookKind: novel # 建议与 category 对齐;选定后 Book 结构固定
@@ -206,13 +210,13 @@ suggestedWorkers: # 可选,本 skill 常用 worker
| 字段 | 必需 | 用途 | | 字段 | 必需 | 用途 |
|---|---|---| |---|---|---|
| `name` | ✅ | skill id通常与文件名一致不含 .md | | `name` | ✅ | skill id通常与文件名一致不含 .md |
| `description` | ✅ | 启动选择列表展示;总管判断用户描述是否匹配 | | `description` | ✅ | 启动选择列表展示;编排器判断用户描述是否匹配 |
| `category` | ✅ | 与 `bookKind` 一致:`novel` \| `dialogue` | | `category` | ✅ | 与 `bookKind` 一致:`novel` \| `dialogue` |
| `bookKind` | 建议 | 选定后 Book 结构固定;缺省时由所在文件夹推断 | | `bookKind` | 建议 | 选定后 Book 结构固定;缺省时由所在文件夹推断 |
| `tags` | | 体裁细分:`weird_rules``standard` 等 | | `tags` | | 体裁细分:`weird_rules``standard` 等 |
| `path` | registry | 相对路径,如 `novel/weird-rules-short.md` | | `path` | registry | 相对路径,如 `novel/weird-rules-short.md` |
| `defaultFlowId` | | 选中后默认 execution flow | | `defaultFlowId` | | 选中后默认 execution flow |
| `suggestedWorkers` | | 总管选 worker 时的白名单提示 | | `suggestedWorkers` | | 编排器选 worker 时的白名单提示 |
### 3.2 撰写标准:写作生命周期(推荐) ### 3.2 撰写标准:写作生命周期(推荐)
@@ -237,7 +241,7 @@ Skill 文件本质上是**给 LLM 与 Runtime 读的字符串规格**。下面
| **写作中 · 分步引导** | `## 推荐阶段` + `## 示例` + `## 禁用行为` | 阶段链、每步约束、好/坏示例;对应 worker 与产出 key | | **写作中 · 分步引导** | `## 推荐阶段` + `## 示例` + `## 禁用行为` | 阶段链、每步约束、好/坏示例;对应 worker 与产出 key |
| **写作后 · 自检润色** | `## 自检清单` + `## 验收策略` | 产出前检查点LLM 自审 vs 人工 vs 程序验收 | | **写作后 · 自检润色** | `## 自检清单` + `## 验收策略` | 产出前检查点LLM 自审 vs 人工 vs 程序验收 |
| **质量评估** | `## 质量评估标准` | 可量化维度 + 各 stage 的 acceptanceMode | | **质量评估** | `## 质量评估标准` | 可量化维度 + 各 stage 的 acceptanceMode |
| **编排** | `## 总管思维链` + `## 询问策略` + `## 推荐 Worker` | 总管如何调度;谁向用户提问 | | **编排** | `## 编排器思维链` + `## 询问策略` + `## 推荐 Worker` | 编排器如何调度;谁向用户提问 |
不必每个 skill 都写独立 `# 写作前` 大标题;**用统一章节名即可**,内容覆盖上表即可。 不必每个 skill 都写独立 `# 写作前` 大标题;**用统一章节名即可**,内容覆盖上表即可。
@@ -266,7 +270,7 @@ Skill 文件本质上是**给 LLM 与 Runtime 读的字符串规格**。下面
#### `## 自检清单`(必需) #### `## 自检清单`(必需)
写作后、提交验收前worker 或总管应过的检查点(字符串列表即可): 写作后、提交验收前worker 或编排器应过的检查点(字符串列表即可):
```markdown ```markdown
## 自检清单 ## 自检清单
@@ -298,7 +302,7 @@ suggestedWorkers: …
## 启动询问 # 写作前 · 需求分析 ## 启动询问 # 写作前 · 需求分析
## 创作总纲 ## 创作总纲
## 总管思维链 ## 编排器思维链
## 推荐阶段 # 写作中 · 分步引导 ## 推荐阶段 # 写作中 · 分步引导
## 询问策略 ## 询问策略
## 推荐 Worker ## 推荐 Worker
@@ -310,7 +314,7 @@ suggestedWorkers: …
## Book 结构 # 可选novel / dialogue 形态说明 ## Book 结构 # 可选novel / dialogue 形态说明
``` ```
代码当前**结构化解析**的仍主要是 `## 启动询问`;其余章节整段注入总管 prompt`buildSkillContext`)。**全部是 Markdown 字符串,不矛盾。** 代码当前**结构化解析**的仍主要是 `## 启动询问`;其余章节整段注入编排器 prompt`buildSkillContext`)。**全部是 Markdown 字符串,不矛盾。**
### 3.3 正文必需章节(检查清单) ### 3.3 正文必需章节(检查清单)
@@ -325,8 +329,8 @@ suggestedWorkers: …
| **自检清单** | 写后 | 提交验收前的检查点 | | **自检清单** | 写后 | 提交验收前的检查点 |
| **验收策略** | 写后 | 各 stage 的 acceptanceMode | | **验收策略** | 写后 | 各 stage 的 acceptanceMode |
| **质量评估标准** | 质量 | 可量化维度 + **接受度(预留)** | | **质量评估标准** | 质量 | 可量化维度 + **接受度(预留)** |
| **总管思维链** | 编排 | 每轮决策检查 | | **编排器思维链** | 编排 | 每轮决策检查 |
| **询问策略** | 编排 | 总管问 vs worker 问 | | **询问策略** | 编排 | 编排器问 vs worker 问 |
| **推荐 Worker** | 编排 | 与 suggestedWorkers 一致 | | **推荐 Worker** | 编排 | 与 suggestedWorkers 一致 |
可选:`## Book 结构``examples.md` 外链。 可选:`## Book 结构``examples.md` 外链。
@@ -414,25 +418,25 @@ Runtime 写入 `用户.需求`(或 skill 指定的 startupTargetKey
阶段 2intake 启动询问 → 用户描述需求 → confirm → agent burst 阶段 2intake 启动询问 → 用户描述需求 → confirm → agent burst
``` ```
**Agent 根据需求推理 worker 集**`design-intake`),不再让用户在 registry 里四选一。 **Agent 根据需求编排能力并收成 worker 集**`design-flow``design-step`),不再让用户在 registry 里四选一。
--- ---
## 6. 总管如何使用已选 Skill ## 6. 编排器如何使用已选 Skill
`session.slots.activeSkill` 加载后,总管 prompt 注入: `session.slots.activeSkill` 加载后,编排器 prompt 注入:
```text ```text
当前 skill: novel-standard 当前 skill: novel-standard
category: novel category: novel
创作总纲: SKILL.md 摘要或全文) 创作总纲: SKILL.md 摘要或全文)
当前推荐阶段: outline由 resolver 根据黑板推断) 当前推荐阶段: outline由 resolver 根据黑板推断)
询问策略: 总管应先问 briefoutline 细节交给 worker 询问策略: 编排器应先问 briefoutline 细节交给 worker
建议 worker: outline-worker, drafting-worker 建议 worker: outline-worker, drafting-worker
defaultFlowId: ghostwriting-flow defaultFlowId: ghostwriting-flow
``` ```
总管决策仍通过 tool / JSON 决策,**不**直接改 phase。 编排器决策仍通过 tool / JSON 决策,**不**直接改 phase。
--- ---
@@ -441,10 +445,14 @@ defaultFlowId: ghostwriting-flow
完整示例见仓库内真实文件(不要只在文档里维护一份): 完整示例见仓库内真实文件(不要只在文档里维护一份):
```text ```text
skills/novel/weird-rules-short.md skills/dialogue/world-simulator/orchestrator.md
skills/dialogue/theater-roleplay.md skills/dialogue/world-simulator/workers/design-flow/SKILL.md
skills/dialogue/world-simulator/modules/catalog.yaml
skills/dialogue/world-simulator/recipes/catalog.yaml
``` ```
(历史示例 `skills/novel/weird-rules-short``theater-roleplay` 已不在仓库。)
--- ---
## 8. 解析与加载(将来代码) ## 8. 解析与加载(将来代码)
@@ -463,7 +471,7 @@ listSkills() → SkillIndexEntry[]
loadSkill(skillId) → ParsedSkill含 startupInquiry 解析自 ## 启动询问) loadSkill(skillId) → ParsedSkill含 startupInquiry 解析自 ## 启动询问)
selectSkill(session, skillId) → session.slots.activeSkill selectSkill(session, skillId) → session.slots.activeSkill
getStartupPrompt(activeSkill) → 流程 2 展示文案 getStartupPrompt(activeSkill) → 流程 2 展示文案
buildSkillContext(activeSkill, blackboardIndex) → 总管 prompt 片段 buildSkillContext(activeSkill, blackboardIndex) → 编排器 prompt 片段
``` ```
--- ---
@@ -491,7 +499,7 @@ Creation Playbook概念
```text ```text
skills/ 目录 + 示例 orchestrator 包 skills/ 目录 + 示例 orchestrator 包
启动 → 自动绑定默认 orchestrator → intake描述需求 启动 → 自动绑定默认 orchestrator → intake描述需求
总管 prompt 注入 skill 摘要 编排器 prompt 注入 skill 摘要
registry.yaml 可选legacy 包 / 读档兼容) registry.yaml 可选legacy 包 / 读档兼容)
``` ```

View File

@@ -15,25 +15,26 @@ Runtime = 按声明拼接上下文;表字段 rev 合并
## 2. Skill 包、Worker 声明与 Book ## 2. Skill 包、Worker 声明与 Book
```text ```text
Skill 包 能力库 + design-intake + 可选 templates Skill 包 recipes + modules + design-flow/step + 可选 templates
设计.创作流程 近期能力步骤 DAGopen|closed
设计.worker集acceptedJSON 本实例 Worker 声明play 权威) 设计.worker集acceptedJSON 本实例 Worker 声明play 权威)
Session + 黑板 一次运行的实参 Session + 黑板 一次运行的实参
Book 过程、存档、资产book-storage.md Book 过程、存档(现行见 run-snapshot.md愿景见 book-storage.md
``` ```
### 业务 stage ### 业务 stage
```text ```text
design创作:核心→细节交互→细化)→ 用户验收 → 用户手动进 play → done design编排器→编排流程→执行能力→收成规格)→ 用户验收 → 用户手动进 play → done
运行相位idle | running | waiting_user | done | error 运行相位idle | running | waiting_user | done | error
``` ```
创作方法权威:`design-orchestrator-guide.md` 创作方法权威:`design-orchestrator-guide.md`;包清单:`world-simulator-modules.md`
### 创作 ### 创作
`design-intake` → accept **`设计.worker集` JSON** → 用户手动进 play可选开局 · 开场白,非强制锁定)。 `design-flow``设计.创作流程` → 反复 `design-step` → accept **`设计.worker集` JSON** → 用户手动进 play可选开场白非强制锁定
无独立 instantiate 管道。见 `design-orchestrator-guide.md` 无独立 instantiate 管道。见 `world-simulator` 包 README
### Play ### Play
@@ -45,6 +46,7 @@ Agent 只能 `run_worker` **声明中的 ref**;执行契约来自 Worker 集
```text ```text
用户.需求 / 用户.最新输入 / 用户.修订说明 用户.需求 / 用户.最新输入 / 用户.修订说明
设计.创作流程
设计.worker集 / 设计.worker集.草稿 设计.worker集 / 设计.worker集.草稿
创作.当前单位 / 创作.已验收单位 / 创作.已验收内容 / 创作.对话 创作.当前单位 / 创作.已验收单位 / 创作.已验收内容 / 创作.对话
运行.初始变量 / 运行.事件流 / 运行.本轮.* 运行.初始变量 / 运行.事件流 / 运行.本轮.*
@@ -54,7 +56,7 @@ Agent 只能 `run_worker` **声明中的 ref**;执行契约来自 Worker 集
固定上下文叙事指南、美学纲领等在实例规格里落地play 时经 `resident_context.mount` / `contextSegments` **挂到多个 worker**——这是 tag 化的主收益,不是省掉创作期依赖正文。 固定上下文叙事指南、美学纲领等在实例规格里落地play 时经 `resident_context.mount` / `contextSegments` **挂到多个 worker**——这是 tag 化的主收益,不是省掉创作期依赖正文。
命名与创作单位 id `design-orchestrator-guide.md` §6`ui-glossary.md`;词表可另补 `docs/tag-vocabulary.md` 命名见 `design-orchestrator-guide.md``ui-glossary.md``world-simulator-modules.md`
--- ---

View File

@@ -1,10 +1,14 @@
# Web UI 心流设计 # Web UI 心流设计
> **状态PX1+ 目标态 / 体验北星。**
> **PX0 不做按本文大重构**;仅抄补存档/确认/选配方等缺口(见 [`px-roadmap.md`](./px-roadmap.md) WP-U
> 用户可见文案权威仍是 [`ui-glossary.md`](./ui-glossary.md)。
## 1. 定位 ## 1. 定位
Writing Agent 的 Web 界面是 **全屏创作工作台**,不是即时通讯客户端。 Writing Agent 的 Web 界面是 **全屏创作工作台**,不是即时通讯客户端。
**用户可见文案**阶段名、Worker 名、气泡标题)须服从 **`ui-glossary.md`**:内部仍用 `design` / `design-core` 等 id界面映射为「创作」「创作 · 核心」等中文。实现见 `src/server/display-labels.ts``web/display-labels.js` **用户可见文案**阶段名、Worker 名、气泡标题)须服从 **`ui-glossary.md`**:内部仍用 `design` / `design-flow` 等 id界面映射为「创作」「创作 · 流程编排」等中文。实现见 `src/server/display-labels.ts``web/display-labels.js`
| 层 | 角色 | | 层 | 角色 |
|----|------| |----|------|
@@ -308,7 +312,7 @@ Continue 提交后:卡收起 → 系统 `running` → 回复摘要进对话流
Worker / Agent 发问侧(对齐 Cursor AskQuestion询问不阻断主产出 Worker / Agent 发问侧(对齐 Cursor AskQuestion询问不阻断主产出
- 总管 `ask_user`**assessment 是主内容**`questions` 挂在其下,用户可 Skip 并请总管基于现有信息继续。 - 总管 `ask_user`**assessment 是主内容**`questions` 挂在其下,用户可 Skip 并请编排器基于现有信息继续。
- Worker优先 `outputs` + `askUser` 同时给出;有产物时追问挂在验收态下,用户可直接「接受目前产物」而不作答。仅完全无法产出时才阻塞提问。 - Worker优先 `outputs` + `askUser` 同时给出;有产物时追问挂在验收态下,用户可直接「接受目前产物」而不作答。仅完全无法产出时才阻塞提问。
- 能推断选项时 **必须**`options`;每项写成用户可直接采用或微调的**建议示范**(可含短场景钩子),禁止空泛「是 / 否」。 - 能推断选项时 **必须**`options`;每项写成用户可直接采用或微调的**建议示范**(可含短场景钩子),禁止空泛「是 / 否」。
- `editable` 默认 `true`;挂载题 `required` 默认 `false` - `editable` 默认 `true`;挂载题 `required` 默认 `false`

View File

@@ -4,39 +4,49 @@
**实现**`src/server/display-labels.ts`(权威映射);`web/display-labels.js` 须与本文及该文件保持一致。新增高频 id 时:**先改本文 → 再改代码**。 **实现**`src/server/display-labels.ts`(权威映射);`web/display-labels.js` 须与本文及该文件保持一致。新增高频 id 时:**先改本文 → 再改代码**。
**产品隐喻**:用户侧统一用**拍摄**用语——**导演 / 剧本 / 演员 / 能力**。旧称「总管 / 能力包 / 配方 / Worker」仅作内部或过渡别称 **产品口径**:用户侧与作者文档统一用**业界编排用语的中文译名**——**配方 / 编排器 / 技能 / 工作流计划 / 运行规格 / 执行单元**。旧拍摄词「导演 / 剧本 / 演员 / 能力」与「总管 / 能力包」仅作历史别称,勿再写进新文案
文档写法:**中文为主**;英文业界叫法仅在术语表首次定义时括注,正文尽量不再夹英文。
--- ---
## 0. 拍摄术语(首选) ## 0. 核心术语(首选)
| 拍摄术语 | 用户可见含义 | 内部对应 | 勿再对用户说 | | 中文(首选) | 业界叫法 | 用户可见含义 | 内部对应 | 旧称(勿再用) |
|----------|--------------|----------|--------------| |--------------|----------|--------------|----------|----------------|
| **导演** | 新建时**手动选一次**的方法起点(如世界模拟器、扩写助手),可按现场调味」;② 会话里负责调度的 Agent | `recipes/` 选型 → 黑板 `创作.选用配方`Main Agent / orchestrator | 配方、能力包(作第二层选项)、总管 | | **配方** | Recipe | 新建时**手动选一次**的方法起点(如世界模拟器、扩写助手);给出建议的近期步骤,可按现场调味 | `recipes/` → 黑板 `创作.选用配方` | 导演(选型)、能力包第二层「配方」选型 |
| **剧本** | 本局谈成的流程与规格(活的,不是死选单) | `设计.创作流程``设计.worker集` | 「剧本 Skill 菜单」、死板流程卡 | | **编排器** | Orchestrator / Supervisor | 会话里负责调度的 Agent决定下一步调谁、是否追问或结束 | Main Agent / `orchestrator.md` | 导演(调度)、总管 |
| **演员** | 上场执行的单元(一次 `run_worker` | Worker / design-* / play workers | 对用户堆「Worker · id」标题用中文名 | | **技能** | Skill / Capability module | 共用工序模块(美学纲领与交互范式…);编排器从池里选型编排 | `modules/` | 能力、组件池(作者文档可写模块) |
| **能力** | 共用工序模块(美学纲领与交互范式…);导演从中选型编排 | `modules/` 组件池 | 组件池、模块(可作作者文档用词) | | **工作流计划** | Workflow Plan / Horizon DAG | 本局谈成的**近期**增量有向无环图(步骤 = 技能实例);可追加、拆分、复用、修订 | `设计.创作流程` | 剧本(流程部分)、死板流程卡 |
| **运行规格** | Runtime Spec / Definition | 可复用的执行声明:执行单元、表、常驻上下文、权限与验收点 | `设计.worker集` 等 | 剧本规格部分、Worker 集(对用户) |
| **执行单元** | Worker | 上场执行的一次单元(一次 `run_worker` | Worker / design-* / play workers | 演员 |
关系口诀:
```text ```text
用户选【导演】(世界模拟器 / 扩写助手 …) 用户选【配方】(世界模拟器 / 扩写助手 …)
导演】调度 → 从【能】里编排 → 谈成【剧本 编排器】调度 → 从【能】里编排 → 谈成【工作流计划】→ 收成【运行规格
演员】按剧本上场执行 → 游玩 / 成稿 【执行单元】按规格上场 → 游玩 / 成稿(运行实例)
``` ```
**一层选型**:新建作品只选**导演**,不要再叠「能力包 + 配方」两层。 **一层选型**:新建作品只选**配方**,不要再叠「能力包 + 配方」两层。
**调味**导演给出的建议步骤是**近期起点**;编排时可增量追加、可反复调用标了可反复的能力(像现场改戏),验收的是本局【剧本】,不是磁盘上的静态菜谱。 **调味**配方给出的建议步骤是**近期起点**horizon;编排时可增量追加、可反复调用标了可反复的技能。验收的是本局【工作流计划】与【运行规格】,不是磁盘上的静态菜谱。
**剧本拆分**:旧称「剧本」同时罩住流程与规格,易混。现固定拆成:
- **工作流计划** = 怎么排技能步骤DAG
- **运行规格** = 游玩期按什么声明执行
--- ---
## 1. 原则 ## 1. 原则
1. **内外分离**id 给机器;中文给用户。 1. **内外分离**id 给机器;中文给用户。
2. **拍摄词优先**:对用户优先用 §0技术文档可写「导演Main Agent / recipe」对照。 2. **本节词优先**:对用户与作者文档优先用 §0技术实现注释可写「编排器Main Agent)」「配方(recipe」对照。
3. **阶段用产品词**lifecycle 的 `design` / `play` 用户侧统一为 **创作** / **游玩**(勿译成「设计模式 / 播放」)。 3. **阶段用产品词**lifecycle 的 `design` / `play` 用户侧统一为 **创作** / **游玩**(勿译成「设计模式 / 播放」)。
4. **与 SKILL `name` 对齐**:磁盘 worker 若已有中文 `name`,展示优先用 name本表是缺省与高频兜底。 4. **与 SKILL `name` 对齐**:磁盘 worker 若已有中文 `name`,展示优先用 name本表是缺省与高频兜底。
5. **气泡标题形态**`{中文名}``{中文名} · {动作}`,例如「创作 · 流程编排 · 产出」不要「Worker · design-flow 产出」。 5. **气泡标题形态**`{中文名}``{中文名} · {动作}`,例如「创作 · 流程编排 · 产出」不要「Worker · design-flow 产出」。
@@ -45,30 +55,39 @@
## 2. 生命周期 / 阶段 ## 2. 生命周期 / 阶段
| 内部 id / 词 | 用户可见 | 业界对照与选用说明 | | 内部 id / 词 | 用户可见 | 说明 |
|--------------|----------|-------------------| |--------------|----------|------|
| `design` | **创作** | 谈【剧本】的工作台。不用「设计」作顶栏主词。 | | `design` | **创作** | 谈工作流计划与运行规格的工作台。不用「设计」作顶栏主词。 |
| `play` | **游玩** | 【演员】按剧本上场。不用「播放」。 | | `play` | **游玩** | 执行单元按运行规格上场。不用「播放」。 |
| `done` | **已完成** | — | | `done` | **已完成** | — |
| `idle` | **待命** | — | | `idle` | **待命** | — |
| `running` | **执行中** | — | | `running` | **执行中** | — |
| `waiting_user` | **等待你** | — | | `waiting_user` | **等待你** | — |
相关业界概念(对用户可简化):
| 中文 | 业界叫法 | 含义 |
|------|----------|------|
| **人工审批 / 验收** | Human-in-the-loopHITLApproval | 用户对步骤或产物有最终决定权;评价标准只辅助建议 |
| **运行实例** | Runtime Instance / Run | 钉住某次规格截面的一局游玩过程 |
| **作品** | Project / Book | 长期项目容器(过程、资产、存档);不等于「可玩成品」口语 |
--- ---
## 3. 角色与系统概念(对照表) ## 3. 角色与系统概念(对照表)
| 内部词 | 用户可见(首选) | 过渡别称 | 说明 | | 内部词 | 用户可见(首选) | 过渡别称 | 说明 |
|--------|------------------|----------|------| |--------|------------------|----------|------|
| Agent / Main Agent / orchestrator | **导演** | 总管(旧) | 调度【演员】、推进【剧本】;气泡可用「导演 · 思考」。 | | Agent / Main Agent / orchestrator | **编排器** | 导演、总管(旧) | 调度执行单元、推进工作流计划;气泡可用「编排器 · 思考」。 |
| Worker | **演员** | Worker / 执行单元 | UI 标题用中文名;检查器可写演员Worker。 | | Worker | **执行单元** | 演员(旧) | UI 标题用中文名;检查器可写执行单元。 |
| Tool | **工具** | Tool | 导演 tool call气泡可用「工具 · 读黑板」。 | | Tool | **工具** | Tool | 编排器 tool call气泡可用「工具 · 读黑板」。 |
| Skill pack / recipe用户选型 | **导演**(选项名) | 能力包 / 配方(旧) | 新建下拉只出现导演选项(世界模拟器、扩写助手…)。 | | recipe用户选型 | **配方**(选项名) | 导演、能力包(旧) | 新建下拉只出现配方选项(世界模拟器、扩写助手…)。 |
| Module / modules pool | **能** | 组件池(作者文档) | 美学纲领与交互范式等;`world-simulator-modules.md`。 | | Module / modules pool | **** | 能力、组件池(旧) | `world-simulator-modules.md`。 |
| Creation flow + Worker 集 | **剧本** | — | 动态谈成;非死选单。 | | `设计.创作流程` | **工作流计划** | 剧本(旧,流程部分) | 增量 DAG;非死选单。 |
| `设计.worker集` | **运行规格** | 剧本(旧,规格部分) | 可进游玩的声明截面。 |
| Blackboard | **黑板** | 上下文板 | — | | Blackboard | **黑板** | 上下文板 | — |
| Artifact | **产物** | — | 待验收输出。 | | Artifact | **产物** | — | 待验收输出。 |
| Accept / Review | **验收** / **接受** | | 按钮用「接受」;阶段说明用「验收」。 | | Accept / Review | **验收** / **接受** | 人工审批 | 按钮用「接受」;阶段说明用「验收」。 |
| Intake | **需求描述** | 启动填空 | — | | Intake | **需求描述** | 启动填空 | — |
| Burst | **本轮调度** | — | 少对用户说 burst。 | | Burst | **本轮调度** | — | 少对用户说 burst。 |
| Questions card | **询问卡** | Questions | 详见 `ui-design.md` §8。 | | Questions card | **询问卡** | Questions | 详见 `ui-design.md` §8。 |
@@ -79,8 +98,8 @@
| 内部 id | 用户可见 | 备注 | | 内部 id | 用户可见 | 备注 |
|---------|----------|------| |---------|----------|------|
| `design-flow` | **创作 · 流程编排** | 以已选【导演】为起点,编排/增量修订可变 DAG → 写入剧本(创作流程 | | `design-flow` | **创作 · 流程编排** | 以已选【配方】为起点,编排/增量修订工作流计划(可变 DAG |
| `design-step` | **创作 · 执行步骤** | 按剧本执行当前【能】 | | `design-step` | **创作 · 执行步骤** | 按工作流计划执行当前【能】 |
| `opening-generator` | **开局 · 开场白** | 创作末尾可选 | | `opening-generator` | **开局 · 开场白** | 创作末尾可选 |
| `design-core` 等 | (已废弃) | 旧分步 skill勿再调度 | | `design-core` 等 | (已废弃) | 旧分步 skill勿再调度 |
@@ -95,7 +114,7 @@
--- ---
## 5. 游玩期常用演员(缺省) ## 5. 游玩期常用执行单元(缺省)
声明里可覆盖;无中文名时用下表: 声明里可覆盖;无中文名时用下表:
@@ -106,9 +125,9 @@
| `world-simulator` | **世界推演** | | `world-simulator` | **世界推演** |
| `round-present` | **回合呈现** | | `round-present` | **回合呈现** |
导演选项展示名示例:`world-simulator`recipe**世界模拟器**`expand-assistant`**扩写助手** 配方选项展示名示例:`world-simulator`recipe**世界模拟器**`expand-assistant`**扩写助手**
**创造演员**:规格里另写 `name`(中文展示名)。`ref` 仍用英文 kebabUI 优先 `name` **创造执行单元**:规格里另写 `name`(中文展示名)。`ref` 仍用英文 kebabUI 优先 `name`
--- ---
@@ -118,11 +137,11 @@
|--------------|--------------|------| |--------------|--------------|------|
| `phase:core` | **单位 · 核心** | — | | `phase:core` | **单位 · 核心** | — |
| `phase:refine` | **单位 · 细化** | — | | `phase:refine` | **单位 · 细化** | — |
| `worker:{ref}` | **演员 · {中文名或 ref}** | `worker:narrator`演员 · 叙事转述 | | `worker:{ref}` | **执行单元 · {中文名或 ref}** | `worker:narrator`执行单元 · 叙事转述 |
| `fixed:{topic}` | **能 · {话题中文}** | `fixed:aesthetics-interaction` → 能 · 美学纲领与交互范式 | | `fixed:{topic}` | **能 · {话题中文}** | `fixed:aesthetics-interaction`能 · 美学纲领与交互范式 |
| `resident:{id}` | **常驻 · {id 或名}** | — | | `resident:{id}` | **常驻 · {id 或名}** | — |
话题建议译名: 能话题建议译名:
| topic | 用户可见 | | topic | 用户可见 |
|-------|----------| |-------|----------|
@@ -141,7 +160,7 @@
|----------------------|----------------|----------| |----------------------|----------------|----------|
| `intake` | 描述需求 | 描述创作需求 | | `intake` | 描述需求 | 描述创作需求 |
| `input` | 补充说明 | 补充说明 / 回答追问 | | `input` | 补充说明 | 补充说明 / 回答追问 |
| `worker_questions` | 回答提问 | 回答 · {中文演员名} | | `worker_questions` | 回答提问 | 回答 · {中文执行单元名} |
| `approve_step` | 确认执行 | 建议调用 {中文名} | | `approve_step` | 确认执行 | 建议调用 {中文名} |
| `review_artifact` | 验收产物 | 验收产物 | | `review_artifact` | 验收产物 | 验收产物 |
@@ -151,9 +170,10 @@
- `Worker · design-core``run_worker(design-core)` - `Worker · design-core``run_worker(design-core)`
- 顶栏 / pill 写 `design` / `play` 英文 - 顶栏 / pill 写 `design` / `play` 英文
- 「总管会调度 design-core」(应写「导演会先谈剧本」或「将开始:创作 · 流程编排」) - 「总管会调度 design-core」「导演会先谈剧本」(应写「编排器会先谈工作流计划」或「将开始:创作 · 流程编排」)
- 新建作品同时出现「导演 + 配方」两层选择 - 新建作品同时出现「导演 + 配方」或「能力包 + 配方」两层选择
- 询问卡标题直接写 `design-core` - 询问卡标题直接写 `design-core`
- 新文案继续使用拍摄词「导演 / 剧本 / 演员 / 能力」作首选
技术日志、导出里的「调试附录」、开发者文档不受本条限制,但默认导出给用户的 Markdown 应走同一套映射。 技术日志、导出里的「调试附录」、开发者文档不受本条限制,但默认导出给用户的 Markdown 应走同一套映射。
@@ -165,7 +185,8 @@
|------|------| |------|------|
| `ui-design.md` | 布局与心流;文案须服从本文 | | `ui-design.md` | 布局与心流;文案须服从本文 |
| `architecture.md` | 内部术语;用户侧以本文为准 | | `architecture.md` | 内部术语;用户侧以本文为准 |
| `daily-use-p0.md` | 导演 / 剧本产品定义 | | `daily-use-p0.md` | 配方 / 工作流计划产品定义 |
| `world-simulator-modules.md` | 【能力】与导演recipes作者清单 | | `world-simulator-modules.md` | 【技能】与配方recipes作者清单 |
| `creation-playbook.md` | 创作/游玩流程概念 | | `creation-playbook.md` | 创作/游玩流程概念 |
| `design-orchestrator-guide.md` | 创作方法(可继续写英文 id面向作者 | | `design-orchestrator-guide.md` | 创作方法(可继续写英文 id面向作者 |
| `briefs/capability-authoring-brief.md` | 技能撰写交接(术语须与本文一致) |

View File

@@ -2,6 +2,7 @@
> **文档层级Worker / 声明契约格式(非系统架构)。** > **文档层级Worker / 声明契约格式(非系统架构)。**
> 上下文编译原则见 [`architecture.md`](./architecture.md)、[`context-assembly.md`](./context-assembly.md)。 > 上下文编译原则见 [`architecture.md`](./architecture.md)、[`context-assembly.md`](./context-assembly.md)。
> **现行包落地**见 [`skills/dialogue/world-simulator/README.md`](../skills/dialogue/world-simulator/README.md)。
## 1. 定位(现行:声明驱动) ## 1. 定位(现行:声明驱动)
@@ -9,11 +10,12 @@
```text ```text
play 时执行契约 = accept 后的 设计.worker集 某条 workers[](实例 Worker 声明) play 时执行契约 = accept 后的 设计.worker集 某条 workers[](实例 Worker 声明)
可选模板 = worker-templates/{ref}.yamldesign-intake 合并默认值) 可选模板 = worker-templates/{ref}.yamldesign 缺省合并默认值)
磁盘 SKILL.md = 仅创阶段必要 workerdesign-intake 磁盘 SKILL.md = 仅创阶段必要 workerdesign-flow / design-step / opening-generator
技能正文 = modules/{id}/prompt.md由 design-step 注入,不是独立 worker
``` ```
总管 `run_worker(id)` → Runtime 校验 id ∈ Worker 声明 → 从 **Worker 集条目**+ 可选模板合并)拼 prompt → 写声明的 `outputs` 编排器 `run_worker(id)` → Runtime 校验 id ∈ Worker 声明 → 从 **Worker 集条目**+ 可选模板合并)拼 prompt → 写声明的 `outputs`
**不要**为每个 play ref 预置 `workers/narrator/SKILL.md`;实例差异写在 Worker 集里。 **不要**为每个 play ref 预置 `workers/narrator/SKILL.md`;实例差异写在 Worker 集里。
@@ -28,28 +30,33 @@ play 时执行契约 = accept 后的 设计.worker集 某条 workers[](实例
```text ```text
skills/dialogue/world-simulator/ skills/dialogue/world-simulator/
├── orchestrator.md ├── orchestrator.md
├── modules/{id}/prompt.md # 能力切片(非 SKILL.md
├── worker-templates/ # 可选模板,非执行文件 ├── worker-templates/ # 可选模板,非执行文件
└── workers/ └── workers/
── design-intake/SKILL.md ── design-flow/SKILL.md
├── design-step/SKILL.md
└── opening-generator/SKILL.md
``` ```
- 目录名 = worker id。 - 目录名 = worker id。
- 文件名固定 **`SKILL.md`**。 - 文件名固定 **`SKILL.md`**。
`design-intake` / `design-core` / `design-fixed` / `design-worker` / `design-refine` **已移除**
--- ---
## 3. Design Worker Frontmatter示例 ## 3. Design Worker Frontmatter示例
```yaml ```yaml
--- ---
id: design-intake id: design-step
skill: world-simulator skill: world-simulator
name: 实例设计 · Worker 集 name: 创作 · 执行能力步
stage: design stage: design
inputTags: inputTags:
- "用户.需求" - "用户.需求"
- "设计.创作流程"
outputTags: outputTags:
- "设计.worker集"
- "设计.worker集.草稿" - "设计.worker集.草稿"
inputMerge: latest inputMerge: latest
--- ---
@@ -70,7 +77,7 @@ inputMerge: latest
## 4. 实例声明字段(写入 `设计.worker集` ## 4. 实例声明字段(写入 `设计.worker集`
design-intake 产出的每条 worker `refine` 能力 / design 收口产出的每条 worker
```yaml ```yaml
workers: workers:
@@ -95,12 +102,13 @@ workers:
- Agent **不**指定 inputTags读 Worker 声明 / 模板。 - Agent **不**指定 inputTags读 Worker 声明 / 模板。
- `ref: null` + `gap`:声明了职责但无模板 / SKILL需补声明或 temp worker。 - `ref: null` + `gap`:声明了职责但无模板 / SKILL需补声明或 temp worker。
- 验收:`design-intake` 默认 `user_confirmed`play 中间 worker 可 `no_confirmation` - 验收design-flow / design-step 默认需用户确认play 中间 worker 可 `no_confirmation`
## 相关 ## 相关
| 文档 | 关系 | | 文档 | 关系 |
|------|------| |------|------|
| `creation-playbook.md` | 创作流 | | `creation-playbook.md` | 创作流 |
| `world-simulator-modules.md` | 能力 / 编排器清单 |
| `worker-declaration.ts` | Runtime 声明校验 | | `worker-declaration.ts` | Runtime 声明校验 |
| `worker-templates/README.md` | 可选模板 | | `worker-templates/README.md` | 可选模板 |

View File

@@ -1,15 +1,15 @@
# 世界模拟器 · 导演与能力撰写清单 # 世界模拟器 · 编排器与能力撰写清单
> 给作者用。用户侧术语:**`docs/ui-glossary.md` §0**。 > 给作者用。用户侧术语:**`docs/ui-glossary.md` §0**。
> 运行:选导演 → 编排**增量**剧本 DAG → `design-step` 执行能;可再扩步反复调用。 > 运行:选配方 → 编排**增量**工作流计划 DAG → `design-step` 执行能;可再扩步反复调用。
> **标准范例**`modules/aesthetics-interaction/prompt.md`。 > **标准范例**`modules/aesthetics-interaction/prompt.md`。
> **给外部 AI 的完整泛用规范****`docs/briefs/capability-authoring-brief.md`**(项目概述 + 称呼 + 格式契约)。 > **给外部 AI 的完整泛用规范****`docs/briefs/capability-authoring-brief.md`**(项目概述 + 称呼 + 格式契约)。
## 两层 ## 两层
```text ```text
导演】recipes/ 【能】modules/ 配方】recipes/ 【能】modules/
└─ 编排增量 DAG → design-step 注入能块 →open 则再编排)→ 演员上场 └─ 编排增量 DAG → design-step 注入能块 →open 则再编排)→ 执行单元上场
``` ```
--- ---
@@ -76,20 +76,37 @@ declaration: …
切割实现:`parseModulePromptSections` / `extractModuleOpening` / `formatModulePromptForLlm``src/skills/creation-flow.ts`)。 切割实现:`parseModulePromptSections` / `extractModuleOpening` / `formatModulePromptForLlm``src/skills/creation-flow.ts`)。
注入 LLM 时按块顺序拼接,**不含** `opening`(开场已由程序发出)。 注入 LLM 时按块顺序拼接,**不含** `opening`(开场已由程序发出)。
### catalog 一行(插入导演提示词 ### catalog 一行(索引 + 编排结构
| 字段 | 作用 | | 字段 | 作用 |
|------|------| |------|------|
| `id` / `name` / `declaration` / `artifact` | 选型与产物映射 | | `id` / `name` / `declaration` / `artifact` | 索引与产物映射`declaration` 可被 prompt `meta` 覆盖 |
| `repeatable` | 可选;`true` = 允许同能力多次编入增量 DAG | | `repeatable` | 可选;`true` = 允许同能力多次编入增量 DAG |
| `params` | 可选;编排期 `steps[].params` 声明(`key`/`label`/`required`/`hint`);必填项须在进执行前钉齐 |
| `opening` | 可选覆盖;一般只写在 prompt 的 `opening` 块 | | `opening` | 可选覆盖;一般只写在 prompt 的 `opening` 块 |
编排器注入【能力 · 可选工序】时,会读取各能力 `prompt.md` 的 `meta``declaration` / `when` / `when_not` / `boundary`**不是**只看 catalog 短声明。执行全文仍只在 design-step 注入。
### 配方 `recipe.yaml`
| 字段 | 作用 |
|------|------|
| `when` | 适用什么体验 |
| `core` | 整套设计方法的核心思路与目标 |
| `process` | 设计流程(如何增量选型、何时收成) |
| `principles` | 配方特有取舍 |
| `brief` / `steps` | 近期起点;不是固定全程 DAG |
配方**不要**重复罗列各能力调用条件;那是能力 meta 的职责。旧字段 `hint` 仍可读作兜底。
### 默认问题节奏(通用) ### 默认问题节奏(通用)
```text ```text
程序发 opening → 用户首答 → LLMopening + 首答 + 切割后的方法块 + 依赖) 程序发 opening → 用户首答 → LLMopening + 首答 + 切割后的方法块 + 依赖)
``` ```
有编排参数的能力:先由 design-flow askUser 钉 params → 用户认可 DAG → design-step 注入【本步参数】执行;勿把「生成什么」推迟到执行期。
--- ---
## 目录与清单 ## 目录与清单
@@ -107,11 +124,11 @@ recipes/world-simulator|expand-assistant/recipe.yaml
| 美学纲领与交互范式 | `aesthetics-interaction` | **范例已写** | | 美学纲领与交互范式 | `aesthetics-interaction` | **范例已写** |
| 实现机制 | `mechanism` | **已写** | | 实现机制 | `mechanism` | **已写** |
| 世界蓝图与人文地理 | `world-blueprint` | **已写** | | 世界蓝图与人文地理 | `world-blueprint` | **已写** |
| 生成规则 | `generation-rules` | 骨架,**可反复** | | 生成规则 | `generation-rules` | **已重写**,可反复;双门槛 + schema + 生命周期;编排必填 `params.target` |
| 具体实例 | `concrete-instances` | 骨架,**可反复** | | 具体实例 | `concrete-instances` | **已重写**可反复;执行预生成规则;编排必填 `params.rule_id` |
| 叙事指南 | `narrative` | **已写** |
| 拓扑图谱 | `topology` | 骨架,待细写 | | 拓扑图谱 | `topology` | 骨架,待细写 |
| 设计状态栏 | `status-bar` | 骨架,待细写 | | 设计状态栏 | `status-bar` | 骨架,待细写 |
| 叙事指南 | `narrative` | 骨架,待细写 |
| 变量设计与更新规则 | `variable-design` | 骨架,待细写 | | 变量设计与更新规则 | `variable-design` | 骨架,待细写 |
| 变量控制上下文 | `variable-context` | 骨架,待细写 | | 变量控制上下文 | `variable-context` | 骨架,待细写 |
| 设计回复格式 | `reply-format` | 骨架,待细写 | | 设计回复格式 | `reply-format` | 骨架,待细写 |
@@ -120,20 +137,21 @@ recipes/world-simulator|expand-assistant/recipe.yaml
| 能力 | id | 状态 | | 能力 | id | 状态 |
|------|-----|------| |------|-----|------|
| Worker 规格 | `worker-spec` | 骨架,**可反复** | | Worker 规格 | `worker-spec` | **已写**可反复 |
| 细化终稿 | `refine` | 骨架,待细写 | | 细化终稿 | `refine` | **已写**(产物=`设计.worker集` |
| 导演 | 状态 | | 编排器 | 状态 |
|------|------| |------|------|
| 世界模拟器 | 建议第一步:美学纲领与交互范式 | | 世界模拟器 | 方法论已写core/process/principles起点:美学纲领与交互范式 |
| 扩写助手 | 待完善 | | 扩写助手 | 方法论已写;起点:美学纲领与交互范式;勿默认套世界模拟全套 |
--- ---
## 验收 ## 验收
1. 只选导演 → 出**近期**创作流程(`status=open` 1. 只选配方 → 出**近期**创作流程(`status=open`
2. design-step 能切割出 `opening`/`task`/… 2. design-step 能切割出 `opening`/`task`/…
3. 有 `opening` 时先程序开场再 LLM 3. 有 `opening` 时先程序开场再 LLM
4. 可追加同能力多次(不同 step.id收成前 `status=closed` 4. 可追加同能力多次(不同 step.id + params);收成前 `status=closed`
5. UI 用拍摄术语 5. UI 用编排术语;有编排参数的步骤须展示 params
6. 缺必填 params 的步骤不得视为可执行(校验失败 / 编排先 askUser

4
package-lock.json generated
View File

@@ -15,7 +15,7 @@
"electron": "^35.0.0", "electron": "^35.0.0",
"tsx": "^4.19.0", "tsx": "^4.19.0",
"typescript": "^5.7.0", "typescript": "^5.7.0",
"vitest": "^2.1.0" "vitest": "^2.1.9"
} }
}, },
"node_modules/@electron/get": { "node_modules/@electron/get": {
@@ -2673,7 +2673,7 @@
}, },
"node_modules/vitest": { "node_modules/vitest": {
"version": "2.1.9", "version": "2.1.9",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", "resolved": "https://registry.npmmirror.com/vitest/-/vitest-2.1.9.tgz",
"integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",

View File

@@ -19,7 +19,7 @@
"electron": "^35.0.0", "electron": "^35.0.0",
"tsx": "^4.19.0", "tsx": "^4.19.0",
"typescript": "^5.7.0", "typescript": "^5.7.0",
"vitest": "^2.1.0" "vitest": "^2.1.9"
}, },
"dependencies": { "dependencies": {
"yaml": "^2.9.0" "yaml": "^2.9.0"

View File

@@ -2,16 +2,21 @@
# 各【导演】与编排都从这里选型。 # 各【导演】与编排都从这里选型。
# id = modules/{id}/ 文件夹 # id = modules/{id}/ 文件夹
# name = 固定中文名(流程 JSON 的 name同能力可多次时靠 step.id 区分) # name = 固定中文名(流程 JSON 的 name同能力可多次时靠 step.id 区分)
# declaration = 插入导演 / design-flow 提示词的短声明(选型用;勿塞全文 # declaration = catalog 短声明(可被 prompt.md ```meta 覆盖
# artifact = 执行期产物 tag程序映射不写进流程 JSON # artifact = 执行期产物 tag程序映射不写进流程 JSON
# repeatable = true 时允许同能力多次编入增量 DAG如生成规则、具体实例 # repeatable = true 时允许同能力多次编入增量 DAG如生成规则、具体实例
# params = 可选;编排进 DAG 时 steps[].params 的声明required 须在执行前钉齐)
# opening = 可选;覆盖 prompt.md 里 ```opening 默认问题(一般只写在 prompt.md # opening = 可选;覆盖 prompt.md 里 ```opening 默认问题(一般只写在 prompt.md
# #
# 编排选型:程序会读取各 modules/{id}/prompt.md 的 meta
# declaration / when / when_not / boundary注入 design-flow勿只靠本表短声明。
#
# 标准范例aesthetics-interaction美学纲领与交互范式 # 标准范例aesthetics-interaction美学纲领与交互范式
# 后来写能力:同结构 prompt.md含默认问题+ 本表一行 declaration # 后来写能力:同结构 prompt.md含默认问题+ 本表一行索引
# #
# 世界模拟器常用能力见下「体验→世界→机制→呈现→收成」;编排按需选用,勿默认全选。 # 世界模拟器常用能力见下「体验→世界→机制→呈现→收成」;编排按需选用,勿默认全选。
# 流程是可变增量 DAG勿一次排完全程可反复调用标了 repeatable 的能力。 # 流程是可变增量 DAG勿一次排完全程可反复调用标了 repeatable 的能力。
# 有编排参数的能力DAG 步骤必须是带 params 的具体调用,禁止空壳进 design-step。
modules: modules:
# —— 体验契约 —— # —— 体验契约 ——
@@ -34,17 +39,44 @@ modules:
name: 生成规则 name: 生成规则
repeatable: true repeatable: true
declaration: >- declaration: >-
钉内容如何生成/推进的可执行规则(触发、约束、节奏),非散文设定; 仅当某类内容既对游玩重要、又无法凭世界基底稳定生成时使用:
可按题材块反复调用(每次增量补规则) 定义严格 schema、生成约束与仅动态/仅预生成/预生成并动态三种生命周期;
可按生成对象反复调用
artifact: 设计.生成规则 artifact: 设计.生成规则
params:
- key: target
label: 生成对象
required: true
hint: 本轮为哪一类内容建规则;编排时 askUser 给选项+其它
- key: rule_id
label: 规则 id
required: false
hint: 建议英文 kebab-case可执行时再最终钉死
- key: lifecycle_intent
label: 生命周期意图
required: false
hint: runtime_only | seed_only | seed_and_runtime不明则 askUser
- id: concrete-instances - id: concrete-instances
name: 具体实例 name: 具体实例
repeatable: true repeatable: true
declaration: >- declaration: >-
钉关键人物/地点/物件等具体实例,供开局与生成锚定;勿堆无关名单 执行一条要求预生成的生成规则,直接产出符合其 schema 与约束的具体实例
可按需反复调用(每次增量补实例) 仅动态规则不调用,可按 rule_id 或批次反复调用
artifact: 设计.具体实例 artifact: 设计.具体实例
params:
- key: rule_id
label: 调用规则
required: true
hint: 必须来自已验收生成规则中 seed_only/seed_and_runtime 的真实 rule_id编排时给选项
- key: batch_goal
label: 批次目标
required: false
hint: 本批要锚定什么如开局重要NPC
- key: count
label: 数量
required: false
hint: 数字或「按规则」contextual 时写清规模依据
- id: narrative - id: narrative
name: 叙事指南 name: 叙事指南

View File

@@ -1,6 +1,7 @@
# 具体实例 # 具体实例
> **状态:待完善** — 块格式见 `docs/world-simulator-modules.md`;范例见 `aesthetics-interaction`。 > 能力文档。程序只切割下方 **fence 块**`##` 标题仅供人读。
> 写法说明:`docs/world-simulator-modules.md`;范例:`aesthetics-interaction`。
## meta ## meta
@@ -8,51 +9,101 @@
name: 具体实例 name: 具体实例
id: concrete-instances id: concrete-instances
artifact: 设计.具体实例 artifact: 设计.具体实例
declaration: 钉关键人物/地点/物件等具体实例,供开局与生成锚定;勿堆无关名单 declaration: >
when: 需要可点名的人/地/物锚定开局或生成时 执行一条要求预生成的生成规则,直接产出符合该规则的具体实例;
when_not: 蓝图骨架未定时就堆长名单;用户明确只要即时生成、不要预置实例时 可按 rule_id 或批次反复调用
when: |
「设计.生成规则」中已有生命周期为 `seed_only` 或 `seed_and_runtime` 的规则,
现在需要按该规则生成实际内容。
when_not: |
规则生命周期为 `runtime_only` → 留到实际游玩中生成,本步不预生成。
没有对应生成规则,或规则缺少执行所需信息 → 返回「生成规则」补齐。
想修改 schema、约束或生命周期 → 返回「生成规则」,本步不改合同。
boundary: | boundary: |
本能力:具体可引用条目。 本能力只做一件事读取指定生成规则按规则规定的数量、schema、生成步骤与约束
世界蓝图与人文地理:骨架与尺度,非逐条名片 生成可直接使用的实例。它不重新论证规则、不修改规则,也不扩写其它设计
```
## opening
```opening
``` ```
## task ## task
```task ```task
钉清关键具体实例(人物/地点/物件等),写入 设计.具体实例。只保留服务体验与开局的条目 你正在执行剧本中的「具体实例」步骤。产物写入设计.具体实例
(待作者细写)
本步只是「生成规则」的执行器:根据规则生成具体实例,不做第二轮设计。
要执行的 `rule_id` 已在【本步参数】;禁止再问用户要生成什么或重新讨论规则。
执行顺序:
1. 从「设计.生成规则」找到 `params.rule_id` 对应规则。不存在、不是预生成生命周期或缺少执行所需信息时,停止并准确指出缺口。
2. 确定本批数量:`params.count` 有明确数字时采用;否则完全按规则的「数量」决定。`params.batch_goal` 若有,只作为不违反规则的本批筛选条件。
3. 按规则的「生成依据」和「生成步骤」生成实例。`records` 只使用规则 schema 声明的字段,填满所有必填字段,并遵守类型、枚举、边界、嵌套结构、硬约束、字段间约束、变化维度、禁止项和去重规则。
4. 逐条按规则的「校验」检查;不合格的实例直接重生成,不把错误项或设计过程写进产物。
5. 若已有「设计.具体实例」,按 `rule_id` 追加新批次;除非用户明确要求替换,不改动旧批次。
6. 输出符合 output 的 JSON。
若程序已发出默认问题:用户首答在「用户.worker答复」。禁止重复同一开场。
summary`具体实例 · {生成对象} · {本批数量}条`
``` ```
## principles ## principles
```principles ```principles
少而可用;每条要说清为何需要 1. 规则说什么就生成什么:不补字段、不改边界、不新增规则
2. 只交实例:`records` 放最终可用数据,不放 schema、解释、草稿或占位符。
3. 先生成后自检:不合格项内部重做,只交通过规则校验的结果。
4. 保持差异:在规则允许的变化维度内避免重复,不用变化破坏共同约束。
``` ```
## probe ## probe
```probe ```probe
(待作者细写) 通常不追问,直接按规则生成。
仅当规则使用 contextual 数量而现有参数和依赖无法算出数量时,询问缺失的地区、阶段或规模。
若用户要求 schema 外内容,提示返回「生成规则」修改合同;不要在本步临时加字段。
``` ```
## output ## output
```output ```output
{ {
"人物": [{ "名": "…", "要点": "…", "为何需要": "…" }], "batches": [
"地点": [], {
"物件": [], "batch_id": "稳定的英文 kebab-case id",
"其它": [] "rule_id": "来源生成规则 id",
"对象": "本批生成的内容类型",
"数量": 3,
"批次条件": ["本批额外筛选条件;没有则为空"],
"records": [
{
"这里直接使用来源规则的实际字段": "不得使用通用人物/地点/物件名片代替"
}
]
}
],
"增量说明": "本次新增或替换了哪个 batch_id"
} }
`records` 的示意键必须被实际规则 schema 完整替换。不得把 schema 定义复制进 `records`。
``` ```
## checklist ## checklist
```checklist ```checklist
- [ ] 删掉某条会丢掉哪段体验?说不清则删 - [ ] 是否执行了 params.rule_id 指向的预生成规则?
- [ ] 数量是否来自 params.count 或规则本身?
- [ ] records 是否完整符合 schema 及全部约束?
- [ ] 是否只输出最终实例,没有混入规则解释或校验过程?
- [ ] 是否保留未要求替换的已有批次?
```
## examples
```examples
好:
- `heroine-design` 要求 1 条:直接生成 1 条完整女主记录,字段和值全部服从规则。
- `major-npc` 要求 5 条:直接生成 5 名互不重复、满足阵营与地区约束的重要 NPC。
坏:
- 无视 schema给实例补上“背景故事”等未声明字段。
- 输出一段生成思路和校验报告,却没有直接给可用实例。
``` ```

View File

@@ -1,6 +1,7 @@
# 生成规则 # 生成规则
> **状态:待完善** — 块格式见 `docs/world-simulator-modules.md`;范例见 `aesthetics-interaction`。 > 能力文档。程序只切割下方 **fence 块**`##` 标题仅供人读。
> 写法说明:`docs/world-simulator-modules.md`;范例:`aesthetics-interaction`。
## meta ## meta
@@ -8,53 +9,184 @@
name: 生成规则 name: 生成规则
id: generation-rules id: generation-rules
artifact: 设计.生成规则 artifact: 设计.生成规则
declaration: 钉内容如何生成/推进的可执行规则(触发、约束、节奏),非散文设定 declaration: >
when: 需要把「世界怎么动、内容怎么长出来」写成可执行约束时 仅为重要且模型无法仅凭世界基底稳定生成的同类内容,定义可执行的生成规则、
when_not: 仍在谈体验感受、尚未需要可执行规则时 严格数据格式与生命周期;可按生成对象反复调用
when: |
上游体验、机制与世界基底已足以判断某类内容:
1. 它对实际游玩非常重要;并且
2. 模型仅凭现有上下文无法稳定产出符合期待、彼此一致且可供下游使用的结果。
两项同时成立时,才为该类对象建立专门生成规则。
when_not: |
内容虽重要,但凭世界基底与常识即可稳定生成 → 不调用。
内容难生成,但只是装饰、偶尔出现或删掉不影响核心体验 → 不调用。
只想预先写一个普通人/地/物,且不需要先建立专门格式与生成约束 → 不调用。
只需定义变量在游玩中如何更新 → 变量设计与更新规则。
只需定义剧情、章节或世界如何推进 → 交给对应 Worker 或其它推进能力,不借本步泛化。
boundary: | boundary: |
本能力:触发、约束、节奏、可否随机等可执行规则。 本能力:为“一类格式相近的内容”定义生成合同,包括生成依据、字段 schema、
变量设计与更新规则:字段与何时改值 枚举值、数值上下界、约束、随机维度、校验方式与规则生命周期
实现机制:落到哪些 worker/表来执行这些规则 生成对象不限于人物,也可为怪物、装备、任务、职业、组织、事件等
``` 具体实例:执行本步中要求预生成的规则,产出符合合同的实际记录;本步不填实例数据。
世界蓝图与人文地理:提供可直接依赖的世界基底;本步不重写世界百科。
## opening 实现机制:说明某类内容为何支撑体验;本步先验证其必要性,再定义怎么生成。
变量设计与更新规则:定义游玩期状态如何变化;本步只约束实例生成时的数据类型与初始合法范围。
```opening Worker 规格 / 细化终稿:决定谁在游玩期执行、哪些产物进入常驻上下文;本步只声明所需生命周期。
``` ```
## task ## task
```task ```task
钉清生成与推进规则,写入 设计.生成规则。须可被下游 worker/程序引用,禁止只写散文氛围 你正在执行剧本中的「生成规则」步骤。产物写入设计.生成规则
(待作者细写)
本步不是泛用写作建议,也不是“凡是重要就做一张表”。调用目标已由编排期写入【本步参数】(至少含 target禁止再问「这一步生成什么」。
执行顺序:
1. 读取【本步参数】与依赖产物。`target` 决定本轮唯一生成对象族;不要顺手扩展到其它类别。若缺必填参数,停止产出并提示返回 design-flow 补参。
2. 执行双门槛判断:
- 重要性门槛:没有专门生成合同,核心玩法、关键关系、长期一致性或必要数据接口是否会明显受损?
- 不可替代门槛:模型是否无法依靠世界基底、常识和普通提示稳定生成合格结果?
两项有任一不成立,输出“无需专门规则”的判断与理由,不为了完成步骤硬造 schema。
3. 两项均成立时,从三种生命周期中选且只选一种(若 params.lifecycle_intent 已给且合理,优先采用;不合理则说明并 askUser
- `runtime_only`:仅游玩期动态生成。规则进入后续上下文,不要求「具体实例」预生成。
- `seed_only`:下一步由「具体实例」按规则生成;实例进入后续上下文,规则在完成生成与校验后丢弃。
- `seed_and_runtime`:下一步先生成种子实例;实例与规则都进入后续上下文,游玩期仍可按同一规则继续生成。
4. 建立真正可执行的数据合同:
- 明确顶层 JSON 形状、单批数量或数量决定方式、每个字段是否必填。
- 每个字段固定类型。至少区分 `string`、`number`、`integer`、`boolean`、`enum`、`array`、`object`;不得只给示例值让下游猜类型。
- `enum` 必须同时给出允许值及各值含义;`number/integer` 必须给上下界,并说明边界含义或单位;`array` 必须定义元素类型与数量范围;`object` 必须继续定义子字段。
- 写清字段间约束、与世界基底的引用关系、禁止项、去重规则和一致性校验。
5. 只有确实需要不可预测性时才定义随机维度;区分“允许变化的字段”和“不能随机破坏的约束”。随机不是省略设计。
6. 若 params.rule_id 已给,优先用作本规则 id否则生成稳定 kebab-case `rule_id`。若已有「设计.生成规则」,按 `rule_id` 增量更新或追加;不得无故重写其它对象的规则。
7. 输出符合 output 的 JSON。规则本身不得夹带实际实例。
若程序已发出默认问题:用户首答在「用户.worker答复」。禁止重复同一开场。只追问会改变必要性、生命周期或 schema 的信息。
summary
- 建立规则:`生成规则 · {生成对象} · {仅动态|仅预生成|预生成并动态}`
- 不建立规则:`生成规则 · {生成对象} · 无需专门规则`
``` ```
## principles ## principles
```principles ```principles
可执行优于文采;与体验禁忌对齐 1. 双门槛:必须“对游玩重要”且“基础上下文不足以稳定生成”同时成立
2. 反表格冲动:核心玩法是古董拍卖,不代表纯现代背景中的普通古董必须有专门规则;常识足够时直接生成。
3. 一规则一对象族:怪物与装备若 schema、约束和用途不同分次调用不要做万能内容生成器。
4. 格式也是规则:字段名、类型、枚举、上下界、嵌套结构与必填性都必须可校验。
5. 生命周期先行:是否预生成、规则最终是否保留,必须在生成实例前决定。
6. 规则服务差异:只固定影响体验和接口的字段;不要把所有可描写细节都结构化。
7. 可追溯:每项关键约束应能指向世界基底、实现机制、体验禁忌或用户明确要求。
8. 不混淆状态更新:好感度可在实例 schema 中规定为有界数字;何时增减、如何结算属于变量设计。
``` ```
## probe ## probe
```probe ```probe
(待作者细写) 一轮 askUser 12 点;优先问会改变结论的分叉。禁止重问【本步参数】已钉的 target / rule_id。
必要性不明:如果不做专门规则、只让模型按世界设定直接生成,最可能出现的不可接受结果是什么?
生命周期不明且 params 未给:这些实例需要每局变化、固定为开局设定,还是固定一批后仍要继续随机补充?
枚举不明:这个字段只能从哪些世界内类别中选择?是否允许“其它”?
数值不明:上下界分别代表什么,生成时是否允许取到边界?
数量不明:需要固定数量,还是由场景/规模决定?允许范围是多少?
若用户的答案证明双门槛不成立,直接建议跳过,不再追问 schema。
``` ```
## output ## output
```output ```output
{ {
"触发": ["…"], "brief": "一句话:本轮判断与其服务的核心体验",
"约束": ["…"], "必要性判断": {
"节奏": "…", "生成对象": "例:重要 NPC / 怪物 / 装备 / 任务 / 职业体系",
"例外": ["…"] "对游玩的重要性": "没有专门规则会具体损失什么",
"基础生成的不足": "现有世界基底为何不足以稳定产出合格结果",
"结论": "建立专门规则|无需专门规则"
},
"rules": [
{
"rule_id": "稳定的英文 kebab-case id",
"对象": "该规则生成什么",
"生命周期": "runtime_only|seed_only|seed_and_runtime",
"上下文策略": {
"预生成实例": true,
"保留规则到游玩期": false,
"保留实例到游玩期": true
},
"生成依据": ["引用的上游产物、世界事实或用户要求"],
"数量": {
"模式": "fixed|range|contextual",
"值": 1,
"最小": 1,
"最大": 1,
"决定规则": "contextual 时必填"
},
"输出合同": {
"格式": "JSON",
"顶层": "array",
"schema": {
"字段名": {
"type": "string|number|integer|boolean|enum|array|object",
"required": true,
"description": "字段语义",
"allowed_values": [
{ "value": "枚举值", "meaning": "含义与适用边界" }
],
"minimum": 0,
"maximum": 100,
"items": { "type": "string" },
"min_items": 1,
"max_items": 3,
"properties": {}
}
}
},
"生成步骤": ["按什么顺序决定字段,如何利用上游依据"],
"硬约束": ["任何实例都不得违反的条件"],
"字段间约束": ["例:阵营=A 时,权限等级不得低于 3"],
"变化维度": ["允许随机或变化的部分;不需要随机则为空"],
"禁止项": ["即使随机抽到也不得出现的组合或内容"],
"去重规则": ["同批及跨批如何避免同质化或重复"],
"校验": ["类型、枚举、边界、世界一致性与体验一致性检查"]
}
],
"增量说明": "相对已有规则新增或修改了什么",
"开放问题": ["仅保留会阻止规则执行的问题"]
} }
当结论为「无需专门规则」时,省略 `rules`,并在 `brief` 中说明应直接依赖哪些现有世界基底生成。
schema 中只保留实际字段适用的类型属性:例如非枚举字段不写 `allowed_values`,非数字字段不写 `minimum/maximum`。
``` ```
## checklist ## checklist
```checklist ```checklist
- [ ] 规则是否可被执行/检查,而非纯描写 - [ ] 重要性与基础生成不足是否分别举证,且两项都成立
- [ ] 是否与体验边界禁忌冲突 - [ ] 是否因为“玩法重要”就误给常识足够的内容建表
- [ ] 生命周期是否在三种模式中明确唯一,布尔策略与之相符?
- [ ] 每个字段是否有明确类型、必填性和语义?
- [ ] enum 是否给全允许值与含义,数字是否给上下界,嵌套类型是否定义完整?
- [ ] 是否写清字段间约束、禁止项、去重与校验?
- [ ] 是否把实际实例、变量更新规则、剧情推进规则或 Worker 规格混入本步?
- [ ] 是否只覆盖本轮对象族,并保留其它已有 rule_id
```
## examples
```examples
应建立:
- 怪物是核心战斗资源,需要每局变化,且世界有独特生态与战斗接口;使用 `runtime_only`,固定属性 schema、生态枚举、数值边界与组合禁忌。
- 单女主必须承载特定关系体验,直接写人设容易遗漏关键切面;使用 `seed_only`,下一步生成女主后丢弃规则。
- 重要 NPC 需要开局已有一批,后续也会随地区开放继续出现;使用 `seed_and_runtime`。
不应建立:
- 纯现代都市拍卖玩法中的普通古董;即使古董很重要,只要现实常识与世界基底足以直接生成,就不值得专门维护规则。
- 只在背景里出现一次的路边摊菜单;即使模型可能写得普通,也不影响核心体验。
坏:
- 只写“人物要立体、装备要有趣”,没有 JSON schema 与可校验约束。
- 枚举字段写“阵营:字符串”,却不生成允许的阵营项。
- 好感度写“0100”又在本步编写每轮加减公式侵入变量更新能力。
``` ```

View File

@@ -1,6 +1,7 @@
# 叙事指南 # 叙事指南
> **状态:待完善** — 块格式见 `docs/world-simulator-modules.md`;范例见 `aesthetics-interaction`。 > 能力文档。程序只切割下方 **fence 块**`##` 标题仅供人读。
> 写法说明:`docs/world-simulator-modules.md`;范例:`aesthetics-interaction`。
## meta ## meta
@@ -8,49 +9,101 @@
name: 叙事指南 name: 叙事指南
id: narrative id: narrative
artifact: 设计.叙事指南 artifact: 设计.叙事指南
declaration: 世界/助手态度与体验边界(不等于文风;契约已写清的态度勿重复问卷) declaration: >
when: 需要钉世界/助手态度口径,且美学纲领与交互范式未写清或需单独收口时 世界/助手态度与体验边界(不等于文风;契约已写清的态度勿重复问卷)
when_not: 契约里已写清态度/禁忌,仅重复问卷 when: |
boundary: 不等于文风;呈现与站位优先读 设计.美学纲领与交互范式 需要单独钉清「世界/助手如何说话、如何取舍信息、如何对待用户情绪」时;
或美学纲领与交互范式里态度仍过粗、下游演员会飘时。
when_not: |
美学纲领与交互范式已写清态度/禁忌,用户未要求加细 → 不要重复问卷。
用户只要文风辞藻样本、不要态度边界 → 可放入常驻上下文短句,不必强开本步。
排版/回复块结构 → 设计回复格式。
boundary: |
本能力:态度、信息取舍、体验边界、焦点偏好(给转述/写手演员的稳定口径)。
不等于文风词典:少堆形容词;多写「遇到 X 时怎么处理」。
美学纲领与交互范式:站位、呈现、核心体验、轮转——已写清的勿重问。
生成规则:可执行推进规则;本步不定章结构算法。
设计回复格式:块结构与拼接顺序。
``` ```
## opening ## opening
```opening ```opening
用几句话说明「系统说话时该像什么人」(想到什么写什么):
1. 态度:冷静如实 / 偏袒主角 / 狠心推进 / 温柔留余地 / 其它?
2. 信息:用户不知道的世界内情,默认藏多少?可以剧透结构吗?
3. 边界:什么绝对不写或不怎么写?(已有禁忌可写「同体验契约」)
若上游契约已够用,可回复「按美学纲领,只补……」。
``` ```
## task ## task
```task ```task
钉清世界/助手态度与体验边界。写入 设计.叙事指南。 你正在执行剧本中的「叙事指南」步骤。产物写入设计.叙事指南
依赖已验收的美学纲领与交互范式时先读再写;已写清的勿重复问卷。
(待作者细写) 先读「设计.美学纲领与交互范式」:已写清的态度/禁忌直接继承,只补缺口。
执行顺序:
1. 复述已确认的体验内核与呈现;不重定站位。
2. 钉态度、信息策略、焦点、边界;写成下游可挂载的短规则,而非散文赏析。
3. 与体验禁忌冲突时以体验禁忌为准,并在产物里点明。
4. 输出符合 output 的 JSON。
若程序已发出默认问题:禁止重复同一开场。
summary`叙事指南 · …`(点题态度,非「文学性」空话)。
``` ```
## principles ## principles
```principles ```principles
(待作者细写) 1. 态度是行为规则,不是形容词堆砌。
2. 不重复问卷:契约已有的字段引用即可。
3. 服务体验:狠心或温柔都必须能指向核心感受。
4. 写手模式:可写「助手如何给大纲意见 / 如何改稿语气」,仍避免空泛文风课。
5. 缩减:三条管用口径优于一页风格指南。
``` ```
## probe ## probe
```probe ```probe
(待作者细写) 一轮 12 点。
缺态度:失败时系统更像「如实报损」还是「帮用户找补救」?
缺信息:用户是否允许「角色知道但用户暂不知」的悬置?
与禁忌冲突:用户既要无虐又要残酷真实——以哪边为先?
``` ```
## output ## output
```output ```output
{ {
"brief": "一句话:叙事口径服务什么体验",
"态度": "…", "态度": "…",
"信息策略": "…",
"焦点": "…",
"边界": ["…"], "边界": ["…"],
"焦点": "…" "遇到冲突时": "优先保全…",
"继承自体验契约": ["已直接采用的字段"],
"开放问题": ["…"]
} }
``` ```
## checklist ## checklist
```checklist ```checklist
- [ ] 与美学纲领与交互范式不重复、不矛盾 - [ ] 与美学纲领与交互范式不重复盘问、不矛盾
- [ ] 是否可被演员当规则执行(非纯文风赏析)?
- [ ] 是否误写成回复块结构或生成规则?
```
## examples
```examples
好:
- 「如实推进代价;不替用户道德排雷;悬念可藏事实不可藏规则。」
坏:
- 「要有诗意、电影感、高级感……」无可执行口径
``` ```

View File

@@ -1,6 +1,8 @@
# 细化终稿 # 细化终稿
> **状态:待完善** — 块格式见 `docs/world-simulator-modules.md`。 > 能力文档。程序只切割下方 **fence 块**`##` 标题仅供人读。
> 写法说明:`docs/world-simulator-modules.md`;规格字段见 `docs/skill-design-guide.md`。
> 本步产物 tag 为 **`设计.worker集`**(可进游玩的实例规格)。
## meta ## meta
@@ -8,28 +10,82 @@
name: 细化终稿 name: 细化终稿
id: refine id: refine
artifact: 设计.worker集 artifact: 设计.worker集
declaration: 钉死关键前提、表与副作用,收成可进游玩的规格 declaration: >
when: 前面步骤已大致谈清,需要收成可进游玩的 Worker 集时 钉死关键前提、表与副作用,收成可进游玩的规格
boundary: 产出设计.worker集 JSON进 play 由用户手动 when: |
前面能力已大致谈清(至少有体验契约,且演员职责可说清),
需要收成可进游玩的「设计.worker集」JSON 时;
编排应将本局流程 status 导向 closed。
when_not: |
体验站位未定、或关键演员仍完全空白时,不要用本步代替上游。
用户只想改某一个演员细节 → 可先 Worker 规格,再本步合并。
boundary: |
本能力:合并上游产物,钉死不能瞎发挥的前提,输出完整「设计.worker集」JSON含 interaction、workers、resident_context、tables 等)。
进 play 由用户手动决定;本步不自动切游玩。
Worker 规格:分步钉演员;本步负责合并与终稿一致性。
美学纲领与交互范式等:只读引用,不重做问卷(矛盾处才问)。
开局·开场白:可选后续步骤,本步可用 design_end.opening 标记是否建议。
```
## opening
```opening
准备收成可进游玩的规格。请确认或补充:
1. 还有没有「绝不能瞎发挥」的前提要钉死?(一句一条)
2. 游玩时最少需要哪些演员上场?(用中文名即可)
3. 要不要表/状态栏?(不要就写「不要」)
若前面产物已经够用,可直接回复「按已有产物收成」。
``` ```
## task ## task
```task ```task
钉死关键前提;表/副作用;收成可进游玩的设计.worker集 JSON 你正在执行剧本中的「细化终稿」步骤。产物必须写入 **设计.worker集**,且为 **JSON**(不要 YAML
(待作者细写)
本步是收成,不是再开一场题材发明。优先合并:
- 设计.美学纲领与交互范式 → interaction / experience_check / 呈现
- 设计.worker规格 → workers[]
- 设计.叙事指南 / 生成规则 / 具体实例 / 世界蓝图 / 实现机制等 → resident_context 挂载或 core_premises
- 设计.变量* / 状态栏 / 拓扑 → tables / 显隐说明(有则写,无则省略)
执行顺序:
1. 忠实复述已确认的站位、体验内核、禁忌;矛盾处 askUser 1 点,勿静默覆盖。
2. 组装 workers[]:每个含 ref、name中文、duty、rationale、acceptance缺省 context/outputs 可标示留给模板合并,但 acceptance 必须写出。
3. resident_context把稳定长文叙事态度、关键规则摘要、禁忌挂到需要的 workers不要把全过程聊天塞进去。
4. tables仅钉体验真正依赖的字段与副作用无则 `tables` 省略或空 schemas。
5. core_premises不能瞎发挥的短列表。
6. design_end如 `{ "opening": "optional" }` 表示可随后跑开场白。
7. 输出完整 JSONsummary`细化终稿 · Worker集 · N 演员 · …`
若程序已发出默认问题:禁止重复同一开场。
进游玩不在本步完成;用户验收本产物后,由用户手动进入游玩。
``` ```
## principles ## principles
```principles ```principles
只钉不能瞎发挥又对体验关键的东西 1. 合并优于重写:上游已验收内容优先进入规格,禁止无故改写体验内核
2. 每个面向用户的可读终稿点必须有 acceptancereview中间层 continue。
3. 正推缩减:能不建表就不建;能常驻一段话解决的不要新演员。
4. 写手路径最小可运行outline + chapter-writer或用户只要分段写手扮演路径按已钉演员。
5. 键名稳定workers[].ref 英文 kebabname 中文给人看。
6. 禁止题材固定套件;禁止在本步发明新 tool。
7. 未决进 open_questions不要假完备。
``` ```
## probe ## probe
```probe ```probe
(待作者细写) 一轮 12 点,只问会挡住收成的矛盾:
- 上游演员列表与用户本轮说法冲突时,以谁为准?
- 终稿演员是「每轮世界+叙事」还是「先纲后章」?
- 有表需求但字段未定:先不要表,还是先钉 12 个关键字段?
能按已有产物收成则不要为「完美」继续盘问。
``` ```
## output ## output
@@ -37,15 +93,81 @@ boundary: 产出设计.worker集 JSON进 play 由用户手动
```output ```output
{ {
"version": 1, "version": 1,
"interaction": {}, "interaction": {
"workers": [], "user_stance": "…",
"resident_context": [], "system_role": "…",
"tables": {} "output": "…",
"turn_shape": "对话回合|助手分段|…"
},
"experience_check": {
"user_relation": "…",
"focus": "…",
"satisfaction_source": "…"
},
"workers": [
{
"name": "章节正文",
"ref": "chapter-writer",
"duty": "…",
"when": "…",
"rationale": "删掉则…",
"acceptance": "review",
"context": {
"static": ["设计.worker集", "大纲.当前"],
"dynamic": ["用户.最新输入"]
},
"outputs": ["正文.当前段", "正文.已完成"]
}
],
"resident_context": [
{
"id": "experience-contract",
"position": "static",
"content": "从上游压缩的稳定句(体验/禁忌/态度)",
"mount": ["chapter-writer"]
}
],
"tables": {
"schemas": [],
"side_effects": []
},
"core_premises": ["…"],
"narrative_guide": "可选短摘要;长文优先走 resident_context",
"input_protocol": {
"parens": "() 元要求",
"quotes": "\"\" 角色对白",
"bare": "无包裹按站位解释"
},
"design_end": {
"opening": "optional"
},
"open_questions": ["…"]
} }
``` ```
必须是可解析 JSON。无表可省略 tables 或留空数组。每个 workers[] 元素必须有 acceptance。
## checklist ## checklist
```checklist ```checklist
- [ ] 验收复述含站位、体验核心、worker/表、为何没有某件 - [ ] 是否 JSON 且可解析为设计.worker集
- [ ] interaction 站位/轮转是否与美学纲领一致?
- [ ] 每个 worker 是否有 name、ref、duty、rationale、acceptance
- [ ] 删掉任一 worker 的 rationale 是否说得清?
- [ ] 有没有把聊天过程塞进常驻上下文?
- [ ] 有没有题材默认灌入用户未要的演员/表?
- [ ] 验收复述能否一句话说清:站位、体验核心、演员、为何没有某件?
```
## examples
```examples
好:
- 扩写interaction.turn_shape=助手分段workers=outline(continue/review)+chapter-writer(review)resident 挂爽点与禁忌。
- 扮演world-simulator(continue)+narrator(review)core_premises 含变造点。
坏:
- 输出 YAML 或半散文
- workers 无 acceptance
- 无视上游,按「标准世界模拟套件」重写
``` ```

View File

@@ -1,6 +1,8 @@
# Worker 规格 # Worker 规格
> **状态:待完善** — 块格式见 `docs/world-simulator-modules.md`。 > 能力文档。程序只切割下方 **fence 块**`##` 标题仅供人读。
> 写法说明:`docs/world-simulator-modules.md`;范例:`aesthetics-interaction`。
> 可选默认契约见 `worker-templates/`(缺省合并用,非本步全文)。
## meta ## meta
@@ -8,45 +10,126 @@
name: Worker 规格 name: Worker 规格
id: worker-spec id: worker-spec
artifact: 设计.worker规格 artifact: 设计.worker规格
declaration: 钉一个游玩期执行单元(职责、读写、挂载) declaration: >
when: 需要钉清某个执行单元的契约时 钉一个游玩期执行单元(职责、读写、挂载);多演员时可多次调用
boundary: 一次一个为宜;终稿合并进 设计.worker集 when: |
已能说出「游玩时谁上场做什么」,需要把某一个演员钉成可调度契约时;
或多演员需分次钉清时(本能力可反复)。
when_not: |
体验/机制仍混沌,还说不清删掉谁会坏体验时 → 先上游能力。
已在收成「细化终稿」且只需合并已有规格时 → 交给细化终稿,勿重复问卷。
boundary: |
本能力一次或本步焦点内钉清一个游玩期执行单元中文名、ref、职责、何时上场、读写 tag、验收点、为何需要。
产物写入「设计.worker规格」可含累积列表最终合并进「设计.worker集」由「细化终稿」完成。
细化终稿:收成完整 Worker 集、表、常驻上下文;本步不假装交终稿。
拓扑图谱:多演员依赖与数据流总图;本步可写本单元读写,不画全图。
生成规则 / 叙事指南:规则与态度正文;本步只声明挂载哪些 tag不重写全文。
```
## opening
```opening
先点名「下一个要钉的演员」(一个即可):
1. 中文称呼TA 在游玩里叫什么?(例:世界推进、叙事转述、大纲、章节正文)
2. 职责一句话:删掉 TA 会丢掉哪段体验?
3. 何时上场:每轮?用户点名写章时?某条件触发?
若你已有多个演员想法,先写最核心的一个;其余可再跑本能力。
``` ```
## task ## task
```task ```task
一次钉一个游玩期执行单元中文名、ref、职责、读写、挂载。写入 设计.worker规格。 你正在执行剧本中的「Worker 规格」步骤。产物写入设计.worker规格
(待作者细写)
一次 design-step 以钉清**一个**游玩期执行单元为主;若用户一次抛出多个且关系简单,可写入 `actors` 数组但须逐个写清 rationale并在 summary 标明本步焦点。
执行顺序:
1. 读依赖产物与体验契约;正推「需要谁」——禁止题材默认演员套餐。
2. 若已有「设计.worker规格」增量同 ref 更新;新 ref 追加;不要无故删除用户已验收条目(除非用户要求改)。
3. 为该单元填写name中文、ref英文 kebab可与 worker-templates 对齐、duty、when、rationale、acceptance、context/outputs 建议。
4. acceptance面向用户的可读终稿倾向 `review`;纯中间裁决/整理倾向 `continue`;吃不准就 ask_user。
5. ref 可参考包内模板(如 narrator、world-simulator、outline、chapter-writer但必须以本局体验为准勿强行两端都上。
6. 输出符合 output 的 JSON。
若程序已发出默认问题:禁止重复同一开场。
summary`Worker 规格 · {中文名} · …`
``` ```
## principles ## principles
```principles ```principles
(待作者细写) 1. 删掉检验:说不清「丢掉哪段体验」的演员不要。
2. 正推:体验 → 手段 → 演员;禁止「世界模拟就一定要 world-simulator + narrator」。
3. 写手/分段常见最小集:大纲/细纲outline+ 章节正文chapter-writer按需加减。
4. 扮演/世界推进常见:世界裁决 + 叙事转述;能合并则问用户是否合并。
5. name 给人看ref 给机器;二者成对出现。
6. 本步不写完整表 schema、不写整份 Worker 集终稿。
7. 常驻上下文挂载只点名「需要挂哪些已有产物 tag」不在本步粘贴长文。
``` ```
## probe ## probe
```probe ```probe
(待作者细写) 一轮 12 点。
缺验收点:本演员产出是「给用户读的一段」还是「给下一演员的中间结果」?
缺 ref更接近包内哪个模板职责给中文选项勿逼用户记英文
多演员纠结:能否合并成一个?合并会损失什么?
写手路径:是否需要「先大纲后正文」两个演员,还是只要分段写手?
``` ```
## output ## output
```output ```output
{ {
"brief": "一句话:本步钉的演员如何服务体验",
"actors": [
{
"name": "叙事转述", "name": "叙事转述",
"ref": "narrator", "ref": "narrator",
"职责": "…", "duty": "…",
"读取": ["…"], "when": "…",
"写入": ["…"], "rationale": "删掉则…",
"为何需要": "…" "acceptance": "review",
"context": {
"static": ["设计.worker集"],
"dynamic": ["用户.最新输入"]
},
"outputs": ["输出.用户展示"],
"presentation": {
"tone": "可选;转述类可填"
}
}
],
"增量说明": "相对旧稿新增/改了哪个 ref",
"开放问题": ["…"]
} }
``` ```
`acceptance` 只能是 `review``continue`。未知字段省略。
## checklist ## checklist
```checklist ```checklist
- [ ] 删掉该 worker 会丢掉哪段体验? - [ ] 每个演员能否通过删掉检验?
- [ ] name/ref 是否成对acceptance 是否写出?
- [ ] 是否误交完整 设计.worker集 或表结构?
- [ ] 是否题材默认套演员?
- [ ] 增量是否误删已有条目?
```
## examples
```examples
好:
- 扩写:先钉「大纲/细纲」outlinecontinue 或 review 按用户是否要验大纲再另一步钉「章节正文」chapter-writerreview
- 扮演:世界推进 continue + 叙事转述 review。
坏:
- 一次甩出 8 个演员且无 rationale
- 只写英文 id 给用户看
- 本步直接输出整份 version:1 Worker 集冒充终稿
``` ```

View File

@@ -1,16 +1,17 @@
# 导演选项目录(用户在新建作品时手动选择;对用户称「导演」) # 导演选项目录(用户在新建作品时手动选择;对用户称「导演」/「配方」
# id = recipes/{id}/ 文件夹 # id = recipes/{id}/ 文件夹
# name = 固定中文名(下拉展示) # name = 固定中文名(下拉展示)
# declaration = 给人看的短说明 # declaration = 给人看的短说明
# 内部仍叫 recipe勿对用户再说「配方」作第二层选项 # 内部仍叫 recipe勿对用户再说「配方」作第二层选项
# recipe.yaml 写方法论when / core / process / principles + 近期 steps
# 步骤 name 必须 ∈ modules/catalog.yaml【能力】 # 步骤 name 必须 ∈ modules/catalog.yaml【能力】
# 选定后写入黑板 tag 创作.选用配方 # 选定后写入黑板 tag 创作.选用配方
recipes: recipes:
- id: world-simulator - id: world-simulator
name: 世界模拟器 name: 世界模拟器
declaration: 回合互动、世界推进、角色扮演类体验的初始编排参考 declaration: 回合互动、世界推进、角色扮演类体验的设计方法
- id: expand-assistant - id: expand-assistant
name: 扩写助手 name: 扩写助手
declaration: 大纲/分段写作、写手统筹、成稿向助手类体验的初始编排参考 declaration: 大纲/分段写作、写手统筹、成稿向助手类体验的设计方法

View File

@@ -1,8 +1,31 @@
# 状态:待完善 — 作者细写「何时用 / 怎么调 / 建议近期 steps」 # 扩写助手 · 配方
# 本文件是增量起点:可按现场追加;勿一次排死全程 # 写方法论:适用、核心思路、设计流程、原则
# steps[].name 必须来自 modules/catalog.yaml共用组件池 # 各能力何时用 / 不用 → 读能力 meta编排器会注入勿在此重复
# steps = 近期起点,不是固定全程 DAG。
when: 大纲/分段扩写、写手统筹、先纲后章、成稿向助手类体验 when: 大纲/分段扩写、写手统筹、先纲后章、成稿向助手、长文/爽文类体验
hint: 初始参考。按用户意图增量追加步骤与依赖,勿机械照搬整份 steps。
brief: (占位)扩写助手类体验 core: >-
steps: [] 先钉清写手/统筹站位、分段轮转、爽点与禁忌;
再落到「谁写大纲、谁写正文」的可执行规格;
世界舞台与状态机仅在体验真需要时才引入,默认不做世界模拟全套。
process:
- 开始通常先做「美学纲领与交互范式」,钉清助手站位、分段节奏与体验禁忌。
- 之后对照能力池选型:态度/信息边界不够时用叙事指南;重要同类内容难稳定生成时用生成规则,需预生成时再排具体实例。
- 执行单元通常至少覆盖大纲/细纲与章节正文(可多次钉 Worker 规格),最后细化终稿并 closed。
- 世界蓝图、实现机制、拓扑、变量、状态栏等:仅当体验需要可引用舞台或状态机时再选。
principles:
- 正推写手体验,勿默认套「世界模拟」全套能力。
- 能力选型以能力 meta 为准;本配方不代替各能力写调用条件。
- 有编排参数的步骤须在进执行前钉齐 params禁止空壳进 design-step。
- 同能力可反复编入;已验收步骤不得删除。
- 收成前 status: closed产物进运行规格而非散文说明书。
brief: 扩写/写手类:先定站位与轮转,再落到大纲→分段写文规格
steps:
- id: 美学纲领与交互范式
name: 美学纲领与交互范式
depends_on: []

View File

@@ -1,15 +1,31 @@
# 世界模拟器 · 初始导演 # 世界模拟器 · 配方
# steps = 近期 horizon增量起点不是固定全程 DAG # 写方法论:适用、核心思路、设计流程、原则
# steps[].name 必须来自 modules/catalog.yaml可反复追加 repeatable 能力 # 各能力何时用 / 不用 → 读能力 meta编排器会注入勿在此重复
# steps = 近期起点,不是固定全程 DAG。
when: 回合互动、世界推进、角色扮演、沉浸推演类体验 when: 回合互动、世界推进、角色扮演、沉浸推演类体验
hint: >-
先只排「美学纲领与交互范式」;谈完后再增量追加。 core: >-
「生成规则」「具体实例」标了 repeatable可多次编入不同 step.id 先钉清用户如何参与、正文如何呈现、核心体验与禁忌;
其它按需:世界蓝图与人文地理 / 叙事指南 / 实现机制 / 再从体验反推:世界舞台、支撑机制、可生成内容、呈现与执行单元还缺什么;
拓扑图谱 / 变量* / 状态栏 / 回复格式 / Worker 规格 / 细化终稿。 按缺口增量设计最终收成可调度的运行规格Worker 集),而不是一次性堆满设定百科。
勿一次排完全程;收成前再 closed。
brief: 世界模拟类:先定体验与轮转,再增量落到可运行规格 process:
- 开始通常先做「美学纲领与交互范式」,确认站位、轮转与要反复感受到什么。
- 之后对照能力池的「何时用 / 何时不用」,只排近期真正缺的 14 步;不预设固定长链。
- 需要可引用舞台时用世界蓝图;需要识别体验支点时用实现机制;同类内容难稳定生成时用生成规则,需预生成时再排具体实例。
- 呈现、变量、拓扑、叙事等仅在体验真需要时再选。
- 游玩期执行结构清楚后,钉 Worker 规格并细化终稿;收成前将流程 status 设为 closed。
principles:
- 正推:体验 → 缺口 → 能力;禁止题材默认全选世界模拟套件。
- 能力选型以能力 meta 为准;本配方不代替各能力写调用条件。
- 有编排参数的步骤必须在进执行前钉齐 paramsaskUser 选项+其它),禁止空壳进 design-step。
- 同能力可反复编入(不同 step.id + params已验收步骤不得删除。
- 轻设定或用户明确不要世界骨架时,跳过不必要的世界/机制步骤。
brief: 世界模拟类:先定体验与轮转,再按缺口增量落到可运行规格
steps: steps:
- id: 美学纲领与交互范式 - id: 美学纲领与交互范式
name: 美学纲领与交互范式 name: 美学纲领与交互范式

View File

@@ -3,7 +3,7 @@ id: design-flow
skill: world-simulator skill: world-simulator
name: 创作 · 流程编排 name: 创作 · 流程编排
description: >- description: >-
【编排】以用户已选导演为起点,从能力池排出近期工序与依赖, 【编排】以用户已选配方为起点,从能力池排出近期工序与依赖,
产出/修订可变增量 DAG设计.创作流程)。本步不写美学/机制正文,不写 Worker 集。 产出/修订可变增量 DAG设计.创作流程)。本步不写美学/机制正文,不写 Worker 集。
version: 1 version: 1
stage: design stage: design
@@ -31,7 +31,7 @@ contextSegments:
- id: selected-recipe - id: selected-recipe
tier: static tier: static
tags: ["创作.选用配方"] tags: ["创作.选用配方"]
label: "## 【用户已选导演】只读引用" label: "## 【用户已选配方】只读引用"
- id: user-demand - id: user-demand
tier: dynamic tier: dynamic
tags: ["用户.需求", "book.brief", "用户.最新输入", "用户.worker答复", "用户.修订说明"] tags: ["用户.需求", "book.brief", "用户.最新输入", "用户.worker答复", "用户.修订说明"]
@@ -44,24 +44,23 @@ contextSegments:
上下文里会有: 上下文里会有:
1. **【用户已选导演】**用户在界面手动选定——方法起点,**不是**锁死流水线;**禁止**替用户改选其它导演 1. **【用户已选配方】**该方法的适用、核心思路、设计流程与原则 + 近期起点 steps——**不是**锁死流水线;**禁止**替用户改选其它配方
2. **【能力 · 可选工序】**:固定中文名 + 声明——步骤只能从这里选;标〔可反复〕的可多次编入 2. **【能力 · 可选工序】**:固定中文名 + 声明 + **何时用 / 何时不用 / 边界**(来自各能力 meta+(若有)编排参数——步骤只能从这里选;标〔可反复〕的可多次编入
3. **【已有剧本草案】/【已验收步骤】**:若有,在其上追加或改未验收步,**不要**推倒重来 3. **【已有剧本草案】/【已验收步骤】**:若有,在其上追加或改未验收步,**不要**推倒重来
## 增量 DAG核心 ## 增量 DAG核心
**禁止**一次排完全程固定长链。每次只排出**近期要做**的步骤(通常 14 步),`status` 默认 `"open"` **禁止**一次排完全程固定长链。每次只排出**近期要做**的步骤(通常 14 步),`status` 默认 `"open"`
典型节奏 选型规则
```text - **跟配方方法论**:用配方的 core / process / principles 理解整局怎么设计、何时收成。
先排「美学纲领与交互范式」→ 用户验收并跑完 - **跟能力 meta**:某步该不该排,看能力的「何时用 / 何时不用 / 边界」;**不要**在配方里找各能力调用条件,也不要凭题材默认全选。
→ 再调本 worker追加「生成规则」「具体实例」等 - 有「编排参数」声明的能力:写入 DAG 前必须钉齐 **必填 params**
→ 某类内容不够 → 再追加同能力(不同 id如 生成规则#2 - 参数不明时:**先 askUser**(优先 options + 允许其它),再产出流程;禁止把「生成什么 / 调用哪个规则」推迟到 design-step。
→ 准备收成 → 追加 Worker 规格 / 细化终稿,并设 status: "closed" - 用户先认可带参数的 DAG 雏形,再进入执行;用户提出新要求时,再调本 worker 修订未验收步或追加新步。
```
同能力**可以**多次出现(尤其〔可反复〕生成规则、具体实例、Worker 规格):每次一次调用、一次验收、产物写入同一 artifact增量补全 同能力**可以**多次出现(尤其〔可反复〕):每次一次调用、一次验收、产物写入同一 artifact增量补全id 应尽量带上调用目标,如 `生成规则·怪物`,避免无信息的 `#2`
## 产出(唯一) ## 产出(唯一)
@@ -73,8 +72,26 @@ contextSegments:
"status": "open", "status": "open",
"steps": [ "steps": [
{ "id": "美学纲领与交互范式", "name": "美学纲领与交互范式", "depends_on": [] }, { "id": "美学纲领与交互范式", "name": "美学纲领与交互范式", "depends_on": [] },
{ "id": "生成规则", "name": "生成规则", "depends_on": ["美学纲领与交互范式"] }, {
{ "id": "生成规则#2", "name": "生成规则", "depends_on": ["生成规则"] } "id": "生成规则·怪物",
"name": "生成规则",
"params": {
"target": "怪物",
"rule_id": "monsters",
"lifecycle_intent": "runtime_only"
},
"depends_on": ["美学纲领与交互范式"]
},
{
"id": "具体实例·重要NPC·开局",
"name": "具体实例",
"params": {
"rule_id": "major-npcs",
"batch_goal": "开局重要NPC",
"count": "按规则"
},
"depends_on": ["生成规则·重要NPC"]
}
] ]
} }
``` ```
@@ -83,22 +100,26 @@ contextSegments:
1. `steps` 数组顺序 = **建议执行顺序**(依赖须指向更前的步骤) 1. `steps` 数组顺序 = **建议执行顺序**(依赖须指向更前的步骤)
2. `name` = 能力池里的固定中文名(可重复) 2. `name` = 能力池里的固定中文名(可重复)
3. `id` = 本局步骤唯一键;同 name 多次时必须不同(如 `生成规则``生成规则#2` 3. `id` = 本局步骤唯一键;同 name 多次时必须不同;优先语义化(`生成规则·{对象}`
4. `depends_on` = 其它步骤的 **id**(若某 name 在本流程唯一,也可写该 name 4. `depends_on` = 其它步骤的 **id**(若某 name 在本流程唯一,也可写该 name
5. `status``"open"` = 还可能追加;`"closed"` = 不再扩步(可走收成) 5. `params` = 本步调用参数(对象)。能力目录声明了编排参数时,**必填项必须写出**;可选则能推断就写
6. 已验收步骤的 id **必须保留**;只能追加新步,或改未验收步的依赖/顺序 6. `status``"open"` = 还可能追加;`"closed"` = 不再扩步(可走收成)
7. 导演建议 steps 只作近期起点;按需选用,勿默认全选、勿一次排满 7. 已验收步骤的 id **必须保留**;只能追加新步,或改未验收步的依赖/顺序/params
8. **禁止**把「交互」与「美学」拆成两步 8. 配方建议 steps 只作近期起点;按能力 meta 按需选用,勿默认全选、勿一次排满
9. **禁止**在本步写能力正文、Worker 列表、表结构 9. **禁止**把「交互」与「美学」拆成两步
10. 信息不够影响选型时,用 askUser 问 12 点(优先带 options 10. **禁止**在本步写能力正文、Worker 列表、表结构
11. `summary``流程 · N 步 · open|closed · …` 11. 参数或选型不够时,用 askUser 问 12 点(**优先带 options并允许其它**
12. 依赖真实产物的步骤(如具体实例依赖某条生成规则)须等上游验收后再编排,并从产物中列出可选项供用户选
13. `summary``流程 · N 步 · open|closed · …`
## 自检 ## 自检
- 用户是否已选导演?(未选则不要硬编) - 用户是否已选配方?(未选则不要硬编)
- 是否只排了近期 horizon而不是假固定全图 - 是否只排了近期 horizon而不是假固定全图
- 每步是否按能力 meta 的何时用/不用判断过,而非题材默认?
- 每步 name 都在【能力】里?同名多次是否都有不同 id - 每步 name 都在【能力】里?同名多次是否都有不同 id
- 有编排参数的步骤,必填 params 是否已钉齐?缺参是否应先 askUser 而不是产出空壳?
- depends_on 是否都指向更靠前的步骤 id - depends_on 是否都指向更靠前的步骤 id
- 已验收 id 是否都还在? - 已验收 id 是否都还在?
- 需要反复补规则/实例时,是否用了新 id 追加而非改写旧步? - 需要反复补同类内容时,是否用了新 id + 新 params 追加而非改写旧步?
- 收成前是否把 `status` 设为 `closed` - 收成前是否把 `status` 设为 `closed`

View File

@@ -49,3 +49,4 @@ contextSegments:
4. 信息不足 → askUser 12 点(优先 options 4. 信息不足 → askUser 12 点(优先 options
5. `summary``{本步能力名} · …` 5. `summary``{本步能力名} · …`
6. **禁止**重排或扩写流程;流程只读。需要追加「再来一次生成规则」等 → 由总管再调 design-flow 6. **禁止**重排或扩写流程;流程只读。需要追加「再来一次生成规则」等 → 由总管再调 design-flow
7. **本步参数**由编排期写入 steps[].params程序会注入【本步参数】。按参数执行禁止再问「这一步生成什么 / 调用哪个规则」。参数缺失或与目录必填项不符 → 停止产出,提示返回 design-flow 补参

View File

@@ -23,7 +23,7 @@ function buildMainAgentSystemPrompt(
? workers.map((w) => `- ${w.id}${w.description}`).join("\n") ? workers.map((w) => `- ${w.id}${w.description}`).join("\n")
: "- (当前 skill 未加载 worker 列表)"; : "- (当前 skill 未加载 worker 列表)";
return `你是写作系统的导演Main Agent。你的职责是调度演员worker而不是直接创作正文。 return `你是写作系统的编排器Main Agent。你的职责是调度执行单元worker而不是直接创作正文。
规则: 规则:
1. 你不能直接生成小说/文章正文。 1. 你不能直接生成小说/文章正文。
@@ -34,27 +34,27 @@ function buildMainAgentSystemPrompt(
6. requiresApproval 表示运行 worker 前是否需要用户确认。代笔模式通常为 true。 6. requiresApproval 表示运行 worker 前是否需要用户确认。代笔模式通常为 true。
7. run_worker 可选 workerContext{ "roleId": "A" },用于 role-decide 等指定当前决策角色Runtime 写入 世界.当前角色.id 7. run_worker 可选 workerContext{ "roleId": "A" },用于 role-decide 等指定当前决策角色Runtime 写入 世界.当前角色.id
8. 你不能把未验收内容当作事实。 8. 你不能把未验收内容当作事实。
9. 向用户提问是 worker 的能ask_user tool不是独立 worker。导演只在调度层提问。 9. 向用户提问是 worker 的ask_user tool不是独立 worker。编排器只在调度层提问。
10. blackboardIndex 只有 tag 索引,不含正文 content。 10. blackboardIndex 只有 tag 索引,不含正文 content。
## 调度思维 ## 调度思维
用需求正推:「用户需要 [具体体验/能] → 调用 [worker/skill] 来 [生成/补充/调整] [什么],以便更好满足用户。」 用需求正推:「用户需要 [具体体验/能] → 调用 [worker/skill] 来 [生成/补充/调整] [什么],以便更好满足用户。」
禁止否定式路由:「某模式 / 背景形态 → 不需要某步骤 / 跳过某 worker」。 禁止否定式路由:「某模式 / 背景形态 → 不需要某步骤 / 跳过某 worker」。
反例(禁止):「背景为单一角色,无需世界构建」「不是规则怪谈,跳过 write-rules」「默认上世界模拟套件」 反例(禁止):「背景为单一角色,无需世界构建」「不是规则怪谈,跳过 write-rules」「默认上世界模拟套件」
正例:「用户已选世界模拟器导演且要网恋对话 → design-flow 排出近期增量步骤(可调味、可后补)→ 用户认可后反复 design-step需要再补规则/实例 → 再 design-flow 追加同能力 → 收成后若需开局 → opening-generator用户手动进 play」 正例:「用户已选世界模拟器配方且要网恋对话 → design-flow 排出近期增量步骤(可调味、可后补;有编排参数的步骤须钉 params)→ 用户认可后反复 design-step需要再补规则/实例 → 再 design-flow 追加同技能并写齐 params → 收成后若需开局 → opening-generator用户手动进 play」
当前 skill 可用 workerworkerId 必须与下列 id 完全一致): 当前 skill 可用 workerworkerId 必须与下列 id 完全一致):
${workerLines} ${workerLines}
## design 优先顺序 ## design 优先顺序
- 尚无「设计.创作流程」→ **design-flow**(近期 horizonstatus=open未选导演则先请用户选) - 尚无「设计.创作流程」→ **design-flow**(近期 horizonstatus=open未选配方则先请用户选)
- 流程已验收且还有未完成步骤 → **design-step**(一次一步;能由程序注入) - 流程已验收且还有未完成步骤 → **design-step**(一次一步;能由程序注入)
- 已列步骤都验收但流程仍 **status=open** → 再 **design-flow**(追加反复步或 closed - 已列步骤都验收但流程仍 **status=open** → 再 **design-flow**(追加反复步或 closed
- 禁止调度已废弃的 design-core / design-fixed / design-worker / design-refine - 禁止调度已废弃的 design-core / design-fixed / design-worker / design-refine
- 终稿已 accept 且可用 opening-generator、尚无开场产物 → opening-generator - 终稿已 accept 且可用 opening-generator、尚无开场产物 → opening-generator
- 进 play 由用户手动决定 - 进 play 由用户手动决定
- **禁止**替用户猜测或改选导演 - **禁止**替用户猜测或改选配方
- **禁止**一次编排排死全程固定 DAG - **禁止**一次编排排死全程固定 DAG
输出必须是 JSON 对象,字段: 输出必须是 JSON 对象,字段:

View File

@@ -68,29 +68,30 @@ function buildToolLoopSystemPrompt(
「不是规则怪谈,跳过 write-rules。」 「不是规则怪谈,跳过 write-rules。」
示例(好): 示例(好):
- 「用户已选导演且要 1v1 网恋 → design-flow 排出近期增量步骤(可调味)→ 认可后反复 design-step不够再追加。」 - 「用户已选配方且要 1v1 网恋 → design-flow 排出近期增量步骤(可调味)→ 认可后反复 design-step不够再追加。」
- 「尚无设计.创作流程 → run_worker(design-flow);有未完成步骤 → design-stepsteps 完但 status=open → 再 design-flow。」 - 「尚无设计.创作流程 → run_worker(design-flow);有未完成步骤 → design-stepsteps 完但 status=open → 再 design-flow。」
- 「Worker 集已 accept 且声明需要开局 → 调用 opening-generator 写开场白。」 - 「运行规格已 accept 且声明需要开局 → 调用 opening-generator 写开场白。」
示例(坏): 示例(坏):
- 「调度 design-core / design-fixed已废弃。」 - 「调度 design-core / design-fixed已废弃。」
- 「一次 design-flow 排死全程固定 DAG。」 - 「一次 design-flow 排死全程固定 DAG。」
- 「跳过流程编排直接写满 Worker 集。」 - 「跳过流程编排直接写满运行规格。」
- 「默认先上世界模拟全套再问用户要什么。」 - 「默认先上世界模拟全套再问用户要什么。」
- 「替用户改选 / 猜测导演。」 - 「替用户改选 / 猜测配方。」
在 reasoning / 可见 content 中请用 **正推句式** 写出调度理由;终止 tool 的 reason 字段同样用正推表述。 在 reasoning / 可见 content 中请用 **正推句式** 写出调度理由;终止 tool 的 reason 字段同样用正推表述。
## design 阶段提示 ## design 阶段提示
- 尚无「设计.创作流程」→ **优先 design-flow**(近期 horizonstatus=open未选则先请用户选 - 尚无「设计.创作流程」→ **优先 design-flow**(近期 horizonstatus=open未选则先请用户选
- 流程已验收、还有未完成步骤 → **design-step**(一次一步)。 - 流程已验收、还有未完成步骤 → **design-step**(一次一步)。
- 已列步骤全验收但 **status=open** → 再 **design-flow**(追加生成规则/具体实例等,或设 closed - 已列步骤全验收但 **status=open** → 再 **design-flow**(追加生成规则/具体实例等并钉齐 params,或设 closed
- 有编排参数的步骤缺必填 params → 先让 design-flow askUser不要空壳跑 design-step。
- 禁止 run_worker(design-core|design-fixed|design-worker|design-refine)——已废弃。 - 禁止 run_worker(design-core|design-fixed|design-worker|design-refine)——已废弃。
- 不要重复问用户「想做什么」——意图已在 用户.需求。 - 不要重复问用户「想做什么」——意图已在 用户.需求。
- Worker 集已 accept且可用 worker 含 opening-generator尚无开场产物 → opening-generator。 - 运行规格已 accept且可用 worker 含 opening-generator尚无开场产物 → opening-generator。
- 进 play 由用户手动决定。 - 进 play 由用户手动决定。
- 未声明开局、用户也未要求开场时,不要硬调 opening-generator。 - 未声明开局、用户也未要求开场时,不要硬调 opening-generator。
- **禁止**替用户猜测或改选导演 - **禁止**替用户猜测或改选配方
- **禁止**一次编排排死全程固定长链。 - **禁止**一次编排排死全程固定长链。
当前 skill 可用 worker 当前 skill 可用 worker
${workerLines} ${workerLines}

View File

@@ -177,7 +177,7 @@ export async function handleBooksApi(
return true; return true;
} }
/** 新建作品:导演一层选型(内部 = recipes catalog */ /** 新建作品:配方一层选型(内部 = recipes catalog */
if (pathname === "/api/directors" && req.method === "GET") { if (pathname === "/api/directors" && req.method === "GET") {
const { DEFAULT_ORCHESTRATOR_ID } = await import( const { DEFAULT_ORCHESTRATOR_ID } = await import(
"../config/default-orchestrator.js" "../config/default-orchestrator.js"
@@ -202,7 +202,7 @@ export async function handleBooksApi(
}); });
} catch (err) { } catch (err) {
json(res, 404, { json(res, 404, {
error: err instanceof Error ? err.message : "未找到导演列表", error: err instanceof Error ? err.message : "未找到配方列表",
}); });
} }
return true; return true;
@@ -229,13 +229,13 @@ export async function handleBooksApi(
}); });
} catch (err) { } catch (err) {
json(res, 404, { json(res, 404, {
error: err instanceof Error ? err.message : "未找到能包", error: err instanceof Error ? err.message : "未找到能包",
}); });
} }
return true; return true;
} }
/** 默认导演包的能力池(编排备选) */ /** 默认配方包的技能池(编排备选) */
if (pathname === "/api/modules" && req.method === "GET") { if (pathname === "/api/modules" && req.method === "GET") {
const { DEFAULT_ORCHESTRATOR_ID } = await import( const { DEFAULT_ORCHESTRATOR_ID } = await import(
"../config/default-orchestrator.js" "../config/default-orchestrator.js"
@@ -320,9 +320,9 @@ export async function handleBooksApi(
if (pathname === "/api/books" && req.method === "POST") { if (pathname === "/api/books" && req.method === "POST") {
const body = JSON.parse(await readBody(req)) as { const body = JSON.parse(await readBody(req)) as {
title?: string; title?: string;
/** 导演 Skill / 能力包 idregistry name */ /** 编排器包 idregistry name */
orchestratorId?: string; orchestratorId?: string;
/** 用户手动选定的导演 id内部 recipe */ /** 用户手动选定的配方 id内部 recipe */
recipeId?: string; recipeId?: string;
}; };
const skills = await listSkills(); const skills = await listSkills();
@@ -332,7 +332,7 @@ export async function handleBooksApi(
skills.find((s) => s.name === "world-simulator") || skills.find((s) => s.name === "world-simulator") ||
skills[0]; skills[0];
if (!director) { if (!director) {
json(res, 400, { error: "没有可用的导演 Skill能力包" }); json(res, 400, { error: "没有可用的编排器技能包" });
return true; return true;
} }
const book = createBook({ title: body.title }); const book = createBook({ title: body.title });

View File

@@ -1,6 +1,7 @@
/** /**
* 用户可见中文标签(与 docs/ui-glossary.md 同步)。 * 用户可见中文标签(与 docs/ui-glossary.md 同步)。
* 内部 id 不变;仅展示层映射。 * 内部 id 不变;仅展示层映射。
* 口径:配方 / 编排器 / 技能 / 工作流计划 / 运行规格 / 执行单元
*/ */
const STAGE_LABELS: Record<string, string> = { const STAGE_LABELS: Record<string, string> = {
@@ -15,15 +16,15 @@ const STAGE_LABELS: Record<string, string> = {
const WORKER_LABELS: Record<string, string> = { const WORKER_LABELS: Record<string, string> = {
"design-core": "创作 · 核心", "design-core": "创作 · 核心",
"design-worker": "创作 · 演员规格", "design-worker": "创作 · 执行单元规格",
"design-fixed": "创作 · 固定上下文", "design-fixed": "创作 · 固定上下文",
"design-refine": "创作 · 细化与终稿", "design-refine": "创作 · 细化与终稿",
"design-intake": "创作 · 综合收口", "design-intake": "创作 · 综合收口",
"design-flow": "创作 · 流程编排", "design-flow": "创作 · 流程编排",
"design-step": "创作 · 执行步骤", "design-step": "创作 · 执行步骤",
"opening-generator": "开局 · 开场白", "opening-generator": "开局 · 开场白",
orchestrator: "导演", orchestrator: "编排器",
"agent-burst": "导演调度", "agent-burst": "编排器调度",
narrator: "叙事转述", narrator: "叙事转述",
"role-decide": "角色决策", "role-decide": "角色决策",
"world-simulator": "世界推演", "world-simulator": "世界推演",
@@ -57,14 +58,14 @@ export function displayStageLabel(id: string | undefined | null): string {
return STAGE_LABELS[id] ?? id; return STAGE_LABELS[id] ?? id;
} }
/** 导演选项 / skill pack 展示名 */ /** 配方选项 / skill pack 展示名 */
export function displaySkillPackLabel(id: string | undefined | null): string { export function displaySkillPackLabel(id: string | undefined | null): string {
if (!id) return ""; if (!id) return "";
return SKILL_PACK_LABELS[id] ?? id; return SKILL_PACK_LABELS[id] ?? id;
} }
/** /**
* 演员 / 单位 / 能 id → 用户可见名(不含动作后缀)。 * 执行单元 / 单位 / 能 id → 用户可见名(不含动作后缀)。
*/ */
export function displayWorkerLabel(id: string | undefined | null): string { export function displayWorkerLabel(id: string | undefined | null): string {
if (!id) return ""; if (!id) return "";
@@ -79,11 +80,11 @@ export function displayWorkerLabel(id: string | undefined | null): string {
} }
if (trimmed.startsWith("worker:")) { if (trimmed.startsWith("worker:")) {
const ref = trimmed.slice("worker:".length); const ref = trimmed.slice("worker:".length);
return `演员 · ${displayWorkerLabel(ref)}`; return `执行单元 · ${displayWorkerLabel(ref)}`;
} }
if (trimmed.startsWith("fixed:")) { if (trimmed.startsWith("fixed:")) {
const topic = trimmed.slice("fixed:".length); const topic = trimmed.slice("fixed:".length);
return ` · ${FIXED_TOPIC_LABELS[topic] ?? topic}`; return `能 · ${FIXED_TOPIC_LABELS[topic] ?? topic}`;
} }
if (trimmed.startsWith("resident:")) { if (trimmed.startsWith("resident:")) {
return `常驻 · ${trimmed.slice("resident:".length)}`; return `常驻 · ${trimmed.slice("resident:".length)}`;
@@ -99,7 +100,7 @@ export function formatWorkerDisplayTitle(
workerId: string | undefined | null, workerId: string | undefined | null,
action: WorkerTitleAction = null, action: WorkerTitleAction = null,
): string { ): string {
const base = displayWorkerLabel(workerId) || "演员"; const base = displayWorkerLabel(workerId) || "执行单元";
switch (action) { switch (action) {
case "output": case "output":
return `${base} · 产出`; return `${base} · 产出`;
@@ -114,8 +115,8 @@ export function formatWorkerDisplayTitle(
} }
} }
/** 导演(调度 Agent相关标题 */ /** 编排器(调度 Agent相关标题 */
export function formatAgentDisplayTitle(detail?: string): string { export function formatAgentDisplayTitle(detail?: string): string {
if (detail?.trim()) return `导演 · ${detail.trim()}`; if (detail?.trim()) return `编排器 · ${detail.trim()}`;
return "导演"; return "编排器";
} }

View File

@@ -3,8 +3,8 @@
* 可变增量 DAG有序 steps + 每步 id/中文名 + depends_on可追加、可同能力多次。 * 可变增量 DAG有序 steps + 每步 id/中文名 + depends_on可追加、可同能力多次。
* *
* 两层内容(作者细写,运行时只搭骨架): * 两层内容(作者细写,运行时只搭骨架):
* - recipes/初始配方(给总管 / design-flow 的参考起点,可调味) * - recipes/配方方法论(适用、核心思路、设计流程、原则)+ 近期起点 steps
* - modules/:共用组件池(步骤名与方法正文;配方与总管都从这里选型) * - modules/:共用能力池;编排注入 meta 选型字段,执行注入方法全文
*/ */
import { readFile } from "node:fs/promises"; import { readFile } from "node:fs/promises";
import path from "node:path"; import path from "node:path";
@@ -25,6 +25,9 @@ const DEFAULT_SKILLS_ROOT = path.resolve(
"../../skills", "../../skills",
); );
/** 步骤调用参数(编排期钉死;执行期只读) */
export type CreationFlowStepParams = Record<string, unknown>;
export type CreationFlowStep = { export type CreationFlowStep = {
/** /**
* 本局步骤唯一 id验收与 depends_on 用这个)。 * 本局步骤唯一 id验收与 depends_on 用这个)。
@@ -35,6 +38,11 @@ export type CreationFlowStep = {
name: string; name: string;
/** 依赖的其它步骤 id旧稿若 name 唯一也可写 name */ /** 依赖的其它步骤 id旧稿若 name 唯一也可写 name */
depends_on: string[]; depends_on: string[];
/**
* 本步调用参数。有「编排参数」声明的能力必须在进 design-step 前钉齐必填项。
* 例:生成规则 → target具体实例 → rule_id。
*/
params?: CreationFlowStepParams;
}; };
export type CreationFlowStatus = "open" | "closed"; export type CreationFlowStatus = "open" | "closed";
@@ -51,6 +59,17 @@ export type CreationFlow = {
steps: CreationFlowStep[]; steps: CreationFlowStep[];
}; };
/** catalog 声明:编排进 DAG 时本步需要哪些调用参数 */
export type ModuleParamSpec = {
key: string;
/** 给人看的中文名 */
label: string;
/** 缺省 falsetrue = validateCreationFlow / 编排必须钉齐 */
required?: boolean;
/** 给编排器的短提示(选项从何来、可否其它) */
hint?: string;
};
export type ModuleCatalogEntry = { export type ModuleCatalogEntry = {
/** 目录文件夹名,如 aesthetics-interaction */ /** 目录文件夹名,如 aesthetics-interaction */
id: string; id: string;
@@ -69,6 +88,17 @@ export type ModuleCatalogEntry = {
* catalog 写了则作覆盖。程序发出,不经 LLM。 * catalog 写了则作覆盖。程序发出,不经 LLM。
*/ */
opening?: string; opening?: string;
/**
* 可选:编排期步骤参数声明。
* 有 required 项时steps[].params 必须在进执行前钉齐;勿把选型推迟到 design-step。
*/
params?: ModuleParamSpec[];
/** 来自 prompt.md ```meta何时该选用编排选型 */
when?: string;
/** 来自 prompt.md ```meta何时不该选用 */
when_not?: string;
/** 来自 prompt.md ```meta与其它能力的边界 */
boundary?: string;
}; };
/** 本步程序开场白正文design-step 发出后写入,供 LLM 看见) */ /** 本步程序开场白正文design-step 发出后写入,供 LLM 看见) */
@@ -95,14 +125,24 @@ export type RecipeCatalog = {
}; };
/** /**
* 单份初始配方详情。 * 单份配方详情。
* seed = 建议步骤可为空name 须 ∈ 模块池);编排时允许增删改 * 方法论字段供编排选型seed = 近期起点 steps可为空name 须 ∈ 模块池)。
*/ */
export type RecipeDetail = { export type RecipeDetail = {
id: string; id: string;
name: string; name: string;
declaration: string; declaration: string;
/** 适用什么体验/任务 */
when?: string; when?: string;
/** 整套设计方法的核心思路与最终目标 */
core?: string;
/** 设计流程:如何增量选型、何时收成(字符串或条目列表) */
process?: string | string[];
/** 配方特有取舍原则 */
principles?: string | string[];
/**
* @deprecated 旧字段;新配方用 core/process/principles。解析仍可读格式化时作兜底。
*/
hint?: string; hint?: string;
seed: CreationFlow | null; seed: CreationFlow | null;
}; };
@@ -125,6 +165,10 @@ export type CreationFlowUserView = {
/** 目录里的短声明(有则展示) */ /** 目录里的短声明(有则展示) */
declaration?: string; declaration?: string;
repeatable?: boolean; repeatable?: boolean;
/** 本步调用参数(编排期钉死) */
params?: CreationFlowStepParams;
/** 参数缺必填项时的提示(给人看) */
paramsMissing?: string[];
}>; }>;
parseError?: string; parseError?: string;
}; };
@@ -150,9 +194,65 @@ export function extractJsonObject(raw: string): unknown | null {
return null; return null;
} }
/** 规范化 steps[].params仅接受普通对象 */
export function normalizeStepParams(
raw: unknown,
): CreationFlowStepParams | undefined {
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
const out: CreationFlowStepParams = {};
for (const [k, v] of Object.entries(raw as Record<string, unknown>)) {
const key = k.trim();
if (!key) continue;
out[key] = v;
}
return Object.keys(out).length > 0 ? out : undefined;
}
/** 目录声明的必填参数中,本步仍缺失的 key按声明顺序 */
export function missingRequiredStepParams(
step: Pick<CreationFlowStep, "params">,
module: ModuleCatalogEntry | null | undefined,
): string[] {
const specs = module?.params ?? [];
if (specs.length === 0) return [];
const params = step.params ?? {};
const missing: string[] = [];
for (const spec of specs) {
if (!spec.required) continue;
const v = params[spec.key];
if (v == null) {
missing.push(spec.key);
continue;
}
if (typeof v === "string" && !v.trim()) {
missing.push(spec.key);
}
}
return missing;
}
/** 给人 / LLM 看的参数摘要 */
export function formatStepParamsForPrompt(
params: CreationFlowStepParams | null | undefined,
): string {
if (!params || Object.keys(params).length === 0) return "(无)";
return Object.entries(params)
.map(([k, v]) => {
const rendered =
typeof v === "string" ? v : JSON.stringify(v, null, 0);
return `- ${k}: ${rendered}`;
})
.join("\n");
}
/** 为缺 id 的步骤补齐唯一 id同 name 多次 → name#2、name#3… */ /** 为缺 id 的步骤补齐唯一 id同 name 多次 → name#2、name#3… */
export function ensureCreationFlowStepIds( export function ensureCreationFlowStepIds(
steps: Array<{ id?: string; name: string; depends_on: string[] }>, steps: Array<{
id?: string;
name: string;
depends_on: string[];
params?: CreationFlowStepParams;
}>,
): CreationFlowStep[] { ): CreationFlowStep[] {
const used = new Set<string>(); const used = new Set<string>();
const nameCount = new Map<string, number>(); const nameCount = new Map<string, number>();
@@ -177,6 +277,7 @@ export function ensureCreationFlowStepIds(
id, id,
name, name,
depends_on: raw.depends_on.map((d) => d.trim()).filter(Boolean), depends_on: raw.depends_on.map((d) => d.trim()).filter(Boolean),
...(raw.params ? { params: raw.params } : {}),
}); });
} }
return out; return out;
@@ -208,7 +309,12 @@ export function parseCreationFlow(raw: string | undefined | null): CreationFlow
const stepsRaw = row.steps; const stepsRaw = row.steps;
if (!Array.isArray(stepsRaw) || stepsRaw.length === 0) return null; if (!Array.isArray(stepsRaw) || stepsRaw.length === 0) return null;
const drafted: Array<{ id?: string; name: string; depends_on: string[] }> = []; const drafted: Array<{
id?: string;
name: string;
depends_on: string[];
params?: CreationFlowStepParams;
}> = [];
for (const item of stepsRaw) { for (const item of stepsRaw) {
if (!item || typeof item !== "object" || Array.isArray(item)) return null; if (!item || typeof item !== "object" || Array.isArray(item)) return null;
const s = item as Record<string, unknown>; const s = item as Record<string, unknown>;
@@ -219,7 +325,8 @@ export function parseCreationFlow(raw: string | undefined | null): CreationFlow
const depends_on = Array.isArray(depsRaw) const depends_on = Array.isArray(depsRaw)
? depsRaw.map((d) => String(d).trim()).filter(Boolean) ? depsRaw.map((d) => String(d).trim()).filter(Boolean)
: []; : [];
drafted.push({ id, name, depends_on }); const params = normalizeStepParams(s.params);
drafted.push({ id, name, depends_on, ...(params ? { params } : {}) });
} }
const steps = ensureCreationFlowStepIds(drafted); const steps = ensureCreationFlowStepIds(drafted);
@@ -264,6 +371,7 @@ export function parseModuleCatalog(raw: string): ModuleCatalog | null {
? m.opening.trim() ? m.opening.trim()
: undefined; : undefined;
const repeatable = m.repeatable === true; const repeatable = m.repeatable === true;
const params = parseModuleParamSpecs(m.params);
modules.push({ modules.push({
id, id,
name, name,
@@ -271,12 +379,36 @@ export function parseModuleCatalog(raw: string): ModuleCatalog | null {
artifact, artifact,
...(repeatable ? { repeatable: true } : {}), ...(repeatable ? { repeatable: true } : {}),
...(opening ? { opening } : {}), ...(opening ? { opening } : {}),
...(params ? { params } : {}),
}); });
} }
if (modules.length === 0) return null; if (modules.length === 0) return null;
return { modules }; return { modules };
} }
function parseModuleParamSpecs(raw: unknown): ModuleParamSpec[] | undefined {
if (!Array.isArray(raw) || raw.length === 0) return undefined;
const out: ModuleParamSpec[] = [];
for (const item of raw) {
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
const row = item as Record<string, unknown>;
const key = typeof row.key === "string" ? row.key.trim() : "";
const label = typeof row.label === "string" ? row.label.trim() : "";
if (!key || !label) continue;
const hint =
typeof row.hint === "string" && row.hint.trim()
? row.hint.trim()
: undefined;
out.push({
key,
label,
...(row.required === true ? { required: true } : {}),
...(hint ? { hint } : {}),
});
}
return out.length > 0 ? out : undefined;
}
/** /**
* 能力 prompt.md 可切割块fence 语言标签 = 块 id * 能力 prompt.md 可切割块fence 语言标签 = 块 id
* 标准块见 MODULE_SECTION_IDS程序只认 ```id … ```,不认散文标题 alone。 * 标准块见 MODULE_SECTION_IDS程序只认 ```id … ```,不认散文标题 alone。
@@ -327,6 +459,78 @@ export function getModuleSection(
return body || null; return body || null;
} }
/** 把 YAML 字段收成可展示的字符串(支持 string / string[] */
export function coerceYamlTextField(raw: unknown): string | undefined {
if (typeof raw === "string" && raw.trim()) return raw.trim();
if (Array.isArray(raw)) {
const lines = raw
.map((x) => (typeof x === "string" ? x.trim() : ""))
.filter(Boolean);
return lines.length ? lines.map((l) => `- ${l}`).join("\n") : undefined;
}
return undefined;
}
/**
* 从 prompt.md 的 ```meta 块解析选型字段。
* catalog 负责索引/paramswhen/when_not/boundary 以 meta 为准。
*/
export function parseModuleMetaFromPrompt(promptMd: string): {
declaration?: string;
when?: string;
when_not?: string;
boundary?: string;
} | null {
const metaRaw = getModuleSection(parseModulePromptSections(promptMd), "meta");
if (!metaRaw) return null;
let doc: unknown;
try {
doc = parseYaml(metaRaw);
} catch {
return null;
}
if (!doc || typeof doc !== "object" || Array.isArray(doc)) return null;
const row = doc as Record<string, unknown>;
const declaration = coerceYamlTextField(row.declaration);
const when = coerceYamlTextField(row.when);
const when_not = coerceYamlTextField(row.when_not);
const boundary = coerceYamlTextField(row.boundary);
if (!declaration && !when && !when_not && !boundary) return null;
return {
...(declaration ? { declaration } : {}),
...(when ? { when } : {}),
...(when_not ? { when_not } : {}),
...(boundary ? { boundary } : {}),
};
}
/**
* 用各能力 prompt.md 的 meta 充实目录条目(编排选型用)。
* declarationmeta 有则覆盖 catalogwhen/when_not/boundary仅来自 meta。
*/
export async function enrichModuleCatalogWithMeta(
catalog: ModuleCatalog,
skillPackRoot: string,
skillsRoot = DEFAULT_SKILLS_ROOT,
): Promise<ModuleCatalog> {
const modules = await Promise.all(
catalog.modules.map(async (m) => {
const prompt = await loadModulePrompt(skillPackRoot, m.id, skillsRoot);
if (!prompt) return m;
const meta = parseModuleMetaFromPrompt(prompt);
if (!meta) return m;
return {
...m,
...(meta.declaration ? { declaration: meta.declaration } : {}),
...(meta.when ? { when: meta.when } : {}),
...(meta.when_not ? { when_not: meta.when_not } : {}),
...(meta.boundary ? { boundary: meta.boundary } : {}),
};
}),
);
return { modules };
}
/** /**
* 从能力 prompt.md 抽取默认问题(开场白)。 * 从能力 prompt.md 抽取默认问题(开场白)。
* 只认 ```opening … ```(能力标准块)。 * 只认 ```opening … ```(能力标准块)。
@@ -416,19 +620,49 @@ export async function loadModuleCatalog(
const fullPath = path.join(skillsRoot, skillPackRoot, MODULE_CATALOG_FILENAME); const fullPath = path.join(skillsRoot, skillPackRoot, MODULE_CATALOG_FILENAME);
try { try {
const raw = await readFile(fullPath, "utf8"); const raw = await readFile(fullPath, "utf8");
return parseModuleCatalog(raw); const catalog = parseModuleCatalog(raw);
if (!catalog) return null;
return enrichModuleCatalogWithMeta(catalog, skillPackRoot, skillsRoot);
} catch { } catch {
return null; return null;
} }
} }
/** 注入 design-flow 的短目录(非全文 prompt */ /** 注入 design-flow:能力名 + 选型字段meta+ 编排参数;非执行全文 */
export function formatModuleCatalogForAgent(catalog: ModuleCatalog): string { export function formatModuleCatalogForAgent(catalog: ModuleCatalog): string {
const lines = catalog.modules.map((m) => { const lines = catalog.modules.map((m) => {
const flags = m.repeatable ? "〔可反复〕" : ""; const flags = m.repeatable ? "〔可反复〕" : "";
return `- ${m.name}${flags}${m.declaration}`; const parts: string[] = [`- ${m.name}${flags}${m.declaration}`];
if (m.when) parts.push(` 何时用:${indentMultiline(m.when, " ")}`);
if (m.when_not) parts.push(` 何时不用:${indentMultiline(m.when_not, " ")}`);
if (m.boundary) parts.push(` 边界:${indentMultiline(m.boundary, " ")}`);
if (m.params && m.params.length > 0) {
parts.push(
` 编排参数:${m.params
.map((p) => {
const req = p.required ? "必填" : "可选";
const hint = p.hint ? `${p.hint}` : "";
return `${p.key}${p.label}${req}${hint}`;
})
.join("")}`,
);
}
return parts.join("\n");
}); });
return `【能力 · 可选工序】(按需选用,勿默认全选;步骤名只能从这里选;标〔可反复〕的可多次编入)\n${lines.join("\n")}`; return [
"【能力 · 可选工序】",
"按需选用,勿默认全选;步骤名只能从这里选;标〔可反复〕的可多次编入。",
"选型依据是下方「何时用 / 何时不用 / 边界」(来自各能力 meta有「编排参数」的步骤必须在 DAG 里写齐 params缺参时用 askUser 选项+其它,禁止空壳进执行。",
"不要把能力执行全文塞进本步;执行由 design-step 注入。",
lines.join("\n"),
].join("\n");
}
/** 多行字段:首行接在标签后,续行缩进 */
function indentMultiline(text: string, indent: string): string {
const lines = text.split(/\r?\n/);
if (lines.length <= 1) return text;
return [lines[0], ...lines.slice(1).map((l) => `${indent}${l}`)].join("\n");
} }
export function parseRecipeCatalog(raw: string): RecipeCatalog | null { export function parseRecipeCatalog(raw: string): RecipeCatalog | null {
@@ -476,8 +710,8 @@ export async function loadRecipeCatalog(
} }
/** /**
* 解析单份 recipe.yamlwhen / hint / brief / steps * 解析单份 recipe.yamlwhen / core / process / principles / brief / steps
* steps 空或缺失 → seed 为 null仍可作选型参考 * 兼容旧字段 hint。steps 空或缺失 → seed 为 null仍可作选型参考
*/ */
export function parseRecipeYaml( export function parseRecipeYaml(
raw: string, raw: string,
@@ -507,6 +741,9 @@ export function parseRecipeYaml(
typeof row.when === "string" && row.when.trim() typeof row.when === "string" && row.when.trim()
? row.when.trim() ? row.when.trim()
: undefined; : undefined;
const core = coerceYamlTextField(row.core);
const process = normalizeRecipeListOrText(row.process);
const principles = normalizeRecipeListOrText(row.principles);
const hint = const hint =
typeof row.hint === "string" && row.hint.trim() typeof row.hint === "string" && row.hint.trim()
? row.hint.trim() ? row.hint.trim()
@@ -528,11 +765,28 @@ export function parseRecipeYaml(
name, name,
declaration: meta.declaration, declaration: meta.declaration,
when, when,
hint, ...(core ? { core } : {}),
...(process ? { process } : {}),
...(principles ? { principles } : {}),
...(hint ? { hint } : {}),
seed, seed,
}; };
} }
/** process / principles保留数组或收成单字符串 */
function normalizeRecipeListOrText(
raw: unknown,
): string | string[] | undefined {
if (typeof raw === "string" && raw.trim()) return raw.trim();
if (Array.isArray(raw)) {
const items = raw
.map((x) => (typeof x === "string" ? x.trim() : ""))
.filter(Boolean);
return items.length ? items : undefined;
}
return undefined;
}
export async function loadRecipeDetail( export async function loadRecipeDetail(
skillPackRoot: string, skillPackRoot: string,
entry: RecipeCatalogEntry, entry: RecipeCatalogEntry,
@@ -610,21 +864,36 @@ export function formatRecipeCatalogForAgent(catalog: RecipeCatalog): string {
const lines = catalog.recipes.map( const lines = catalog.recipes.map(
(r) => `- ${r.name}${r.declaration}`, (r) => `- ${r.name}${r.declaration}`,
); );
return `【可选导演】(须由用户手动选择)\n${lines.join("\n")}`; return `【可选配方】(须由用户手动选择)\n${lines.join("\n")}`;
} }
/** 注入 design-flow用户已选导演(内部 recipe */ /** 注入 design-flow用户已选配方(方法论 + 近期起点 */
export function formatSelectedRecipeForAgent(detail: RecipeDetail): string { export function formatSelectedRecipeForAgent(detail: RecipeDetail): string {
const lines: string[] = [ const lines: string[] = [
`【用户已选导演 · ${detail.name}`, `【用户已选配方 · ${detail.name}`,
"这是用户手动选定的方法起点,不是锁死流水线。", "这是用户手动选定的设计方法,不是锁死流水线。",
"产出**增量 DAG**:只排近期要做的步骤;已验收步保留,可追加同能多次调用(如生成规则 / 具体实例)。", "产出**增量工作流计划(DAG**:只排近期要做的步骤;已验收步保留,可追加同能多次调用。",
"按用户表述增删改未验收步骤与依赖(像现场改戏 / 调味);步骤名只能从【能力】选。", "按用户表述与配方方法论增删改未验收步骤与依赖;步骤名只能从【能力】选。",
"禁止改选其它导演;若用户要换导演,须等用户重新选定后再编排。", "能力「何时用 / 何时不用」以【能力 · 可选工序】为准;本配方不重复罗列各能力调用条件。",
"禁止改选其它配方;若用户要换配方,须等用户重新选定后再编排。",
]; ];
if (detail.declaration) lines.push(`简介:${detail.declaration}`); if (detail.declaration) lines.push(`简介:${detail.declaration}`);
if (detail.when) lines.push(`适用:${detail.when}`); if (detail.when) lines.push(`适用:${detail.when}`);
if (detail.hint) lines.push(`调味提示:${detail.hint}`); if (detail.core) {
lines.push("核心思路:");
lines.push(detail.core);
}
if (detail.process) {
lines.push("设计流程:");
lines.push(formatRecipeFieldBlock(detail.process));
}
if (detail.principles) {
lines.push("原则:");
lines.push(formatRecipeFieldBlock(detail.principles));
}
if (!detail.core && !detail.process && !detail.principles && detail.hint) {
lines.push(`调味提示(旧字段):${detail.hint}`);
}
if (detail.seed?.steps.length) { if (detail.seed?.steps.length) {
const stepsJson = JSON.stringify( const stepsJson = JSON.stringify(
{ {
@@ -645,7 +914,14 @@ export function formatSelectedRecipeForAgent(detail: RecipeDetail): string {
return lines.join("\n"); return lines.join("\n");
} }
/** design-flow 一次注入:已选配方 + 组件池 */ function formatRecipeFieldBlock(value: string | string[]): string {
if (Array.isArray(value)) {
return value.map((l) => `- ${l}`).join("\n");
}
return value;
}
/** design-flow 一次注入:已选配方 + 技能池 */
export function formatDesignFlowContentBlocks(params: { export function formatDesignFlowContentBlocks(params: {
selectedRecipe?: RecipeDetail | null; selectedRecipe?: RecipeDetail | null;
modules?: ModuleCatalog | null; modules?: ModuleCatalog | null;
@@ -655,9 +931,9 @@ export function formatDesignFlowContentBlocks(params: {
if (params.missingSelection) { if (params.missingSelection) {
blocks.push( blocks.push(
[ [
"【导演】用户尚未手动选择。", "【配方】用户尚未手动选择。",
"禁止自行猜测或替用户选定导演。", "禁止自行猜测或替用户选定配方。",
"请 askUser 请用户从可用导演中选择,或等待用户在界面选定后再编排。", "请 askUser 请用户从可用配方中选择,或等待用户在界面选定后再编排。",
].join("\n"), ].join("\n"),
); );
} else if (params.selectedRecipe) { } else if (params.selectedRecipe) {
@@ -735,6 +1011,21 @@ export function validateCreationFlow(
); );
} }
} }
if (mod?.params?.length) {
const missing = missingRequiredStepParams(step, mod);
if (missing.length > 0) {
const labels = missing
.map((key) => {
const spec = mod.params!.find((p) => p.key === key);
return spec ? `${key}${spec.label}` : key;
})
.join("、");
errors.push(
`${step.id}」缺少必填编排参数:${labels}(须在 design-flow 钉齐后再执行)`,
);
}
}
} }
return { ok: errors.length === 0, errors }; return { ok: errors.length === 0, errors };
@@ -762,6 +1053,7 @@ export function formatCreationFlowForUser(
const n = (seenName.get(s.name) ?? 0) + 1; const n = (seenName.get(s.name) ?? 0) + 1;
seenName.set(s.name, n); seenName.set(s.name, n);
const mod = decl.get(s.name); const mod = decl.get(s.name);
const paramsMissing = missingRequiredStepParams(s, mod);
return { return {
order: i + 1, order: i + 1,
id: s.id, id: s.id,
@@ -770,6 +1062,8 @@ export function formatCreationFlowForUser(
occurrence: n, occurrence: n,
declaration: mod?.declaration, declaration: mod?.declaration,
repeatable: mod?.repeatable, repeatable: mod?.repeatable,
...(s.params ? { params: s.params } : {}),
...(paramsMissing.length > 0 ? { paramsMissing } : {}),
}; };
}), }),
}; };

View File

@@ -510,6 +510,7 @@ export async function loadWorkerSkillWithContext(
resolveDesignStepBinding, resolveDesignStepBinding,
CREATION_CURRENT_STEP_TAG, CREATION_CURRENT_STEP_TAG,
CREATION_MODULE_OPENING_TAG, CREATION_MODULE_OPENING_TAG,
formatStepParamsForPrompt,
} = await import("./creation-flow.js"); } = await import("./creation-flow.js");
const binding = await resolveDesignStepBinding({ const binding = await resolveDesignStepBinding({
skillPackRoot: skill.skillPackRoot, skillPackRoot: skill.skillPackRoot,
@@ -522,7 +523,8 @@ export async function loadWorkerSkillWithContext(
const openingNote = binding.opening const openingNote = binding.opening
? `\n\n【程序开场】若黑板有「${CREATION_MODULE_OPENING_TAG}」,该默认问题已由程序发给用户(不经 LLM用户首答在「用户.worker答复」。勿重复同一开场白在其答复与提示词基础上继续追问或产出。` ? `\n\n【程序开场】若黑板有「${CREATION_MODULE_OPENING_TAG}」,该默认问题已由程序发给用户(不经 LLM用户首答在「用户.worker答复」。勿重复同一开场白在其答复与提示词基础上继续追问或产出。`
: ""; : "";
modulePromptBlock = `## 【本步方法 · ${binding.module.name}\n\n${binding.modulePrompt.trim()}${openingNote}`; const paramsBlock = `## 【本步参数】(编排期已钉;直接按此执行,勿再问「生成什么 / 调用哪个规则」)\n\n${formatStepParamsForPrompt(binding.step.params)}`;
modulePromptBlock = `${paramsBlock}\n\n## 【本步方法 · ${binding.module.name}\n\n${binding.modulePrompt.trim()}${openingNote}`;
const baseInputs = [ const baseInputs = [
"用户.需求", "用户.需求",
"book.brief", "book.brief",

View File

@@ -186,10 +186,23 @@ describe("creation-flow", () => {
expect( expect(
catalog?.modules.find((m) => m.name === "具体实例")?.repeatable, catalog?.modules.find((m) => m.name === "具体实例")?.repeatable,
).toBe(true); ).toBe(true);
expect(
catalog?.modules.find((m) => m.name === "生成规则")?.params?.[0]?.key,
).toBe("target");
expect(
catalog?.modules.find((m) => m.name === "具体实例")?.params?.[0]?.key,
).toBe("rule_id");
const gen = catalog?.modules.find((m) => m.name === "生成规则");
expect(gen?.when).toBeTruthy();
expect(gen?.when_not).toBeTruthy();
expect(gen?.boundary).toBeTruthy();
const block = formatModuleCatalogForAgent(catalog!); const block = formatModuleCatalogForAgent(catalog!);
expect(block).toContain("【能力"); expect(block).toContain("【能力");
expect(block).toContain("美学纲领与交互范式:"); expect(block).toContain("美学纲领与交互范式:");
expect(block).toContain("生成规则〔可反复〕"); expect(block).toContain("生成规则〔可反复〕");
expect(block).toContain("何时用");
expect(block).toContain("何时不用");
expect(block).toContain("编排参数");
expect(block).not.toContain("设计.美学纲领与交互范式"); expect(block).not.toContain("设计.美学纲领与交互范式");
}); });
@@ -203,15 +216,20 @@ describe("creation-flow", () => {
const details = await loadAllRecipeDetails("dialogue/world-simulator"); const details = await loadAllRecipeDetails("dialogue/world-simulator");
expect(details.length).toBeGreaterThanOrEqual(2); expect(details.length).toBeGreaterThanOrEqual(2);
expect(details.find((d) => d.id === "world-simulator")?.when).toBeTruthy(); const ws = details.find((d) => d.id === "world-simulator");
expect(ws?.when).toBeTruthy();
expect(ws?.core).toBeTruthy();
expect(ws?.process).toBeTruthy();
expect(ws?.principles).toBeTruthy();
expect( expect(
details ws?.seed?.steps.some((s) => s.name === "美学纲领与交互范式"),
.find((d) => d.id === "world-simulator")
?.seed?.steps.some((s) => s.name === "美学纲领与交互范式"),
).toBe(true); ).toBe(true);
expect(details.find((d) => d.id === "world-simulator")?.seed?.status).toBe( expect(ws?.seed?.status).toBe("open");
"open", const formatted = formatSelectedRecipeForAgent(ws!);
); expect(formatted).toContain("核心思路");
expect(formatted).toContain("设计流程");
expect(formatted).toContain("原则");
expect(formatted).not.toContain("调味提示");
}); });
it("parses selected recipe ref", () => { it("parses selected recipe ref", () => {
@@ -222,11 +240,16 @@ describe("creation-flow", () => {
expect(parseSelectedRecipeRef("")).toBeNull(); expect(parseSelectedRecipeRef("")).toBeNull();
}); });
it("parses recipe yaml with suggested steps", () => { it("parses recipe yaml with methodology fields", () => {
const detail = parseRecipeYaml( const detail = parseRecipeYaml(
` `
when: 测试适用 when: 测试适用
hint: 可调味 core: 核心一句话
process:
- 先美学
- 再按缺口选型
principles:
- 正推
brief: 测试 brief brief: 测试 brief
steps: steps:
- name: 美学纲领与交互范式 - name: 美学纲领与交互范式
@@ -235,6 +258,9 @@ steps:
{ id: "t", name: "测试配方", declaration: "测" }, { id: "t", name: "测试配方", declaration: "测" },
); );
expect(detail.when).toBe("测试适用"); expect(detail.when).toBe("测试适用");
expect(detail.core).toContain("核心一句话");
expect(detail.process).toEqual(["先美学", "再按缺口选型"]);
expect(detail.principles).toEqual(["正推"]);
expect(detail.seed?.status).toBe("open"); expect(detail.seed?.status).toBe("open");
expect(detail.seed?.steps).toEqual([ expect(detail.seed?.steps).toEqual([
{ {
@@ -243,10 +269,26 @@ steps:
depends_on: [], depends_on: [],
}, },
]); ]);
expect(formatSelectedRecipeForAgent(detail)).toContain("用户已选导演"); const formatted = formatSelectedRecipeForAgent(detail);
expect(formatSelectedRecipeForAgent(detail)).toContain("增量"); expect(formatted).toContain("用户已选配方");
expect(formatted).toContain("核心思路");
expect(formatted).toContain("增量");
}); });
it("falls back to legacy hint when methodology absent", () => {
const detail = parseRecipeYaml(
`
when: 旧配方
hint: 可调味
steps:
- name: 美学纲领与交互范式
depends_on: []
`,
{ id: "legacy", name: "旧", declaration: "测" },
);
expect(detail.hint).toBe("可调味");
expect(formatSelectedRecipeForAgent(detail)).toContain("调味提示(旧字段)");
});
it("parseRecipeCatalog skips incomplete rows", () => { it("parseRecipeCatalog skips incomplete rows", () => {
const cat = parseRecipeCatalog(` const cat = parseRecipeCatalog(`
recipes: recipes:
@@ -277,10 +319,12 @@ recipes:
{ selectedRecipeRef: "world-simulator" }, { selectedRecipeRef: "world-simulator" },
); );
expect(selected.worker.outputTags).toContain("设计.创作流程"); expect(selected.worker.outputTags).toContain("设计.创作流程");
expect(selected.promptBody).toContain("【用户已选导演 · 世界模拟器】"); expect(selected.promptBody).toContain("【用户已选配方 · 世界模拟器】");
expect(selected.promptBody).toContain("世界模拟器"); expect(selected.promptBody).toContain("世界模拟器");
expect(selected.promptBody).toContain("【能力"); expect(selected.promptBody).toContain("【能力");
expect(selected.promptBody).toContain("美学纲领与交互范式"); expect(selected.promptBody).toContain("美学纲领与交互范式");
expect(selected.promptBody).toContain("核心思路");
expect(selected.promptBody).toContain("何时用");
expect(selected.promptBody).toContain("增量"); expect(selected.promptBody).toContain("增量");
expect(selected.promptBody).not.toContain("【导演】用户尚未手动选择"); expect(selected.promptBody).not.toContain("【导演】用户尚未手动选择");
}); });
@@ -354,6 +398,72 @@ recipes:
expect(binding?.modulePrompt).not.toContain("最想反复感受到的是什么"); expect(binding?.modulePrompt).not.toContain("最想反复感受到的是什么");
}); });
it("parses and validates step params from catalog", async () => {
const flow = parseCreationFlow(`{
"status": "open",
"steps": [
{
"id": "生成规则·怪物",
"name": "生成规则",
"params": { "target": "怪物", "lifecycle_intent": "runtime_only" },
"depends_on": []
}
]
}`)!;
expect(flow.steps[0]?.params).toEqual({
target: "怪物",
lifecycle_intent: "runtime_only",
});
const view = formatCreationFlowForUser(flow);
expect(view.steps[0]?.params?.target).toBe("怪物");
const catalog = await loadModuleCatalog("dialogue/world-simulator");
expect(
catalog?.modules.find((m) => m.name === "生成规则")?.params?.some(
(p) => p.key === "target" && p.required,
),
).toBe(true);
expect(validateCreationFlow(flow, catalog).ok).toBe(true);
const missing = parseCreationFlow(`{
"steps": [{ "name": "生成规则", "depends_on": [] }]
}`)!;
const bad = validateCreationFlow(missing, catalog);
expect(bad.ok).toBe(false);
expect(bad.errors.some((e) => e.includes("target"))).toBe(true);
const block = formatModuleCatalogForAgent(catalog!);
expect(block).toContain("编排参数");
expect(block).toContain("target");
});
it("injects step params into design-step prompt", async () => {
const flowRaw = JSON.stringify({
steps: [
{
id: "生成规则·怪物",
name: "生成规则",
params: { target: "怪物", rule_id: "monsters" },
depends_on: [],
},
],
});
const loaded = await loadWorkerSkillWithContext(
"world-simulator",
"design-step",
undefined,
{
flowRaw,
currentStepName: "生成规则·怪物",
acceptedStepNames: [],
},
);
expect(loaded.promptBody).toContain("【本步参数】");
expect(loaded.promptBody).toContain("target: 怪物");
expect(loaded.promptBody).toContain("rule_id: monsters");
expect(loaded.worker.outputTags).toContain("设计.生成规则");
});
it("nextPendingStep respects deps and accepted by id", () => { it("nextPendingStep respects deps and accepted by id", () => {
const flow = parseCreationFlow(`{ const flow = parseCreationFlow(`{
"status": "open", "status": "open",

View File

@@ -21,10 +21,10 @@ describe("display-labels", () => {
it("maps creation unit ids", () => { it("maps creation unit ids", () => {
expect(displayWorkerLabel("phase:core")).toBe("单位 · 核心"); expect(displayWorkerLabel("phase:core")).toBe("单位 · 核心");
expect(displayWorkerLabel("fixed:interaction")).toBe("能 · 交互范式"); expect(displayWorkerLabel("fixed:interaction")).toBe("能 · 交互范式");
expect(displayWorkerLabel("fixed:aesthetics-interaction")).toBe( expect(displayWorkerLabel("fixed:aesthetics-interaction")).toBe(
"能 · 美学纲领与交互范式", "能 · 美学纲领与交互范式",
); );
expect(displayWorkerLabel("worker:narrator")).toBe("演员 · 叙事转述"); expect(displayWorkerLabel("worker:narrator")).toBe("执行单元 · 叙事转述");
}); });
}); });

View File

@@ -27,12 +27,12 @@ const MSG_CLASS = {
const MSG_LABEL = { const MSG_LABEL = {
user_input: "你", user_input: "你",
agent_tool: "工具", agent_tool: "工具",
orchestrator_decision: "导演", orchestrator_decision: "编排器",
orchestrator_thinking: "导演 · 思考", orchestrator_thinking: "编排器 · 思考",
orchestrator_prompt: "导演", orchestrator_prompt: "编排器",
orchestrator_assessment: "导演 · 内容评价", orchestrator_assessment: "编排器 · 内容评价",
worker_running: "Worker", worker_running: "执行单元",
worker_output: "Worker", worker_output: "执行单元",
worker_questions: "提问", worker_questions: "提问",
error: "错误", error: "错误",
system_info: "系统", system_info: "系统",
@@ -924,7 +924,7 @@ function renderCreationFlowView(flowView) {
return `<div class="review-parse-error" role="alert"> return `<div class="review-parse-error" role="alert">
<div class="review-parse-error-title">流程无法解析</div> <div class="review-parse-error-title">流程无法解析</div>
<p>${esc(flowView.parseError)}</p> <p>${esc(flowView.parseError)}</p>
<p class="review-parse-error-hint">需要 JSONsteps 数组,每步含 name与可选 iddepends_on可含 status=open|closed。</p> <p class="review-parse-error-hint">需要 JSONsteps 数组,每步含 name与可选 iddepends_on、可选 params;可含 status=open|closed。</p>
</div>`; </div>`;
} }
if (!flowView.steps?.length) return ""; if (!flowView.steps?.length) return "";
@@ -957,9 +957,19 @@ function renderCreationFlowView(flowView) {
s.id && s.id !== s.name s.id && s.id !== s.name
? `${esc(s.name)} <span class="flow-id">(${esc(s.id)})</span>` ? `${esc(s.name)} <span class="flow-id">(${esc(s.id)})</span>`
: esc(s.name); : esc(s.name);
const paramsText = formatFlowParams(s.params);
const paramsMissing =
s.paramsMissing?.length > 0
? `<span class="flow-params-missing">缺参:${esc(s.paramsMissing.join("、"))}</span>`
: "";
const paramsHtml = paramsText
? `<span class="flow-params">${esc(paramsText)}</span>`
: "";
return `<li class="flow-step"> return `<li class="flow-step">
<span class="flow-order">${esc(String(s.order))}</span> <span class="flow-order">${esc(String(s.order))}</span>
<span class="flow-name">${nameLabel}${occ}</span> <span class="flow-name">${nameLabel}${occ}</span>
${paramsHtml}
${paramsMissing}
<span class="flow-deps">依赖:${deps}</span> <span class="flow-deps">依赖:${deps}</span>
</li>`; </li>`;
}) })
@@ -973,6 +983,14 @@ function renderCreationFlowView(flowView) {
</section>`; </section>`;
} }
function formatFlowParams(params) {
if (!params || typeof params !== "object" || Array.isArray(params)) return "";
const parts = Object.entries(params)
.filter(([, v]) => v != null && String(v).trim() !== "")
.map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`);
return parts.length ? parts.join(" · ") : "";
}
function renderReviewFeedCard(review) { function renderReviewFeedCard(review) {
const flowHtml = review.creationFlowView const flowHtml = review.creationFlowView
? renderCreationFlowView(review.creationFlowView) ? renderCreationFlowView(review.creationFlowView)
@@ -1133,9 +1151,9 @@ export function renderMessageFeed(view, loading, handlers = {}) {
p.textContent = "游玩模式Agent 将按 Worker 集调度,推进世界与叙事。"; p.textContent = "游玩模式Agent 将按 Worker 集调度,推进世界与叙事。";
} else if (view.uiPrompt) { } else if (view.uiPrompt) {
const recipeLine = view.selectedRecipe?.name const recipeLine = view.selectedRecipe?.name
? `\n\n已选导演${view.selectedRecipe.name}` ? `\n\n已选配方${view.selectedRecipe.name}`
: view.recipes?.length : view.recipes?.length
? "\n\n请先在新建作品时选定导演" ? "\n\n请先在新建作品时选定配方"
: ""; : "";
p.textContent = `${view.uiPrompt}${recipeLine}`; p.textContent = `${view.uiPrompt}${recipeLine}`;
p.classList.add("empty-intake"); p.classList.add("empty-intake");

View File

@@ -28,7 +28,7 @@ const $ = (id) => document.getElementById(id);
const PHASE = { idle: "待命", running: "执行中", waiting_user: "等待你", done: "已完成", error: "出错" }; const PHASE = { idle: "待命", running: "执行中", waiting_user: "等待你", done: "已完成", error: "出错" };
const REASON = { const REASON = {
skill_selection: "选择能力包", skill_selection: "选择配方",
intake: "补充信息", intake: "补充信息",
input: "等待输入", input: "等待输入",
approve_step: "确认执行", approve_step: "确认执行",
@@ -748,7 +748,7 @@ function renderHeader(view, loading) {
$("work-title").textContent = view.bookTitle ?? "未命名作品"; $("work-title").textContent = view.bookTitle ?? "未命名作品";
const skill = displaySkillPackLabel(view.activeSkill) || const skill = displaySkillPackLabel(view.activeSkill) ||
view.selectedRecipe?.name || view.selectedRecipe?.name ||
"导演"; "配方";
const phase = view.waitingReason const phase = view.waitingReason
? REASON[view.waitingReason.kind] ?? view.phase ? REASON[view.waitingReason.kind] ?? view.phase
: PHASE[view.phase] ?? view.phase; : PHASE[view.phase] ?? view.phase;
@@ -988,10 +988,10 @@ async function populateDirectorSelect() {
const directors = data.directors ?? []; const directors = data.directors ?? [];
sel.innerHTML = ""; sel.innerHTML = "";
if (!directors.length) { if (!directors.length) {
sel.innerHTML = `<option value="">暂无导演</option>`; sel.innerHTML = `<option value="">暂无配方</option>`;
if (desc) { if (desc) {
desc.hidden = false; desc.hidden = false;
desc.textContent = "尚未配置导演选项recipes/catalog.yaml。"; desc.textContent = "尚未配置配方选项recipes/catalog.yaml。";
} }
return; return;
} }
@@ -1027,7 +1027,7 @@ async function createBook() {
const title = $("input-book-title").value.trim() || "未命名作品"; const title = $("input-book-title").value.trim() || "未命名作品";
const recipeId = $("select-director")?.value?.trim(); const recipeId = $("select-director")?.value?.trim();
if (!recipeId) { if (!recipeId) {
alert("请选择导演"); alert("请选择配方");
return; return;
} }
$("btn-create-book").disabled = true; $("btn-create-book").disabled = true;

View File

@@ -1,6 +1,6 @@
/** /**
* 与 docs/ui-glossary.md、src/server/display-labels.ts 保持同步。 * 与 docs/ui-glossary.md、src/server/display-labels.ts 保持同步。
* 用户侧拍摄术语:导演 / 剧本 / 演员 / 能力 * 用户侧口径:配方 / 编排器 / 技能 / 工作流计划 / 运行规格 / 执行单元
*/ */
const STAGE_LABELS = { const STAGE_LABELS = {
@@ -15,15 +15,15 @@ const STAGE_LABELS = {
const WORKER_LABELS = { const WORKER_LABELS = {
"design-core": "创作 · 核心", "design-core": "创作 · 核心",
"design-worker": "创作 · 演员规格", "design-worker": "创作 · 执行单元规格",
"design-fixed": "创作 · 固定上下文", "design-fixed": "创作 · 固定上下文",
"design-refine": "创作 · 细化与终稿", "design-refine": "创作 · 细化与终稿",
"design-intake": "创作 · 综合收口", "design-intake": "创作 · 综合收口",
"design-flow": "创作 · 流程编排", "design-flow": "创作 · 流程编排",
"design-step": "创作 · 执行步骤", "design-step": "创作 · 执行步骤",
"opening-generator": "开局 · 开场白", "opening-generator": "开局 · 开场白",
orchestrator: "导演", orchestrator: "编排器",
"agent-burst": "导演调度", "agent-burst": "编排器调度",
narrator: "叙事转述", narrator: "叙事转述",
"role-decide": "角色决策", "role-decide": "角色决策",
"world-simulator": "世界推演", "world-simulator": "世界推演",
@@ -72,11 +72,11 @@ export function displayWorkerLabel(id) {
} }
if (trimmed.startsWith("worker:")) { if (trimmed.startsWith("worker:")) {
const ref = trimmed.slice("worker:".length); const ref = trimmed.slice("worker:".length);
return `演员 · ${displayWorkerLabel(ref)}`; return `执行单元 · ${displayWorkerLabel(ref)}`;
} }
if (trimmed.startsWith("fixed:")) { if (trimmed.startsWith("fixed:")) {
const topic = trimmed.slice("fixed:".length); const topic = trimmed.slice("fixed:".length);
return ` · ${FIXED_TOPIC_LABELS[topic] ?? topic}`; return `能 · ${FIXED_TOPIC_LABELS[topic] ?? topic}`;
} }
if (trimmed.startsWith("resident:")) { if (trimmed.startsWith("resident:")) {
return `常驻 · ${trimmed.slice("resident:".length)}`; return `常驻 · ${trimmed.slice("resident:".length)}`;
@@ -85,7 +85,7 @@ export function displayWorkerLabel(id) {
} }
export function formatWorkerDisplayTitle(workerId, action = null) { export function formatWorkerDisplayTitle(workerId, action = null) {
const base = displayWorkerLabel(workerId) || "演员"; const base = displayWorkerLabel(workerId) || "执行单元";
if (action === "output") return `${base} · 产出`; if (action === "output") return `${base} · 产出`;
if (action === "questions") return `${base} · 提问`; if (action === "questions") return `${base} · 提问`;
if (action === "stub") return `${base} · 占位`; if (action === "stub") return `${base} · 占位`;

View File

@@ -13,12 +13,12 @@ function formatExportTime(iso) {
const KIND_LABELS = { const KIND_LABELS = {
user_input: "用户输入", user_input: "用户输入",
orchestrator_decision: "导演决策", orchestrator_decision: "编排器决策",
orchestrator_prompt: "导演询问", orchestrator_prompt: "编排器询问",
agent_tool: "Agent Tool", agent_tool: "工具",
worker_running: "Worker 执行", worker_running: "执行单元 · 执行",
worker_output: "Worker 产出", worker_output: "执行单元 · 产出",
worker_stub: "Worker 占位", worker_stub: "执行单元 · 占位",
system_info: "系统", system_info: "系统",
error: "错误", error: "错误",
}; };
@@ -39,7 +39,7 @@ export function sessionToMarkdown(view) {
if (view.skillCatalog?.length) { if (view.skillCatalog?.length) {
const stageLabel = view.lifecycleStage === "play" ? "游玩" : "创作"; const stageLabel = view.lifecycleStage === "play" ? "游玩" : "创作";
lines.push(`## ${stageLabel}清单`); lines.push(`## ${stageLabel}能清单`);
lines.push(""); lines.push("");
for (const skill of view.skillCatalog) { for (const skill of view.skillCatalog) {
const mark = const mark =

View File

@@ -33,7 +33,7 @@
</div> </div>
</div> </div>
<div class="main-head-right"> <div class="main-head-right">
<a class="link" href="/modules.html"></a> <a class="link" href="/modules.html"></a>
<a class="link" href="/stats.html">Token</a> <a class="link" href="/stats.html">Token</a>
<a class="link" href="/settings.html">设置</a> <a class="link" href="/settings.html">设置</a>
<button type="button" class="btn-sm" id="btn-save-instance" hidden>保存定稿</button> <button type="button" class="btn-sm" id="btn-save-instance" hidden>保存定稿</button>
@@ -88,9 +88,9 @@
<dialog id="dialog-new-book" class="dialog"> <dialog id="dialog-new-book" class="dialog">
<form method="dialog" id="form-new-book"> <form method="dialog" id="form-new-book">
<h2>新建作品</h2> <h2>新建作品</h2>
<p class="dialog-desc">选择导演,再起名。导演是本局方法起点,之后按对话谈成剧本(可调味)。</p> <p class="dialog-desc">选择配方,再起名。配方是本局方法起点,之后按对话谈成工作流计划与运行规格(可调味)。</p>
<label class="field"> <label class="field">
导演 配方
<select id="select-director" required> <select id="select-director" required>
<option value="">加载中…</option> <option value="">加载中…</option>
</select> </select>

View File

@@ -1,4 +1,4 @@
/* 能池浏览页 — 叠在 settings.css 壳上 */ /* 能池浏览页 — 叠在 settings.css 壳上 */
.mod-shell { .mod-shell {
max-width: 1280px; max-width: 1280px;

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>池 · Writing Agent</title> <title>能池 · Writing Agent</title>
<link rel="stylesheet" href="/settings.css" /> <link rel="stylesheet" href="/settings.css" />
<link rel="stylesheet" href="/modules.css" /> <link rel="stylesheet" href="/modules.css" />
</head> </head>
@@ -12,15 +12,15 @@
<a class="st-brand" href="/">Writing Agent</a> <a class="st-brand" href="/">Writing Agent</a>
<nav class="st-nav" aria-label="主导航"> <nav class="st-nav" aria-label="主导航">
<a href="/">对话</a> <a href="/">对话</a>
<a href="/modules.html" aria-current="page"></a> <a href="/modules.html" aria-current="page"></a>
<a href="/stats.html">Token</a> <a href="/stats.html">Token</a>
<a href="/settings.html">设置</a> <a href="/settings.html">设置</a>
</nav> </nav>
</header> </header>
<div class="st-shell mod-shell"> <div class="st-shell mod-shell">
<aside class="st-rail mod-rail" aria-label="能列表"> <aside class="st-rail mod-rail" aria-label="能列表">
<p class="st-rail-label">备选能</p> <p class="st-rail-label">备选</p>
<p class="mod-pack" id="pack-label">加载中…</p> <p class="mod-pack" id="pack-label">加载中…</p>
<div class="mod-filter"> <div class="mod-filter">
<input <input
@@ -38,14 +38,14 @@
</div> </div>
<nav class="mod-list" id="mod-list"></nav> <nav class="mod-list" id="mod-list"></nav>
<p class="st-rail-note"> <p class="st-rail-note">
导演编排剧本时从这里选型;本页只读浏览方法正文。 编排器编排工作流计划时从这里选型;本页只读浏览方法正文。
</p> </p>
</aside> </aside>
<main class="st-main mod-main"> <main class="st-main mod-main">
<header class="st-main-head"> <header class="st-main-head">
<div> <div>
<h1 id="panel-title"></h1> <h1 id="panel-title">能池</h1>
<p class="st-sub" id="panel-subtitle">选择左侧一项查看方法块</p> <p class="st-sub" id="panel-subtitle">选择左侧一项查看方法块</p>
</div> </div>
<div class="st-main-actions"> <div class="st-main-actions">
@@ -57,7 +57,7 @@
<p class="mod-error" id="mod-error" hidden></p> <p class="mod-error" id="mod-error" hidden></p>
<div class="st-body mod-body" id="mod-detail"> <div class="st-body mod-body" id="mod-detail">
<p class="mod-empty">从左侧选择一项能</p> <p class="mod-empty">从左侧选择一项</p>
</div> </div>
</main> </main>
</div> </div>

View File

@@ -193,7 +193,7 @@ async function boot() {
const data = await res.json(); const data = await res.json();
modulesCache = data.modules || []; modulesCache = data.modules || [];
document.getElementById("pack-label").textContent = document.getElementById("pack-label").textContent =
`导演包 · ${data.skillPackId || "—"} · ${modulesCache.length}`; `配方包 · ${data.skillPackId || "—"} · ${modulesCache.length}`;
renderList(); renderList();
const fromHash = decodeURIComponent((location.hash || "").replace(/^#/, "")); const fromHash = decodeURIComponent((location.hash || "").replace(/^#/, ""));

View File

@@ -11,7 +11,7 @@
<a class="st-brand" href="/">Writing Agent</a> <a class="st-brand" href="/">Writing Agent</a>
<nav class="st-nav" aria-label="主导航"> <nav class="st-nav" aria-label="主导航">
<a href="/">对话</a> <a href="/">对话</a>
<a href="/modules.html"></a> <a href="/modules.html"></a>
<a href="/stats.html">Token</a> <a href="/stats.html">Token</a>
<a href="/settings.html" aria-current="page">设置</a> <a href="/settings.html" aria-current="page">设置</a>
</nav> </nav>

View File

@@ -67,7 +67,7 @@
<body> <body>
<div class="stats-page"> <div class="stats-page">
<header> <header>
<p><a href="/">← 对话</a> · <a href="/modules.html"></a> · <a href="/settings.html">设置</a></p> <p><a href="/">← 对话</a> · <a href="/modules.html"></a> · <a href="/settings.html">设置</a></p>
<h1>Token 统计</h1> <h1>Token 统计</h1>
<p class="stats-muted">按时间戳筛选调用记录(存于本地 stats/*.jsonl</p> <p class="stats-muted">按时间戳筛选调用记录(存于本地 stats/*.jsonl</p>
</header> </header>

View File

@@ -569,10 +569,16 @@ body[data-lifecycle="play"] .panel-agent { background: #f7fef9; }
.flow-name { .flow-name {
font-weight: 600; font-weight: 600;
} }
.flow-params,
.flow-params-missing,
.flow-deps { .flow-deps {
grid-column: 2;
font-size: 12px; font-size: 12px;
color: var(--muted, #666); color: var(--muted, #666);
} }
.flow-params-missing {
color: var(--danger, #b42318);
}
.board-panel { .board-panel {
flex: 1; flex: 1;