关于 orca-graph
orca-graph 是将 PLAN.md 任务转为依赖图并协调 Agent 执行的技能,面向需要并行调度和持久状态的多任务工作。它以事件日志为状态来源,提供依赖审计、验证和图形视图。
主要功能
- 01从 PLAN.md 构建依赖图
- 02按拓扑层调度并锁定任务
- 03追加式事件日志持久化状态
- 04验证、审计模型回答及来源
- 05生成图形与二维图谱视图
适用场景
- 01协调含多个依赖任务的计划
- 02防止多个 Agent 抢占同一任务
- 03跨会话恢复未完成的执行状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheinmir/ setup --skill orca-graph安装后在 Claude Code 中输入/orca-graph确认已加载。
详细介绍
技能:orca-graph
orca-workflow 的分支:同样采用 propose → gate → plan → dispatch,但 deps 是数据(graph.json),
而不是在脑中推测。运行时:harness/scripts/orca-graph.py。绘图:fdk/tools/graph-viz.py
(1 张图)+ fdk/tools/graph-atlas.py(2D 图集)。默认存储位置为 llmwiki/graph/。
引擎位于独立仓库 https://github.com/Rheinmir/orca-graph(测试 + VT 评估集 + 独立历史记录),安装到
~/.orca-graph/repo/。上面提到的 overstack 中的三个路径是指向该引擎的 shim——命令照旧输入。Shim 提示
“尚未安装引擎”(rc 3)→ 运行它打印出的确切命令:curl -fsSL https://raw.githubusercontent.com/Rheinmir/orca-graph/main/install.sh | bash。
没有 overstack 时:直接调用 ~/.orca-graph/bin/orca-graph。
内容
目的和背景
- 目的: 将 PLAN.md 中的任务拆分为依赖图(deps 是 graph.json 中的数据),通过确定性工具回答 5 个问题,按带锁 + 租约 + generation 的拓扑层进行 dispatch,采用持久的 append-only 状态,并根据有来源的 rubric 评判模型的所有回答。
- 触发条件(何时使用):
- 有包含 ≥ 3 个任务的 PLAN.md,需要了解哪些可以并行运行、哪些需要等待其他任务,以及进度如何。
- 要 dispatch 多个 agent,需要加锁以防 2 个 agent 抢同一任务/写入同一文件。
- 工作跨越多个会话仍未完成:状态必须在崩溃后保留,不能“靠脑子记住”。
- 非目标: 不用于故障处理(→
orca-issue),也不用于尚无 PLAN 的情况(→/propose然后/plan)。 明确不在 PRD v1.1 范围内(直言不讳):带 outbox/backpressure 的持久化 item pipeline、按 token 分层的 fan-in、anchor registry、根据 eval floor 路由模型、规模化 proposal、用于 discovery 的 seen ledger——参见引擎仓库的evals/vt-matrix.json:28 个 VT 场景中有 13 个标记为out_of_scope并附有原因。 明确不在 PRD 范围内(直言不讳,不假装已有):PostgreSQL ledger、secret gateway、资金预算、LangGraph、integration queue/candidate hash、外部 effect 的 compensation、进程级 sandbox(在独立容器/VM 中运行 agent 命令)。此工具是面向单台机器的文件式工具;如果需要上述功能,那就是另一个引擎,而不是对 orca-graph 的升级。(文件写入 allow-list——不同于进程级 sandbox——已具备,参见下方 Reference — Daemon & control-room 中的run --strict和 GH#162。)
心智模型
PLAN.md → build → graph.json(缓存)+ events.jsonl(事实来源,append-only)→ ask(5 个问题)→ 按拓扑层执行 next/lock/set/run → verify(+ qc)→ audit → graph-viz / graph-atlas / control-room。
每个节点的状态机:
proposed → ready(所有 deps 均已完成)→ locked → dispatched → done | done_unverified | failed | unknown;blocked = 等待人员介入(HITL)。
三个维度彼此独立:state(生命周期)· verified(verify 是否 rc 0?)· fresh(上游在我完成后重新执行 → stale,仅作警告)。
借鉴 Reprise PRD 的规则:op_key 幂等 · CAS --if-rev · generation 阻止旧结果 · 租约过期 → unknown 而非 failed · 未 verify 则不能标记为 done。
qc(GH#163,可选——PLAN.md 中的**QC:**字段,与verify一样计入spec_hash):独立 review 命令,在verify返回 rc=0 后运行,不能由刚刚自行 verify 的同一次调用执行(emit()中by != "reconcile")——将 reviewer 的角色与刚刚自行 verify 的人/agent 分开。失败时:直接通过run/set done→emit()将done降级为done_unverified(与 verify 失败相同);通过reconcile→ 判定为ready(reconcile 会自行明确作出判定,不会让状态停留在 done_unverified)。未声明**QC:**→ 行为与此前完全相同(向后兼容)。
输入和输出约定
| 字段 | 必需? | 含义 | |
|---|---|---|---|
| 输入 | PLAN.md | 是 | ≥ 3 个任务;包含 **Depends:**、**Verify:** 行,以及可选的 **Kind:**、**QC:**、**Resources:**;尚无 → 调用 skill plan |
| 输入 | 边的原因 | 建议提供 | **Depends:** Task 1 (data), Task 2 (preference) — 原因 ∈ data · contract · acceptance · effect_order · control(硬边)· preference(仅由书写顺序决定) |
| 输入 | 资源声明 | 共享时 | **Resources:** db-migration(exclusive), api-x(shared), llm(capacity:2) — 未指定模式 = exclusive |
| 输入 | store | 否 | 默认 llmwiki/graph/ |
| 输入 | --parent <gid>/<node> | 否 | 将子 graph 挂接到父 graph 的 node |
| 输入 | agent + agent 命令 | dispatch 时 | 用于 lock --by 的 agent 名称;用于 run … -- 的命令 |
| 输出 | <id>.graph.json + <id>.events.jsonl + .locks/ | 是 | graph + 持久化状态 |
| 输出 | build 输出 | 是 | cycle、推断出的 deps(gợi-ý)、两个并行 node 写入同一文件时的冲突 |
| 输出 | 带标签 + 来源的 answer | model 回答时 | 按 1 / 0 / 0.3 / 0.5 / 编造 0 的评分标准打分 |
| 输出 | HTML graph + 2D atlas + control-room.html | 是 | 2 个 Python 绘图文件 + control-room 生成器 |
| 输出 | audit-log.jsonl | 结束时 | 重新打开每个来源的结果,编造 = 0 |
规则和能力
- RULE-01 (MUST):Lock 控制 DISPATCH;文件写入副作用的 allow-list 是软性限制(GH#162)——参见上文的
run --strict。Allow-list 不能替代真正的进程隔离 → 需要完全隔离时,仍应为每个任务使用独立 worktree(隔离命令、环境变量、文件系统之外的副作用)。 - RULE-02 (MUST):对于 headless CLI,不要 dispatch
blockednode(HITL)——它会代替人做猜测,然后保持沉默(教训 250626,约 1/5 的任务)。 - RULE-03 (MUST):model 对 graph 的所有回答都必须通过
answer,并附上可打开的标签 + 来源。没有来源 → 选择không-biết(0.3),而不是编造(0)。 - RULE-04 (MUST):推断出的 deps
gợi-ý必须由 user 确认,或在 dispatch 该层之前通过**Depends:**声明。 - RULE-05 (MUST):不要手动删除/修改
events.jsonl;有误时追加修正 event。graph.json只是缓存——损坏时重新运行build,状态由 events 折叠生成。 - RULE-06 (MUST):生成的 HTML 必须包含:明暗模式切换 + 完整路径 + 附带释义的术语(fdk 规则)——2 个绘图文件已处理这些事项,不要手写 HTML。
- RULE-08 (MUST):资源争用不是 DAG 边(PRD v1.1 §23.2)。两个独立任务使用同一个集成分支 / DB schema / 测试端口 / API quota → 声明
**Resources:**,由lock在运行时串行化;不要添加虚假的**Depends:**。独立 worktree 也不能免除资源声明。 - RULE-09 (MUST):
audit-edges只读,只提出建议。缺少原因的边(EDGE_UNJUSTIFIED)必须保留并询问 user;“没有发现 dependency”不等于“已证明独立”。移除边 = user 同意 → 修改 PLAN → 重新运行 build。 - RULE-10 (MUST):user 要求向正在运行的 graph 添加工作 → 使用
add-node(它会修改原始 PLAN 并重新运行 build,plan_version + 1,保留历史记录)。禁止手动修补graph.json;禁止为同一 goal 创建新 graph。 - RULE-07 (MUST):无法做到的事项(直说):文件中未显现的隐式耦合;agent 中途死亡时自动回滚;与 Orca 账本双向同步;超过约 500 个 node 的 atlas 需要 graphviz;allow-list 只检查文件系统,不检查网络/进程/secret 访问。
- Capabilities:读取 PLAN 和项目文件;向 graph store 追加写入 + 文件锁;启动并跟踪 agent 进程(按 pid 检查 heartbeat);运行 verify/qc 命令;读取 git diff 以检查 allow-list;生成静态 HTML。单向镜像到外部协调账本为可选项。
故障边界
- 尚无 PLAN → blocked,调用
plan(或先调用/propose,再调用/plan);若属于故障 → 转交orca-issue。 - 出现循环(
check-cycles返回码为 2)或超过深度 ≤ 6 / ≤ 20 个节点 → 工具拒绝执行,blocked,直到缩小范围。 - 依赖项
gợi-ý尚未确认 → 先向用户澄清,再分派该层。 - 节点为
blocked(HITL)→ 等待人工处理,禁止无头分派。 - Agent 超过租约时间仍无响应 → 状态为
unknown(不是failed)→ 执行reconcile;超过 3 次尝试 → failed。 - 生成结果过时或
plan_version不同 → STALE,不予发布。 - 回答没有来源 → 标记为
không-biết,不得编造。
工作原理
主工作流
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/后续 |
|---|---|---|---|---|---|
| W01 | 确定性 | repo 有 harness | 步骤 0:预先工作扫描 pull-gate-sweep.sh | 扫描完成 | 无 harness → 跳过 |
| W02 | 判断 | PLAN | 步骤 1:是否已有 PLAN;没有 → 调用技能 plan;填写真实的 Depends + Verify | PLAN.md | 缺少 Depends → 工具推断并标记为建议 |
| W03 | 确定性 | PLAN.md | 步骤 2:python3 harness/scripts/orca-graph.py build <PLAN.md> | graph.json + cycle、文件冲突警告 | 冲突 → 添加 Depends 或说明理由后接受 |
| W03b | 确定性 | graph.json | 步骤 2b:audit-edges <id> — 缺少理由的边、可省略的 preference 边、关键路径前后对比 | finding 表(只读) | EDGE_UNJUSTIFIED → 询问用户理由,并填写到 Depends |
| W04 | 判断 | graph | 步骤 3:先通过 ask 提出 5 个问题,再通过 answer 补充模型回答,并附上标签和来源 | 带标签的回答 | 无来源 → 不知道 |
| W05 | 效果 | graph.json | 步骤 4:绘制 graph-viz.py → 将 HTML 发给用户审核(gate-create) | HTML + gate | 未知 kind → B06 |
| W06 | 效果 | 已审核的 graph | 步骤 5:循环执行 next → lock → set dispatched → dispatch → set done,直到 next 报告完成 | node 完成 | lease 过期 → B05 |
| W07 | 确定性 | 已完成的 graph | 步骤 6:audit <id> → graph-atlas.py llmwiki/graph/ → 若发现问题则更新 problem-tree | audit-log + atlas | 编造 > 0 → 报告 |
各步骤详情(W01–W07 的事实来源;步骤 0–6 对应 W01–W07):
- 如果有 harness,按 orca-workflow 执行预先工作扫描(
pull-gate-sweep.sh)。 - 是否已有 PLAN? 没有 → 调用技能
plan。/plan模板中有**Depends:** Task 1, Task 3和**Verify:** <返回码为 0 的命令>— 填写真实内容;缺少 Depends 时,工具根据 Consumes/Produces 推断并标记为gợi-ý。 - 构建 graph:
python3 harness/scripts/orca-graph.py build <PLAN.md>→ 输出 cycle、推断出的 deps,以及两个并行 node 对同一文件的写入冲突(⚠ → 添加 Depends 强制按顺序执行,或说明理由后接受)。 - 回答 5 个问题 — 先用工具,再用模型:
ask <id> needs·ask <id> parallel·ask <id> deps <n>·ask <id> why <n>·ask <id> related。- 模型补充的部分(含义、与旧 graph 的语义关联、风险)→ 使用
answer记录,并附上标签和来源:answer <id> <n> --q why --label chắc|gợi-ý|không-biết --score S --evidence file:path:line edge:a->b event:<op_key> absence:<lệnh> --text "..."。 - 评分标准(用户于 2026-09-12 确认):正确 1 · 错误 0 · 不知道 0.3 · 有真实来源的建议 0.5 · 编造来源 0。不确定时 → 说
gợi-ý/không-biết,不要标为chắc。
- 绘图 + gate:
python3 fdk/tools/graph-viz.py llmwiki/graph/<id>.graph.json→ 将 HTML 发给用户审核(像 orca-workflow 一样使用gate-create)。- 图中的 node 根据任务的 kind 绘制(PLAN.md 中的
**Kind:** build|test|fix|research|docs|design|review|security|infra|data|migrate|deploy|release|cleanup|integration|wiki,默认build)——图标 + 形状 + 背景色从 engine repo 的engine/kind-glyphs.json查询(~/.orca-graph/repo/engine/;默认字典供所有 graph 共用 — 通过向该 repo 提交 PR 来修改/添加)。node 边框仍表示 state(不变)。 - 字典中没有的
kind→ 工具自动临时生成(字母标记 + 根据 hash 生成的颜色/形状,并写入~/.orca-graph/kind-glyphs.local.json— 仅本机使用,不会弄脏 engine 的 git clone),并向 stderr 输出警告。看到此警告 → 询问用户是否想通过/raise-issue将新 glyph 提交到kind-glyphs.json;未经询问不要擅自添加到默认字典。
- 图中的 node 根据任务的 kind 绘制(PLAN.md 中的
- 运行循环(重复执行,直到
next报告完成):
Agent 沉默超过 lease →next <id> # node ready = chạy song song NGAY; blocked = HITL, KHÔNG dispatch headless lock <id> <n> --by <agent> # O_EXCL + lease (mặc định 90 phút); heartbeat <id> <n> khi chờ lâu set <id> <n> dispatched --op-key <uuid> # rồi orca orchestration dispatch --task … --inject (brief NGUYÊN VĂN từ PLAN) set <id> <n> done --gen <gen> --op-key <uuid> # gen lấy từ output lệnh dispatched; gen cũ → STALE, không publishnext自动将 node 设回unknown→ 重新 lock 前先运行reconcile <id> <n>(运行 verify)。 最多 3 次尝试。 如果想同步到 Orca 字典:sync-orca <id> --run(单向;Orca 字典为全局运行时字典,并会标记项目)。 - 结束:
audit <id>(重新打开每个来源;编造 = 0;写入audit-log.jsonl)→graph-atlas.py llmwiki/graph/重新生成 atlas → 如果发现流程问题,则更新 problem-tree。
分支
| ID | 类型 | 守卫条件 | 行为 | 跳过 / 失败 | 重新汇合 |
|---|---|---|---|---|---|
| B01 | user_optional | 需要在某个节点下拆分子图 | build <PLAN> --parent <gid>/<node>;当所有子节点都完成时,父节点汇合 | 超过深度 6 或 20 个节点 → 工具拒绝 | W03 |
| B02 | conditional_required | 对已有图再次运行 build | plan_version + 1,将节点放入 superseded[],已完成节点的 spec_hash 发生变化 → fresh=stale | 旧 plan_version 的结果 → STALE | W06 |
| B03 | user_optional | 用户想暂停 / 继续 / 取消 | control <id> pause、resume、cancel、status | cancelled 后无法 resume → 新建 build plan | W06 |
| B04 | capability_optional | 想用一条命令代替手动输入 4 条命令 | run <id> <node> -- <lệnh agent> + daemon watch + 控制室 | 节点缺少 verify → 拒绝无头运行 | W06 |
| B05 | recovery | Agent 在 lease 过期后仍无响应 | next 将节点设回 unknown → reconcile <id> <n> 运行 verify 后再重新锁定 | 最多尝试 3 次,然后 failed | W06 |
| B06 | conditional_required | kind-glyphs.json 中没有的未知 kind | 工具将临时 glyph 写入 kind-glyphs.local.json + 在 stderr 发出警告 → 询问用户是否要用 /raise-issue 提交新 glyph | 不自动添加到默认登记表 | W05 |
| B07 | user_optional | 想同步到 Orca 登记表 | sync-orca <id> --run(单向) | — | W06 |
| B09 | user_optional | 图已存在时,用户要求添加工作 /“再画一个节点” | add-node <id> --title … [--depends t1:data] [--blocks t5] [--files …] [--verify …] [--kind …] [--resources …] → 输出 + tN,重新 build、重新绘制 HTML,并将链接提供给用户 | 生成环路 / 超过 20 个节点 / 依赖项未知 → 工具拒绝,PLAN 保持不变 | W05 |
| B10 | recovery | lock 报告 等待 RESOURCE | 其他节点正在持有冲突 claim → 先处理其他 ready 节点,用 ask <id> waiting 查看由谁持有;对方节点完成后再锁定 | 不自动 unlock 其他 Agent 的节点 | W06 |
| B08 | conditional_required | 节点声明了 **QC:** | verify 返回 rc 0 后独立运行 QC;失败 → done_unverified(run/set)或 ready(reconcile) | 未声明 → 维持原有行为 | W06 |
验证与停止
确定性:只有 verify 返回 rc 0(以及已声明的 QC 通过)时,状态才为 done;lease/generation/op_key/CAS 由工具决定;出错时 check-cycles 和 lint/build --strict 返回 rc 2;audit 重新打开每个来源,捏造内容 = 0。需要人工处理:在 gate 审核 HTML 图、确认 gợi-ý 依赖项、处理 blocked 节点。next 报告完成时,运行循环停止;每个节点最多尝试 3 次。
示例
- 正向: PLAN 有 5 个任务,t2 和 t3 都 Depends t1 →
build报告无环路、无文件冲突 →ask t2 parallel返回 t3 →next分配 t1,完成后并行分配 t2 + t3,每个节点各有一个lock --by,再执行set done --gen→audit捏造内容 = 0 → atlas 重新生成。 - 边界 / 失败: t2 和 t3 并行写入同一个
src/api.ts→build输出 ⚠ 同一文件写入冲突 → 在 t3 中添加**Depends:** Task 2以强制串行,然后重新 build;Agent t3 在 lease 过期后仍无响应 →unknown→reconcile在重新锁定前运行 verify。 - 边界: 模型想说“t4 存在是为了开放 release”,但没有可打开的来源 →
answer … --label không-biết(0.3),不要标记为chắc。
参考 — 父图 → 子图的层级结构(PRD Reprise Graph Engine §4)
build <PLAN> --parent <gid>/<node>→ 子图挂接到父图的一个节点(包含树,与依赖 DAG 不同)。父节点包含child_graph,自动汇合:只有所有子节点都完成时才变为done_unverified(不变量 4);子图中有blocked节点 → 父节点blocked。- 硬性限制:深度 ≤ 6,且每个图 ≤ 20 个节点。超过限制 → 工具拒绝,应缩小范围而不是继续深入。
- 跨图依赖:
**Depends:** other-graph/t3— 该节点在另一个图中完成后即满足依赖。check-cycles [dir]会合并所有图,输出具体环路路径(a/t2 → b/t3 → a/t2),返回 rc 2(PRD §5.3)。 lint <id>— 检查叶节点是否满足完整约定(PRD §4.4):title · files · produces · verify · 明确的 deps。若缺少 verify/files,build --strict返回 rc 2。
参考 — 有依据的拓扑与有主资源(PRD v1.1 §23)
- **Depends 严格解析:**无法解析的 token(在
—后插入的注释、Task 1 và Task 2、不存在的 task、格式错误的跨 graph 依赖<gid>/<tid>)都是build错误,不会被吞掉——边静默消失会导致 node 提前 ready,却无人察觉。用,或;分隔;注释放在其他行。 - 边的理由:
**Depends:** Task 1 (data), other-graph/t3 (control)。五个硬性类别(data · contract · acceptance · effect_order · control)不可省略,即使不传递 artifact 也一样——不携带 payload 的审批关卡仍是真实边。preference= 仅由书写顺序决定。理由不在spec_hash中:给正在运行的 graph 添加理由,不会让已完成的 node 变为 stale。 audit-edges <id> [--json] [--strict]— dry-run。finding 代码:EDGE_UNJUSTIFIED(声明 Depends 但缺少理由 → 保留)·EDGE_INFERRED(推断出的 deps)·PREFERENCE_REMOVABLE(建议移除)·PREFERENCE_HAS_HIDDEN_CONSTRAINT(虽然标注为 preference,但 downstream 的 Consumes/Verify/QC 提到了 upstream 的 Task、文件或输出,或两个 node 写入同一文件 → 保留;按字符串比较,因此无法捕捉未体现在文字中的耦合)。输出 critical path,按 node 计数(单位权重,并非时长)、类别数量和可立即运行的前后 node 集合。仍有EDGE_UNJUSTIFIED时,--strict返回码为 2。- **资源声明:**key 由 tool 规范化(小写 + normpath),因此拼写不同的别名仍会被视为同一资源。
lock要么获取所有 claim,要么一个都不获取(不会持有 A 等待 B);检查同一 store 中的所有 graph,并在一个 admission mutex 下运行。exclusive会阻止同一 key 的所有 claim;capacity:N= key 的 pool 大小——每个持有该 key 的 node(包括shared)占用 1 个 slot;若 node 声明的 N 不同,则取最小值(不依赖 lock 顺序,shared也不能绕过配额);纯shared只会被exclusive或已满的 pool 阻止。其他 graph 中到期的 lease 也会在lock/next时由 reaper 扫描(claim 不会跨 graph 卡住);手动对正在运行的 node 执行unlock会将其设回unknown——再次 lock 前先 reconcile。build会为并行执行的一对 node 输出ℹ … 同一 claim——这只是信息,不是错误。 ask <id> waiting— 每个尚未运行的 node 附带一个原因:data(等待 upstream)·gate(HITL、control/acceptance 关卡、verify 尚未通过、unknown 等待 reconcile)·resource(claim 被占用,并指出占用者)·queue(max_parallel 已满)·control(pause/cancel)·retry(3 次 attempt 已用完)·none。对于 ready 但尚未成功 lock 的 node,next会额外输出一行——ready ≠ admitted。- topo 类别(
ask parallel)是用于解释的投影,不是屏障:deps 满足的 node 会立即 ready,即使与其 upstream 同属一类的其他 node 尚未完成。
参考 — 标识符、干运行轮次、调用预算(PRD v1.1 §24–27)
reconcile-items --expected A,B,C --verdicts rows.jsonl [--universe N]— 按item_id而非位置匹配 verdict(supported|refuted|inconclusive)。即使{A,A,B}有 3 行,仍然缺少 C → 返回码为 2。verdict: null的行或status≠ ok 的行 = 有 ID 但缺少 outcome(errored_ids),不会被过滤掉,也不计为 refuted;同一 item 同时有 verdict 和错误行 →CONFLICTING_OUTCOME;空 manifest 需要--allow-empty;缺少 verdict 文件是错误,并非“0 行”。coverage使用两个不同的分母:已完成/已选择,以及已选择/全集(未知时为unknown——不会报告 100%)。用于 fan-out 一批 item(例如/tc-run)后汇总结果。dry-streak --prev N --complete 0|1 --new N— 只有在轮次完成且没有新候选项时,才计为一轮干发现。出错的轮次会将计数重置为 0。干发现 = 启发式停止条件,并不能证明已经检查完毕。cost-envelope <id> [--reviewers N] [--max-attempts N]— dispatch 前统计 model 调用次数:planner 1 + worker/node afk + reviewer × 带 QC 的 node + synthesis 1;max_calls将次数乘以 retry 上限;没有测量数据时,expected标记为 unknown。shell verify = 0 token,但仍消耗 CPU,会单独报告。不要用“N 个 agent”代替总调用次数。
参考 — 重新规划不破坏历史(PRD §10)
- 在已有图上重新执行
build=plan_version + 1;被移除的节点加入superseded[](保留最终状态);已完成节点的合约发生变化(spec_hash= title/files/deps/verify/produces)时,fresh=stale(仅警告,不回退状态)。 - 旧结果:执行
set done --plan-version N,且 N ≠ 当前版本 → STALE,不发布(不变量 2)。 run会记住派发时的plan_version:Agent 运行期间发生重新规划 → 结果为 STALE,节点恢复为ready,以便按新规范重新执行(rc ≠ 0)。add-node是单节点重新规划:在 admission mutex 下运行(两个并行命令不会相互覆盖);按 parser 的方式读取 PLAN(忽略 code fence);所有字段必须各占一行;--blocks拒绝正在locked|dispatched的节点;PLAN 必须与 graph 一致(手动修改后先执行build);新 id 不得复用已移除节点的 id;--blocks t5会将新节点插入到 t5 之前(接入 t5 的 Depends 行;若没有则添加)。重新构建 CON graph 时忘记--parent,仍会保留原有父子关联。
参考 — Control(PRD §8.3,不变量 11)
control <id> pause|resume|cancel|status。“请求” ≠ “已停止”:只有当没有节点处于locked|dispatched状态时,pause_requested才会变为paused;非active状态下,next/lock不会分配新节点。cancelled无法 resume——请构建新的 plan version。build --max-parallel N(默认值为 4):正在运行的节点数量已达到上限时,lock会拒绝(PRD §12.1)。
参考 — Daemon 与 control-room(PRD §8.4:lease 60 s · heartbeat 15 s · reaper 15 s)
run <id> <node> [--hb 15] [--lease-sec 60] [--strict] -- <lệnh agent>— 用来替代 4 条手动输入的命令:短暂 lock → dispatched → spawn 命令 → 按 pid 发送 heartbeat → 退出码为 0 时设为done(自动运行 verify),非 0 时设为failed。没有verify的节点会被 headless 拒绝(使用--allow-unverified强制执行)。自动将目录写入 registry~/.orca-graph/registry.json,并在 daemon 尚未运行时自动 spawn(使用ORCA_GRAPH_NO_DAEMON=1关闭,使用ORCA_GRAPH_HOME更改主目录)。- **写入允许列表(GH#162):**在 git repo 中运行时,
run会将实际发生变化的文件(与 spawn 前一刻相比,包括已跟踪文件的修改和新建的未跟踪文件)与节点声明的files进行 diff。超出范围时,默认仅发出警告(写入done事件的note);只有使用--strict才会恢复为强制模式(删除新建的未跟踪文件,并通过git checkout将已跟踪文件恢复到 HEAD)。不在 git repo 中时(例如 store 位于 repo 之外),会自动跳过,不报错。orca-graph 自身的 bookkeeping(.graph.json/.events.jsonl/.locks/)始终从 diff 中排除,不计作“agent 写入”。 watch [--once] [--interval 5] [--idle-sec 600]— 整台机器共用一个 daemon,通过 pid 锁定daemon.lock。每轮只读取 registry 中仍有运行节点的目录(开销取决于运行中的节点数量,而非打开的项目数量;包括 Python 启动在内,每轮实测为 84 ms):过期 lease 的节点由 reaper 处理 →unknown→ 有 verify 时立即 reconcile;打印存活/死亡状态表;registry 空闲超过 idle-sec 后自动退出;graph 发生变化时重新生成 control-room。fdk/tools/build-control-room.py→llmwiki/html/control-room.html— 首次打开的页面,data-first(只读 registry、graph.json、problem-tree、tokens.jsonl、audit-log):全机器正在运行的任务 + 上限;每个 graph 的进度 + 卡住的节点;未解决的问题;今日成本 + 自评与审计之间的差距。每 5 s 自动刷新;daemon 每轮以及每次run开始/结束时都会重新生成,因此无需服务器,页面即可 LIVE。第 2 阶段(服务器 + 点击 pause/cancel)和第 3 阶段(嵌入 Orca)尚未实现,只有在日常使用第 1 阶段后发现不足时才会着手。- 存活/死亡 ≠ 正确/错误:daemon 只知道进程是否仍在运行;是否
done或需要重做仍由verify决定。进程存活但卡住时,heartbeat 仍会显示绿色——请为每个节点设置幂等的**Verify:**和执行时间上限。
参考 — 回顾
/orca-graph = PLAN → 带有 deps 的 graph.json → ask 回答 5 个确定性问题 → 按层分发,并使用锁/租约/代次 → 持久化追加式状态 → answer/audit 按 1/0/0.3/0.5/编造=0 的评分标准评估模型 → 一个 graph 的 HTML + 2D 图集。
意想不到的用例:对已完成的旧 PLAN 运行 build,以检查当时是否有两个 task 同时写入同一文件;或者使用 related,在动手之前查看新 PLAN 会触及旧 PLAN 的哪些文件。