关于 graph-world
graph-world 是用于在 GraphOS 中以节点优先方式设计游戏或应用逻辑的 skill。它规定数据、系统和事件的建模方式,并要求先验证图,再进行后续实现。
主要功能
- 01用 World 和嵌套 Context 建模领域
- 02用 Variant 节点定义类型化运行时数据
- 03在 System 中组织生命周期逻辑
- 04区分表示层与逻辑层事件命名
- 05检查模拟器状态和运行日志
适用场景
- 01设计新的游戏或应用世界模型
- 02用嵌套 Context 组织领域数据
- 03在编写生命周期逻辑前建模类型化状态
- 04调试模拟器事件流程
MCP 相关
graph-world 依赖 graph-management 提供的图检查和事务 API。它使用 GraphOS 图操作与模拟器端点;输入未说明 MCP 服务或客户端接口。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ abpilot-cc/ graphos --skill graph-world安装后在 Claude Code 中输入/graph-world确认已加载。
附带文件World.graph.json
详细介绍
GraphOS 技能:graph-world
使用节点优先架构,为任何游戏或应用设计 GraphOS 中的世界逻辑。
此技能依赖 graph-management 来检查图并应用事务。
完成图验证后,只要任务涉及 npm/TypeScript 项目初始化、生成代码集成,或 System 和 EventSystem 的运行时实现,就使用 graph-world-ts。
节点语义
- World:整个模型的单一根上下文。World 节点名称固定为
World。 - Context:位于 World 或 Context 之下的分层领域/数据模型节点。Context 属于逻辑/数据层,而非呈现层,但应公开 View 层需要观察的状态。Context 还内置存储语义,因此逻辑应优先复用现有的 Context 实例/状态,而非创建新的实例。
- Variant:位于 World 或 Context 之下的类型化变量定义。Variant 是持久化/存储运行时数据的默认设计载体。
- System:位于 World 或 Context 之下的生命周期逻辑节点。临时缓存或短暂的工作状态应在所属 System 内处理,而不是建模为存储的图数据。
- Event:World 级事件定义。事件命名必须体现其层级边界:以
On开头的名称表示呈现层事件,载荷应尽可能精简,最好不带载荷;以Logic开头的名称表示内部逻辑层事件,仅用于逻辑层内的世界/领域编排。 - EventSystem:由 Event 驱动的处理器。
事件命名边界(必需)
- 仅将
On前缀用于呈现层事件。 On...事件表示向 View/呈现层发出或来自该层的信号,载荷应尽可能精简;如果 View 可以通过观察 Context 数据推导状态,则最好不带载荷。- 仅将
Logic前缀用于内部逻辑层事件。 Logic...事件用于世界模型内部的领域/运行时协调,不应作为面向呈现层的事件名称。- 不要在同一个事件名称中混用这两种语义。如果一个事件涉及两类关注点,应将其拆分为一个逻辑事件和一个单独的呈现事件。
配置边界(必需)
- Graph 仅定义运行时逻辑结构:
World/Context/Variant/System/Event/EventSystem及其所有权/触发关系。 - 不要在 Graph 中建模仅用于配置的结构(例如配置目录、环境配置文件、调优表、功能标志映射、平台构建配置)。
- 在代码生成和运行时实现期间,应在代码中设计配置结构(例如
src/config.ts、类型化常量/接口、加载器/适配器),并将其保留在 Graph 拓扑之外。 - 如果某个字段仅用于配置实现,而非领域运行时状态,应将其保留在代码配置中,而不是放入 Graph
Variant。
适用场景
- 你要从头设计一个新的游戏/应用世界模型。
- 你需要将业务领域转换为嵌套的 Context 树。
- 你需要在编写生命周期逻辑前定义类型化数据变量(Variant)。
- 你需要由事件驱动的初始化或运行时流程(例如游戏启动)。
前提条件
- 首先加载并使用
graph-management技能。 - 修改前读取可用节点类型和当前图状态。
- 尽可能在每个设计步骤中使用一个完整的事务。
- 强制执行根节点命名约束:
World节点的name固定为'World'。
模拟器日志检查
当世界插件模拟器可用,且需要检查实际运行时的事件流,而不是仅依赖静态图结构时,请使用此方法。
- 启动模拟器或驱动其运行,直到目标分支或场景执行完毕。
- 通过 GraphOS 运行时查询
/api/world/log。 - 先读取默认响应,检查截至模拟器当前时间的所有日志。
- 调查单个分支时,使用
startTime和endTime缩小查询范围,以隔离模拟时间段。 - 如果
/api/world/log返回的数据量很大,请生成脚本分析数据,而不是依赖手动检查。
/api/world/log 的预期行为:
- 不带查询参数:返回模拟时间
<= current的日志。 - 仅带
startTime:返回[startTime, current]范围内的日志。 - 仅带
endTime:返回(-∞, endTime]范围内的日志。 - 同时带
startTime和endTime:返回[startTime, endTime]范围内的日志。
当 /api/world/log 的响应很大时:
- 生成一个简短的分析脚本,用于解析、筛选、分组和汇总日志记录。
- 优先输出脚本分析结果,而不是完整的原始日志;生成精简摘要,例如事件计数、时间范围、目标 Context ID 和可疑错误模式。
- 在修改图或运行时之前,使用脚本隔离正在调查的具体分支、Event、System 或 Context 变更。
- 脚本应聚焦于当前调试目标,并明确设置筛选条件,例如事件名称、日志类型、Context ID 或模拟时间范围。
- 如有需要,通过细化脚本筛选条件逐步排查,而不是反复手动读取完整的
/api/world/log数据。
使用模拟器日志检查来:
- 验证是否生成了预期的
spawn、change、despawn和event记录。 - 确认
System或EventSystem是否在预期的模拟时间段内更改了目标 Context 数据。 - 在修补图拓扑或生成的逻辑之前,缩小运行时缺陷的排查范围。
模拟器控制 API
使用以下端点通过 HTTP 控制模拟器执行。三个端点均接受 POST 请求,并在成功时返回 { ok: true }。
GET /api/world/state— 获取模拟器当前状态。返回{ duration, current, state, scale, fps }。state的值为'running' | 'paused' | 'loading' | 'stopped'之一。POST /api/world/start— 从零时刻启动模拟器时钟。开始推进时间并执行生命周期逻辑。POST /api/world/pause— 暂停模拟器时钟。日志记录继续进行,但时间停止推进。POST /api/world/resume— 从暂停处恢复模拟器时钟。POST /api/world/reset— 将模拟器重置为初始状态,清除所有运行时状态和日志。POST /api/world/event— 向模拟器发送客户端事件。请求正文必须符合IEvent接口。模拟器会通过事件系统分发该事件,就像它来自已连接的客户端一样。
示例:interface IEvent { type: string; [key: string]: unknown; }{ "type": "MyEvent", ...additional fields as needed }
修改规则(强制顺序)
这些规则是任何变更工作流都必须遵守的硬性约束:
- 数据模型和数据逻辑变更必须先应用到 Graph。
- 在编写下游代码、文档或任务之前,先在 Graph 中完成所需的 Context/Variant/System/Event/EventSystem 更新。
- Graph 变更后立即验证逻辑是否闭环。
- 运行 Step 4 闭环检查,并确保所有闭环维度均通过。
- 只有闭环验证通过后,才能继续执行其他任务。
- 如果闭环检查失败,先返回 Graph 修补;不得继续非 Graph 工作。
- 每次 Graph 变更成功后,都要更新
gen/README.md,记录变更。- 记录新增、修改或删除的内容及其原因。
- 追加到变更日志部分;不要覆盖之前的记录。
- 每次 Graph 变更成功后,都要更新
gen/GRAPH.md,写入完整的当前流程图和闭环检查点。- 确保流程图与实际的 Step 0-6 工作流同步。
- 验证流程图仍然闭环(检查失败时会返回到修补步骤)。
流程
Step 0:读取当前状态
- 调用
get_available_node_types以验证节点模式。 - 调用
get_graph_description以识别当前根节点、上下文和缺口。 - 如果要扩展现有区域,调用
get_graph_node检查焦点节点。
完成检查:
- 确认是否已存在 World 节点。
- 确认 World 根节点的
name正好是'World'。 - 确认新 Context/Variant/System/Event 节点应挂接的位置。
Step 1:构建数据模型和变体
目标:先创建结构模型,再为其数据指定类型。
- 确保恰好存在一个
World根节点。- 根节点名称必须正好是
World;不要重命名,也不要创建其他根节点名称。
- 根节点名称必须正好是
- 按领域边界创建
Context树:- 从宽泛到具体,例如:
Gameplay->Player->Inventory。 - 保持同级 Context 内聚且低耦合。
- 从宽泛到具体,例如:
- 在每个相关的
World/Context下添加Variant节点:- 设置具有稳定语义的
name。 - 将
type设置为string|float|integer|boolean|JSONSchema中的一种。 - 如果
type=JSONSchema,则提供包含必需字段的jsonSchema。 - 仅对运行时真正必需的数据标记
required。
- 设置具有稳定语义的
- 应用事务并重新读取 Graph。
决策要点:
- 用
Context表示领域边界或所有权范围。 - 用
Variant表示范围内的类型化数据,尤其是在需求涉及存储或持久化时。 - 仅对结构化对象使用
JSONSchema;其他情况优先使用原始类型。 - 如果数据必须作为 Graph 定义状态的一部分保留,则将其设计为
Variant。 - 如果数据只是临时缓存、中间计算结果或帧内工作集,则将其保留在相关
System中,而不要添加Variant。 - 如果数据仅用于配置(构建/运行时调优、环境选择、功能标志、生成器选项),则不要在 Graph 中定义;应在生成/实现期间通过代码配置定义。
- Graph 设计应仅包含逻辑/领域状态,不包含表现层组件、样式、动画或渲染相关内容。
- 设计
Context及其Variant,确保 View 层能通过观察/绑定响应数据变更。 - 如果 View 依赖显式运行时状态,例如 loading、selected、active、disabled、visible、phase 或 mode,应将这些状态建模为
Context/Variant中的逻辑状态,而不要让它们隐含在表现层中。
完成检查:
- 每个核心领域都有一个 Context 作为所有者。
- 每项运行时关键数据都有一个明确指定类型的 Variant。
- 不存在没有明确 World/Context 父节点的孤立 Variant。
第 2 步:根据数据模型定义系统
目标:将生命周期行为绑定到现有数据模型范围。
- 为每个行为单元在其所属
World/Context下创建一个System。 - 根据实现契约定义所需的生命周期入口:
spawn、despawn、update、change。
- 为每个已实现的生命周期方法编写文档,清楚说明其意图、触发条件和目标数据范围。
- 确保系统职责与邻近的 Context/Variant 所有权保持一致。
- 应用并验证拓扑。
决策要点:
- 将 System 放置在拥有其所修改数据的最近范围内。
- 初始化使用
Spawn,循环逻辑使用Update,响应式同步使用Change,清理使用Despawn。 - 如果单个节点涵盖了互不相关的职责,则拆分 System。
System实现中不得包含表现层逻辑(渲染、样式、动画、UI 编排)。System逻辑只能由Context/Variant状态和领域规则驱动。- 临时缓存数据应保留在所属
System内部;除非缓存状态必须作为领域模型的一部分存储,否则不要将其提升为图中的Variant。
完成检查:
- 每个已实现的生命周期方法都有对应的说明。
- Systems 已附加到正确的 World/Context 范围。
- 每个生命周期方法都有明确的触发条件和数据目标。
实现交接:
- 第 4 步通过后,使用
graph-world-ts实现具体的 TypeScriptSystem代码、启动引导连接、生成类型集成,以及src/app.ts注册。
第 3 步:定义事件和 EventSystems
目标:在数据和生命周期基础稳定后,对事件驱动流程建模。
- 在
World下为关键领域事件创建Event节点:- 示例:
GameStarted、UserRegistered、SessionRestored。
- 示例:
- 如果需要事件载荷,则在每个
Event下附加Variant节点。 - 在每个
Event下创建EventSystem处理程序:- 说明处理程序如何创建/初始化/更新 Context 实例。
- 应用事务并验证事件与处理程序的完整性。
决策要点:
- 在跨 Context 或具有明确触发边界的场景中创建
Event。 - 如果处理逻辑应与逐帧 System 逻辑解耦,则使用
EventSystem。 - 对于引导流程,优先使用明确的启动/引导事件及其处理程序。
- 对于面向 UI 的事件,尽量精简 Event 数据模型;除非确实需要,否则优先不定义载荷字段。
- 表现层事件以
On为前缀命名,并尽可能保持其信号式特征。 - 内部逻辑层事件以
Logic为前缀命名,用于领域编排,而非面向 View 的通知。
完成检查:
- 每个关键触发条件都有一个 Event。
- 每个 Event 至少有一个预期的 EventSystem 处理程序(或明确记录为未来工作)。
- Event 载荷 Variants 符合处理程序的输入预期。
实现交接:
- Graph 触发链验证通过后,使用
graph-world-ts实现具体的 TypeScriptEventSystem处理程序,重新生成./gen/World类型,并在src/app.ts中连接注册。
步骤 4:闭环验证与完成
目标:验证模型是否端到端闭环;如果没有,则补齐缺失环节并重新验证。
- 完成步骤 1–3 后运行完整验证:
- 重新运行
get_graph_description,并将预期拓扑与实际图进行比较。 - 可选择使用
get_graph_node检查关键节点(World、核心 Context、引导 Event)。
- 重新运行
- 验证闭环维度:
- 结构闭环:只有一个 World 根节点,且不存在孤立的 Context/Variant/System/Event/EventSystem。
- 数据闭环:每项关键运行时数据都以类型化 Variant 的形式存在,并具有所属作用域。
- 行为闭环:每个已实现的生命周期方法都有具体描述和目标数据。
- 触发闭环:引导触发器和关键领域触发器均映射到 Event -> EventSystem -> 目标 Context 更新。
- 事务闭环:所有应用结果均成功,或已通过重试解决部分失败。
- 如果任一闭环检查失败,则进行分类,并在一个专注的事务批次中修补缺口:
- 缺少结构/数据 -> 返回步骤 1。
- 缺少生命周期方法覆盖 -> 返回步骤 2。
- 缺少事件触发器/处理器链 -> 返回步骤 3。
- 重新运行闭环验证,直到所有维度均通过。
- 生成最终验证摘要:
- 添加的节点/边。
- 仍待处理的事项(如有),并明确说明原因。
- 确认模型已形成闭环,可进入下一轮迭代。
完成检查:
- 五个闭环维度均通过。
- 不存在尚未解决的关键缺口。
- 最终图描述与预期领域设计一致。
步骤 5:更新 gen/README.md 变更日志
目标:以易读的形式记录每次图变更会话。
- 打开(或创建)
gen/README.md。 - 按照以下格式,在
## Change Log部分下追加一条新的变更记录:
### YYYY-MM-DD — <short summary>
**Added**
- <node type> `<node name>` under `<parent>`: <reason>
**Modified**
- <node type> `<node name>`: <what changed and why>
**Removed**
- <node type> `<node name>`: <reason>
**Notes**
- <any closure gaps deferred, design decisions, or follow-up items>
- 不要覆盖以前的记录——始终追加。
- 每条记录保持简洁(每个节点变更一行即可)。
完成检查:
gen/README.md存在,并包含本次会话的最新变更记录。- 列出了所有新增/修改/移除的节点。
- 注明了待处理事项或已知缺口。
步骤 6:更新 gen/GRAPH.md 完整流程图
目标:维护一份可执行的流程图,准确反映当前工作流和闭环过程。
- 打开(或创建)
gen/GRAPH.md。 - 维护一份涵盖端到端流程的完整 Mermaid 流程图:
- 包含步骤 0 至步骤 6。
- 包含闭环维度和检查失败时的重试循环。
- 每次图变更会话后,如果任何步骤、关卡或重试路径发生变化,就更新流程图。
- 验证流程图是否正确闭环:
- 任何闭环检查/关卡失败都必须返回正确的修补步骤。
- 成功路径必须以最终验证摘要结束。
完成检查:
gen/GRAPH.md存在,并包含最新的完整流程图。- 流程图包含所有有效步骤(0–6)和重试分支。
- 已验证图中的闭环:成功/失败路径均无断点,且不存在缺失的回边。
质量关卡(最终审查)
- 结构关卡:恰好有一个 World 根节点,其
name必须严格等于'World',且 Context 树结构合理。 - 类型关卡:Variant 的类型正确;JSONSchema 节点包含有效的 schema 文本。
- 所有权关卡:System 和 Variant 均附加到拥有其数据的作用域。
- 事件关卡:Event/EventSystem 配对覆盖引导触发器和关键领域触发器。
- 验证关卡:每次应用后重新运行
get_graph_description,并确认节点/边的增量符合预期。 - 图示关卡:已更新
gen/GRAPH.md,且其内容反映当前的闭环工作流。 - 配置边界关卡:图中不包含仅用于配置的结构;配置设计在生成代码/运行时代码中实现。
建议的提示词输入
- “设计一个 Roguelike 游戏世界,包含玩家、地图、战斗和引导事件流。”
- “构建一个电子商务世界模型,包含目录、订单和支付上下文,以及事件驱动的订单创建。”
- “创建一个智能家居应用模型,包含设备上下文、生命周期系统和设备连接事件处理。”
参考示例
skills/graph-world/World.graph.json 是一个完整的真实世界图,适用于一款名为 Merge Chicken 的塔防游戏。设计新世界时,可将其作为具体参考。
结构概览
World
└── Game (Context) — shared game data
├── time (float) — game time (seconds)
├── gold (integer) — gold coins
├── wave (JSONSchema) — current enemy wave {value, state, start_time}
├── egg (JSONSchema) — egg cooldown config {time, cooldown, ...}
├── buy (JSONSchema) — buy-chicken config {gold, increaseGold, ...}
├── heal (JSONSchema) — heal config {gold, value}
├── health (JSONSchema) — global game health {value, max}
├── grid (JSONSchema) — map grid {cols, rows, cell_size}
├── reward (JSONSchema) — claim-reward state
├── status (string) — game status: none/running/paused/failed/success
├── Ally (Context) — allied units (chickens)
│ ├── level (integer)
│ ├── attack (JSONSchema) — {damage, speed, radius}
│ ├── skin (string)
│ ├── pos (JSONSchema) — grid integer position {x, y}
│ ├── ally_gold (Variant) — chicken gold-production config
│ ├── AllyAttackSystem — launch attacks and shoot bullets based on attack data
│ └── AllyGoldSystem — periodically reward gold; higher level yields more gold
├── Enemy (Context) — enemy units (dogs)
│ ├── level, attack, health, move (JSONSchema)
│ ├── skin (string), state (string: idle/walk/attack)
│ ├── pos (JSONSchema) — world float position {x, y}
│ └── EnemyMoveSystem — movement + attack-range check + self-destruct logic
├── Bullet (Context) — bullets
│ ├── damage, speed, max_count, radius (float/integer)
│ ├── pos, dst (JSONSchema) — world float position
│ ├── skin (integer)
│ └── BulletMoveSystem — bullet movement + enemy collision + attack logic
├── WaveSystem — enemy wave spawn scheduling
└── GameSystem — initialize Game singleton, config-driven
Events (under World):
Merge → MergeEventSystem — move / swap / merge chickens
Egg → EggEventSystem — spawn chicken (free)
Buy → BuyEventSystem — buy chicken (costs gold)
Heal → HealEventSystem — restore game health
IncreaseHealth → IncreaseHealthEventSystem — permanently increase max health
Toast → (tag, message) — notification message
Pause → PauseEventSystem — pause game
Resume → ResumeEventSystem — resume game
Reset → ResetEventSystem — restart after defeat (clear enemies + restore 50% health)
ClaimReward → ClaimRewardEventSystem — claim stage-clear reward (multiplier supported)
此示例中的关键设计模式
- 用于结构化数据的 JSONSchema:当某个字段包含相关子字段(例如,
attack = {damage, speed, radius})时,使用JSONSchemaVariant 类型。标量值则使用基本类型(float、integer、string)。 - 配置驱动的系统:
GameSystem初始化单例 Game 上下文,并从 Variant 字段读取所有可配置参数(成本、冷却时间、缩放参数),绝不硬编码值。 - 单例上下文访问:系统和 EventSystem 始终通过固定 id(`getGameById('id'))获取 Game 上下文,而非按子节点位置查找。
- 事件载荷精简:
Merge等事件仅携带所需的最少载荷(ally_id、dst)。处理器从 Context 中推导其余状态。 - System 缓存中的临时状态:帧内临时工作集(子弹与敌人的碰撞候选项、每帧的移动目标)保存在 System 闭包作用域中,而非作为图 Variant。
- 波次难度缩放:
WaveSystem读取wave.value以调整敌人数量和属性——所有缩放参数都通过可配置的 Variant 设置,而非嵌入常量。 - 重置流程:
ResetEventSystem处理Reset事件:销毁所有 Enemy 和 Bullet 上下文,按可配置百分比恢复生命值,并在等待一段时间后重新触发波次生成。
执行说明
- 优先使用
apply_graph_transaction执行原子变更批次。 - 如果部分操作成功,请检查
errors,并仅重试失败的意图。 - 迭代演进时保持节点 id 稳定。
完整流程图
flowchart TD
A[Start: load graph-world skill] --> B[Preconditions\nload graph-management\nread node types + graph state]
B --> C[Step 0\nRead Current State]
C --> D[Step 1\nBuild Context tree + Variants]
D --> E{Step 1 complete?\nno orphan data\nall key variants typed}
E -- No --> D
E -- Yes --> F[Step 2\nDefine Systems]
F --> G{Step 2 complete?\nlifecycle methods + intent docs\nownership aligned}
G -- No --> F
G -- Yes --> H[Step 3\nDefine Events + EventSystems]
H --> I{Step 3 complete?\ncritical events covered\nhandler chain defined}
I -- No --> H
I -- Yes --> J[Step 4\nClosed-Loop Validation]
J --> K{Structure closure?\n(single World, no orphans)}
K -- No --> D
K -- Yes --> L{Data closure?\n(typed variants + owner scope)}
L -- No --> D
L -- Yes --> M{Behavior closure?\n(system timing -> descriptions -> data target)}
M -- No --> F
M -- Yes --> N{Trigger closure?\n(Event -> EventSystem -> Context update)}
N -- No --> H
N -- Yes --> O{Transaction closure?\n(apply success/retry resolved)}
O -- No --> P[Inspect errors\nretry failed intent only]
P --> J
O -- Yes --> Q[Quality Gates Final Review]
Q --> R{All gates passed?}
R -- No --> J
R -- Yes --> T[Step 5\nUpdate gen/README.md change log]
T --> U[Step 6\nUpdate gen/GRAPH.md full flowchart\nand verify diagram closed-loop]
U --> S[Output final verification summary\nClosed-loop model complete]