Graph 技能
从声明式 JSON 描述符运行确定性编排图。
运行时使用 src/graph/* 中的 sealed-descriptor 和 pure-scheduler 合约,
通过独立的OS进程(omc graph run)执行,
因此崩溃恢复(中间杀死、重新运行、从日志恢复)是真实有效的。
使用方式
/oh-my-claudecode:graph <descriptor.json>
/oh-my-claudecode:graph "构建然后测试然后部署前问我" (先编写描述符)
执行接口始终是 CLI 子命令:
omc graph run <descriptor.json> [--runs-root <dir>]
非交互式图通过 Bash 工具运行。进度行以 [run]、[node]、[ok]、[fail]、[join]、[done] 形式流式输出。
何时使用
- 具有显式依赖关系的可重复多步骤管道(DAG)
- 必须能够容忍中断的工作:杀死/重启可从日志恢复
- 可审计的运行:
.omc/graph-runs/<run_id>/下的 OCC 日志 + 投影快照
何时不使用:探索性的一次性工作(使用对话或 /team); 任何需要中途自适应重规划的工作(图是确定性的)。
工作流程
-
提供描述符 -> 转到步骤3。
-
描述管道 -> 编写描述符 JSON(架构如下), 将其写在项目旁边(建议
.omc/graphs/<name>.json)并在运行前展示给用户。run_id在每个逻辑管道中必须唯一; 使用相同的run_id重新运行是恢复,而不是重新开始。 -
审批节点:如果描述符包含任何
"kind": "human-approval"节点, 不要通过 Bash 工具运行(标准输入在那里不是交互式的; EOF 失败时视为拒绝)。告诉用户改为交互式运行:! omc graph run <file>!前缀使其在该会话中运行,具有实时标准输入,因此 y/n 有效。 -
运行并传递进度。退出码(规范性): 0 成功 | 1 终端失败 | 19 另一个写入者拥有此运行(繁忙) 20 损坏/篡改的日志(失败关闭)| 21 恢复时描述符漂移 | 70 运行时崩溃(未映射的错误)
-
恢复:崩溃后重新运行相同命令会重放已提交的 转换并继续。已完成的节点永远不会重新执行。
描述符架构(最小化)
{ "descriptor_version": 1, "run_id": "unique-pipeline-id", "revision_id": "rev-1", "goal": "一行描述", "nodes": [ { "id": "n1", "kind": "command", "title": "...", "timeout_ms": 60000, "max_attempts": 2, "effect_policy": { "policy": "side_effect_free" }, "command": "npm test" }, { "id": "a1", "kind": "agent", "title": "...", "timeout_ms": 300000, "max_attempts": 1, "effect_policy": { "policy": "side_effect_free" }, "instructions": "..." }, { "id": "gate", "kind": "human-approval", "title": "...", "prompt": "继续?" } ], "edges": [ { "id": "e1", "kind": "fixed", "from": "n1", "to": "a1" } ], "entry_node_ids": ["n1"], "concurrency_limit": 2, "terminal_verification_node_id": "a1" }
边的种类:fixed | conditional | fan_out/join 对
| back_edge(通过 max_traversals 实现有限重试)。请参阅 src/graph/schema.ts 获取权威的 Zod 架构——
并阅读上面的“能力边界”部分,了解内置执行器实际执行的内容。
能力边界与语义(编写前请阅读)
- 边支持:内置的命令/代理执行器覆盖
fixed边和fan_out/join对。conditional和back_edge路由完全由运行时和调度器合约支持, 但需要自定义的 NodeExecutor 在其结果中发出route——内置执行器从不产生路由, 因此依赖它们的图会快速失败并返回route_required而不是猜测。 - 崩溃恢复保证对于命令节点是至少一次:在外部副作用
与其日志追加之间发生的崩溃会在恢复时重新执行该节点。对于
idempotent命令, 在命令启动之前,解析的键可作为GRAPH_IDEMPOTENCY_KEY使用, 并记录下来用于下游去重。内置执行器拒绝reconcile; 协调需要一个具有实际外部协调权威的自定义执行器。 外部副作用的精确一次语义超出 v1 范围。 - 命令信任边界:命令节点是任意的 shell 行,
在当前工作目录中具有进程权限。仅运行您编写或信任的描述符。
命令子进程接收一个允许列表环境(PATH、HOME/USERPROFILE、TEMP/TMP、区域设置/时区、USER 身份、
GRAPH_*和可选幂等键),而不是主机的全部机密。 命令不受文件系统/进程沙箱保护。 - 代理权限边界:内置代理节点明确是只读的。
它们在当前工作目录中运行,没有额外目录,
仅支持
Read、Glob和Grep,permissionMode: dontAsk, 会话持久化已禁用,并具有特定于提供者的环境允许列表。代理超时终止并中断 SDK 查询。 任何需要变更或外部效果的代理,请使用自定义执行器。将.omc/graph-runs/<run_id>/descriptor.json视为可执行内容。