mcpField
G
graph-world

graph-world

github.com/abpilot-cc开发037 次安装9 周前更新
代码仓库

关于 graph-world

graph-world 是用于在 GraphOS 中以节点优先方式设计游戏或应用逻辑的 skill。它规定数据、系统和事件的建模方式,并要求先验证图,再进行后续实现。

主要功能

  1. 01用 World 和嵌套 Context 建模领域
  2. 02用 Variant 节点定义类型化运行时数据
  3. 03在 System 中组织生命周期逻辑
  4. 04区分表示层与逻辑层事件命名
  5. 05检查模拟器状态和运行日志

适用场景

  1. 01设计新的游戏或应用世界模型
  2. 02用嵌套 Context 组织领域数据
  3. 03在编写生命周期逻辑前建模类型化状态
  4. 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)。
  • 你需要由事件驱动的初始化或运行时流程(例如游戏启动)。

前提条件

  1. 首先加载并使用 graph-management 技能。
  2. 修改前读取可用节点类型和当前图状态。
  3. 尽可能在每个设计步骤中使用一个完整的事务。
  4. 强制执行根节点命名约束:World 节点的 name 固定为 'World'。

模拟器日志检查

当世界插件模拟器可用,且需要检查实际运行时的事件流,而不是仅依赖静态图结构时,请使用此方法。

  1. 启动模拟器或驱动其运行,直到目标分支或场景执行完毕。
  2. 通过 GraphOS 运行时查询 /api/world/log。
  3. 先读取默认响应,检查截至模拟器当前时间的所有日志。
  4. 调查单个分支时,使用 startTime 和 endTime 缩小查询范围,以隔离模拟时间段。
  5. 如果 /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 }

修改规则(强制顺序)

这些规则是任何变更工作流都必须遵守的硬性约束:

  1. 数据模型和数据逻辑变更必须先应用到 Graph。
    • 在编写下游代码、文档或任务之前,先在 Graph 中完成所需的 Context/Variant/System/Event/EventSystem 更新。
  2. Graph 变更后立即验证逻辑是否闭环。
    • 运行 Step 4 闭环检查,并确保所有闭环维度均通过。
  3. 只有闭环验证通过后,才能继续执行其他任务。
    • 如果闭环检查失败,先返回 Graph 修补;不得继续非 Graph 工作。
  4. 每次 Graph 变更成功后,都要更新 gen/README.md,记录变更。
    • 记录新增、修改或删除的内容及其原因。
    • 追加到变更日志部分;不要覆盖之前的记录。
  5. 每次 Graph 变更成功后,都要更新 gen/GRAPH.md,写入完整的当前流程图和闭环检查点。
    • 确保流程图与实际的 Step 0-6 工作流同步。
    • 验证流程图仍然闭环(检查失败时会返回到修补步骤)。

流程

Step 0:读取当前状态
  1. 调用 get_available_node_types 以验证节点模式。
  2. 调用 get_graph_description 以识别当前根节点、上下文和缺口。
  3. 如果要扩展现有区域,调用 get_graph_node 检查焦点节点。

完成检查:

  • 确认是否已存在 World 节点。
  • 确认 World 根节点的 name 正好是 'World'。
  • 确认新 Context/Variant/System/Event 节点应挂接的位置。
Step 1:构建数据模型和变体

目标:先创建结构模型,再为其数据指定类型。

  1. 确保恰好存在一个 World 根节点。
    • 根节点名称必须正好是 World;不要重命名,也不要创建其他根节点名称。
  2. 按领域边界创建 Context 树:
    • 从宽泛到具体,例如:Gameplay -> Player -> Inventory。
    • 保持同级 Context 内聚且低耦合。
  3. 在每个相关的 World/Context 下添加 Variant 节点:
    • 设置具有稳定语义的 name。
    • 将 type 设置为 string|float|integer|boolean|JSONSchema 中的一种。
    • 如果 type=JSONSchema,则提供包含必需字段的 jsonSchema。
    • 仅对运行时真正必需的数据标记 required。
  4. 应用事务并重新读取 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 步:根据数据模型定义系统

目标:将生命周期行为绑定到现有数据模型范围。

  1. 为每个行为单元在其所属 World/Context 下创建一个 System。
  2. 根据实现契约定义所需的生命周期入口:
    • spawn、despawn、update、change。
  3. 为每个已实现的生命周期方法编写文档,清楚说明其意图、触发条件和目标数据范围。
  4. 确保系统职责与邻近的 Context/Variant 所有权保持一致。
  5. 应用并验证拓扑。

决策要点:

  • 将 System 放置在拥有其所修改数据的最近范围内。
  • 初始化使用 Spawn,循环逻辑使用 Update,响应式同步使用 Change,清理使用 Despawn。
  • 如果单个节点涵盖了互不相关的职责,则拆分 System。
  • System 实现中不得包含表现层逻辑(渲染、样式、动画、UI 编排)。
  • System 逻辑只能由 Context/Variant 状态和领域规则驱动。
  • 临时缓存数据应保留在所属 System 内部;除非缓存状态必须作为领域模型的一部分存储,否则不要将其提升为图中的 Variant。

完成检查:

  • 每个已实现的生命周期方法都有对应的说明。
  • Systems 已附加到正确的 World/Context 范围。
  • 每个生命周期方法都有明确的触发条件和数据目标。

实现交接:

  • 第 4 步通过后,使用 graph-world-ts 实现具体的 TypeScript System 代码、启动引导连接、生成类型集成,以及 src/app.ts 注册。
第 3 步:定义事件和 EventSystems

目标:在数据和生命周期基础稳定后,对事件驱动流程建模。

  1. 在 World 下为关键领域事件创建 Event 节点:
    • 示例:GameStarted、UserRegistered、SessionRestored。
  2. 如果需要事件载荷,则在每个 Event 下附加 Variant 节点。
  3. 在每个 Event 下创建 EventSystem 处理程序:
    • 说明处理程序如何创建/初始化/更新 Context 实例。
  4. 应用事务并验证事件与处理程序的完整性。

决策要点:

  • 在跨 Context 或具有明确触发边界的场景中创建 Event。
  • 如果处理逻辑应与逐帧 System 逻辑解耦,则使用 EventSystem。
  • 对于引导流程,优先使用明确的启动/引导事件及其处理程序。
  • 对于面向 UI 的事件,尽量精简 Event 数据模型;除非确实需要,否则优先不定义载荷字段。
  • 表现层事件以 On 为前缀命名,并尽可能保持其信号式特征。
  • 内部逻辑层事件以 Logic 为前缀命名,用于领域编排,而非面向 View 的通知。

完成检查:

  • 每个关键触发条件都有一个 Event。
  • 每个 Event 至少有一个预期的 EventSystem 处理程序(或明确记录为未来工作)。
  • Event 载荷 Variants 符合处理程序的输入预期。

实现交接:

  • Graph 触发链验证通过后,使用 graph-world-ts 实现具体的 TypeScript EventSystem 处理程序,重新生成 ./gen/World 类型,并在 src/app.ts 中连接注册。
步骤 4:闭环验证与完成

目标:验证模型是否端到端闭环;如果没有,则补齐缺失环节并重新验证。

  1. 完成步骤 1–3 后运行完整验证:
    • 重新运行 get_graph_description,并将预期拓扑与实际图进行比较。
    • 可选择使用 get_graph_node 检查关键节点(World、核心 Context、引导 Event)。
  2. 验证闭环维度:
    • 结构闭环:只有一个 World 根节点,且不存在孤立的 Context/Variant/System/Event/EventSystem。
    • 数据闭环:每项关键运行时数据都以类型化 Variant 的形式存在,并具有所属作用域。
    • 行为闭环:每个已实现的生命周期方法都有具体描述和目标数据。
    • 触发闭环:引导触发器和关键领域触发器均映射到 Event -> EventSystem -> 目标 Context 更新。
    • 事务闭环:所有应用结果均成功,或已通过重试解决部分失败。
  3. 如果任一闭环检查失败,则进行分类,并在一个专注的事务批次中修补缺口:
    • 缺少结构/数据 -> 返回步骤 1。
    • 缺少生命周期方法覆盖 -> 返回步骤 2。
    • 缺少事件触发器/处理器链 -> 返回步骤 3。
  4. 重新运行闭环验证,直到所有维度均通过。
  5. 生成最终验证摘要:
    • 添加的节点/边。
    • 仍待处理的事项(如有),并明确说明原因。
    • 确认模型已形成闭环,可进入下一轮迭代。

完成检查:

  • 五个闭环维度均通过。
  • 不存在尚未解决的关键缺口。
  • 最终图描述与预期领域设计一致。
步骤 5:更新 gen/README.md 变更日志

目标:以易读的形式记录每次图变更会话。

  1. 打开(或创建)gen/README.md。
  2. 按照以下格式,在 ## 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>
  1. 不要覆盖以前的记录——始终追加。
  2. 每条记录保持简洁(每个节点变更一行即可)。

完成检查:

  • gen/README.md 存在,并包含本次会话的最新变更记录。
  • 列出了所有新增/修改/移除的节点。
  • 注明了待处理事项或已知缺口。
步骤 6:更新 gen/GRAPH.md 完整流程图

目标:维护一份可执行的流程图,准确反映当前工作流和闭环过程。

  1. 打开(或创建)gen/GRAPH.md。
  2. 维护一份涵盖端到端流程的完整 Mermaid 流程图:
    • 包含步骤 0 至步骤 6。
    • 包含闭环维度和检查失败时的重试循环。
  3. 每次图变更会话后,如果任何步骤、关卡或重试路径发生变化,就更新流程图。
  4. 验证流程图是否正确闭环:
    • 任何闭环检查/关卡失败都必须返回正确的修补步骤。
    • 成功路径必须以最终验证摘要结束。

完成检查:

  • gen/GRAPH.md 存在,并包含最新的完整流程图。
  • 流程图包含所有有效步骤(0–6)和重试分支。
  • 已验证图中的闭环:成功/失败路径均无断点,且不存在缺失的回边。

质量关卡(最终审查)

  1. 结构关卡:恰好有一个 World 根节点,其 name 必须严格等于 'World',且 Context 树结构合理。
  2. 类型关卡:Variant 的类型正确;JSONSchema 节点包含有效的 schema 文本。
  3. 所有权关卡:System 和 Variant 均附加到拥有其数据的作用域。
  4. 事件关卡:Event/EventSystem 配对覆盖引导触发器和关键领域触发器。
  5. 验证关卡:每次应用后重新运行 get_graph_description,并确认节点/边的增量符合预期。
  6. 图示关卡:已更新 gen/GRAPH.md,且其内容反映当前的闭环工作流。
  7. 配置边界关卡:图中不包含仅用于配置的结构;配置设计在生成代码/运行时代码中实现。

建议的提示词输入

  • “设计一个 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)
此示例中的关键设计模式
  1. 用于结构化数据的 JSONSchema:当某个字段包含相关子字段(例如,attack = {damage, speed, radius})时,使用 JSONSchema Variant 类型。标量值则使用基本类型(float、integer、string)。
  2. 配置驱动的系统:GameSystem 初始化单例 Game 上下文,并从 Variant 字段读取所有可配置参数(成本、冷却时间、缩放参数),绝不硬编码值。
  3. 单例上下文访问:系统和 EventSystem 始终通过固定 id(`getGameById('id'))获取 Game 上下文,而非按子节点位置查找。
  4. 事件载荷精简:Merge 等事件仅携带所需的最少载荷(ally_id、dst)。处理器从 Context 中推导其余状态。
  5. System 缓存中的临时状态:帧内临时工作集(子弹与敌人的碰撞候选项、每帧的移动目标)保存在 System 闭包作用域中,而非作为图 Variant。
  6. 波次难度缩放:WaveSystem 读取 wave.value 以调整敌人数量和属性——所有缩放参数都通过可配置的 Variant 设置,而非嵌入常量。
  7. 重置流程: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]

评论

支持 Markdown