Archon 工作流运行管理(Run Management)实战指南:get / approve / cancel / abandon / resume 全命令解析
【免费下载链接】ArchonThe first open-source harness builder for AI coding. Make AI coding deterministic and repeatable.项目地址: https://gitcode.com/GitHub_Trending/archon3/Archon
导读
本文基于 Archon 仓库内 .claude/skills/archon-cli/manage-run/manage-runs.md 展开,系统讲解如何查看、控制与解决 Archon 工作流运行(run)的全套命令动词(verb):list / get / status / wait / approve / reject / respond / cancel / abandon / resume,并深入剖析最容易踩坑的“闸门语义”(gate semantics)——包括 approve/resume 两步走的由来、交互循环闸门中“带不带评论”的区别、cancel 与 abandon 的本质差异,以及如何正确评判一次已结束的运行、如何中转 SDLC 包的 discovery 发现项。读完本文,你将掌握用一条命令精确操控任意运行、在 JSON 与人类可读输出间安全切换、以及在运行异常时准确诊断与恢复的完整能力。
输出契约:--json与无标志两种模式
所有 run 管理命令遵循统一的输出契约:
| 模式 | stdout | stderr | 适用场景 |
|---|---|---|---|
--json | 一条干净、完整的 JSON 对象(日志被抑制) | 诊断信息 | 程序化解析(如 jq、Agent 自动化) |
| 无标志 | 人类可读文本 | 诊断信息 | 终端手工操作 |
这一契约在源码中同样严格贯彻:例如 packages/cli/src/commands/workflow.ts 中announceWaitAttached明确注释了“--json承诺 stdout 上恰好一个文档”,因此等待提示通过writeStderr写到 stderr 而非 stdout,以免污染 JSON 输出;同时writeJsonLine带完成回调写入,保证管道消费者不会收到截断的 JSON 文档(见 packages/cli/src/commands/workflow.ts)。规则很简单:要解析,就加--json;要人看,就不加。
单次运行的模型覆盖:--model重绑定
当用户要求“这一次运行换不同的模型”时,只需在启动时重绑定 tier 关键字或@别名,持久化配置完全不受影响:
# 只为这一次运行重绑定一个或多个 tier / @alias;每个绑定重复一次 --model archon workflow run archon-ship --branch fix/x "..." \ --model large=pi/minimax/minimax-m3 \ --model small=openai/gpt-5-mini规格格式:<tier|@alias>=<provider>/<model-ref>,其中<model-ref>是命名 provider 期望的模型引用;对于 Pi 后端,它本身又是一个<vendor>/<model>引用(例如pi/minimax/minimax-m3)。如果传入了未知的 tier 或 alias,命令会直接报错并列出所有已定义的名称。
发送真实工作前务必先验证:
# dry-run 打印每个节点解析出的 provider/model,不产生任何 AI 花费 archon workflow run <workflow> "test" --dry-run --model large=... # 观察 'runs on:' 输出行源码层面,--resume与--model被定义为互斥:恢复运行会保留其原有的模型绑定(见 packages/cli/src/commands/workflow.ts),这也印证了“模型重绑定只发生在启动时刻”的设计。对于需要复用的备选模型组合,更推荐使用配置层(config layer)而不是长长的 flag 列表——见 setup-and-config 文档 的 “Alternate config layers” 一节。
命令总览(Verbs)
以下命令表覆盖全部 run 管理动词。注意:项目列表按 cwd(当前工作目录)限定范围;完整的 run ID 则是全局可寻址的——在别的目录下你依然可以用完整 run ID 直接操作某个运行。
| 目标 | 命令 |
|---|---|
| 列出最近运行(本项目) | archon workflow runs --json |
| 列出全部项目的运行 | archon workflow runs --all --json |
| 按状态过滤 / 限制行数 | archon workflow runs --status running --limit 50 --json |
| 单个运行的状态/错误 | archon workflow get <run-id> --json |
| 单个运行 + 逐节点详情 | archon workflow get <run-id> --verbose --json |
| 单个运行 + 原始事件行 | archon workflow get <run-id> --verbose --events --json |
| 活跃运行(本项目) | archon workflow status --json |
| 活跃运行(全部项目) | archon workflow status --all --json |
| 阻塞直到运行结束或需要人工决策 | archon workflow wait <run-id> --json |
| 以任意声明的决策解决闸门 | archon workflow respond <run-id> <decision> [text] |
| 批准(默认词汇) | archon workflow approve <run-id> [text] |
| 拒绝(默认词汇) | archon workflow reject <run-id> "<reason>" |
| 停止一个活跃的分离式运行 | archon workflow cancel <run-id> |
| 将暂停/孤儿运行标记为已取消(仅状态) | archon workflow abandon <run-id> |
| 从已完成节点处恢复失败/暂停的运行 | archon workflow resume <run-id> |
关于作用域还有一个重要细节:get / resume / cancel / abandon / approve / reject / respond都按 run ID 操作并限定在项目范围内,且接受短 ID(8 字符)或完整 ID——这正是workflow runs打印出的短 id 可以直接拿来用的原因(源码中由resolveRunIdArg统一解析,见 packages/cli/src/commands/workflow.ts)。
另外,wait的退出码描述的是命令本身而不是运行状态:0 表示运行产生了事件,3 表示超时但运行仍存活,1 表示 wait 自身失败;一个failed或cancelled的运行依然是退出码 0 并把状态打印在 stdout 上——把运行状态映射进进程退出码,会让一次合理取消的运行看起来像命令损坏(见 packages/cli/src/commands/workflow.ts)。
approve/resume 两步走:为什么--json下批准后不会继续执行
这是最容易踩坑的闸门语义之一:带--json的approve/reject/respond只记录决策并停止——运行变为“可恢复”(resumable)但不会执行,因为流式输出会污染 JSON 文档。要“记录并继续”,有两种方式:
方式一:不带--json,一次性完成记录 + 自动恢复(后台任务)
archon workflow approve <run-id> "ship it" # 无 --json:记录决策 + 自动恢复;这是一个后台任务!方式二:刻意分两步
archon workflow approve <run-id> "ship it" --json # 已记录,resumable: true archon workflow resume <run-id> # 真正执行;这是一个后台任务如果想让续跑进程拥有一个后台进程(避免启动它的 shell 被回收后运行被卡住),可以在approve/reject/respond/resume上追加--detach:父进程先校验运行并返回带有continues: true的 ack;分离出的子进程记录决策并不带--json地继续执行。
源码实现印证了这一机制:runDetachedControlCommand生成的子进程 argv 会剥离--json(见 packages/cli/src/commands/workflow.ts 的注释),因此子进程走的是内联路径并真正驱动运行前进——批准后的自动恢复、拒绝后的 on_reject 返工、恢复后的重跑都由它完成;同时子进程用detached: truespawn(packages/cli/src/commands/workflow.ts),并等待启动窗口确认子进程确实存活后才返回 ack,避免“父进程已打印 ok 而子进程立即死亡”的假成功。
交互循环闸门:有评论与无评论本身就是两种决策
交互循环闸门(interactive-loop gate)暂停时,先读取闸门状态再决定,不要凭反射行事:
archon workflow get <run-id> --json | jq .metadata.approval.completionSignaledcompletionSignaled字段的语义(源码定义见 packages/workflows/src/schemas/workflow-run.ts):
- 值为
true且你不带评论地 approve →接受并完成:节点直接基于已计算好的输出收尾,不会重跑。此时若同时传了消息,消息会被丢弃而非记录(见 packages/core/src/orchestrator/manage-run-tool.ts 的动作说明)。 - 你带评论地 approve → 使用你的文本作为反馈再跑一整轮迭代。
- Reject 永远需要理由。对于声明了
decisions:的闸门,拒绝理由通过$gate.output.text暴露;只有旧式的approval.on_reject提示词才接收$REJECTION_REASON环境变量。
一句话总结:在读完闸门产出物之后再刻意选择,而不是条件反射式地点批准。
cancel 与 abandon:一个杀进程,一个只改状态
两者都让运行变成 cancelled,但本质完全不同:
cancel主动停止一个活跃的 CLI 分离式运行(detached owner):它会先验证进程树确实消失,然后才记录cancelled。用它来杀死真实工作。cancel只作用于非终态(running)的运行,且不可逆——进程当前正在执行的步骤可能会先完成再停(见 packages/core/src/orchestrator/manage-run-tool.ts 的说明)。abandon仅改状态:用于已经暂停的运行,或在你独立验证过某个 “running” 行是孤儿(例如宿主崩溃)之后。它永远不会杀死任何进程——只是丢弃一条暂停/失败的运行记录(packages/core/src/orchestrator/manage-run-tool.ts)。
注意cancel和abandon都不可逆,因此这类破坏性动作(cancel / abandon / approve / reject / respond)在 core 层的manage_run工具中要求显式confirm: true(见 packages/core/src/orchestrator/manage-run-tool.ts 的DESTRUCTIVE_ACTIONS),CLI 层则会打印一次预览让你确认。此外,abandon 一条父运行被阻塞在它上面的子运行(sub-run)时,父运行会保持 paused——需要你主动 resume 它以干净地让节点失败,或者同样把它 abandon 掉(packages/core/src/orchestrator/manage-run-tool.ts)。
respond:不止 approve/reject 的闸门决策
有些闸门声明的决策超出了默认的 approve/reject 二元组。此时使用:
archon workflow respond <run-id> <decision> [text]在猜测决策之前,先读取运行的元数据,看看它的闸门声明了哪些决策:archon workflow get <run-id>会在适用时打印gate: decisions: <id1>, <id2> ...(用其中一个 ID 配合 respond)。源码在 packages/core/src/orchestrator/manage-run-tool.ts 中读取decisionsAuthored与decisions字段并列出 ID。respond的decision参数也接受'approve'/'reject',但规范建议这两个交给专用动词;respond是给闸门声明的其他决策(如'revise'、'escalate')准备的——传入闸门未声明的 ID 会失败并列出实际可用的选项,绝不会静默取消任何东西(packages/core/src/orchestrator/manage-run-tool.ts)。
评判一次已结束的运行:Terminal ≠ Good
运行结束(terminal)不等于结果良好。三种 JSON 模式暴露的数据各不相同:
| 命令 | 读什么 |
|---|---|
get <id> --json | 顶层归一化的outcome(succeeded/failed)与leave_behind.artifactFiles |
get <id> --verbose --json | 有序的nodes摘要与解析警告 |
get <id> --verbose --events --json | 原始events行 |
需要特别澄清的一点:outcome_field是从返回节点(return node)中选取一个布尔值,但运行只存储归一化后的顶层 outcome——它不会把作者定义的字段名(如green、ready或rooted)作为另一个顶层属性暴露出来(源码中outcome与status是两套独立字段,outcome是“工作流作者声明的裁决”,与引擎拥有的生命周期状态无关,见 packages/workflows/src/schemas/workflow-run.ts 的注释)。因此:
- 通过
leave_behind.artifactFiles定位报告文件; - 先读工件(artifact),再向用户汇报。
汇报时务必带上证据,例如:“completed, review verdict ready:false — 2 findings remain, report at
Discoveries:SDLC 包的“范围外”发现项
这是捆绑 SDLC 工作流(archon-ship、archon-deliver、archon-review、archon-upkeep)的约定,不是所有工作流的通用行为。这些工作流的评审镜头(review lens)会把已被证明、但超出本次运行接受范围的发现,记录为discovery 侧车文件(sidecar)而不是阻塞性 finding:
- 原始按生产者(per-producer)的文件位于
<artifacts>/discoveries/*.json,每条记录包含title、claim、evidence、relation: adjacent | scope_conflict、source_node; - 由评审(review)汇总为
discoveries.json,外加人类可读的discoveries.md; - 终态报告(terminal report)末尾带一个 discoveries 小节,专门写给你这个中转 Agent——这是刻意的设计,因为运行本身永远不会根据这些发现去提交 issue。如果你在这个跳点丢弃了 discovery,就再也不会有人看到它。
仓库内的测试同样固化这一约定:packages/workflows/src/defaults/bundled-defaults.test.ts 断言 SDLC 实现与每个评审镜头各自拥有独立的 discovery 记录(discoveries/implement.json、discoveries/review-code.json等),并断言汇总脚本引用$ARTIFACTS_DIR/discoveries.json/discoveries.md,且向阅读者明确“打开 discoveries.md 并把它呈现给你的用户”。
当这样的运行到达终态时:
- 阅读报告的 Discoveries 小节;只要提到了任何发现,就打开
discoveries.md(通过leave_behind.artifactFiles定位); - 对于失败的运行,还要检查原始
discoveries/*.json侧车文件——汇总发生得较晚,一个中途死亡的运行可能只留有原始记录而报告根本没提到; - 把每条有价值的 discovery 连同其证据呈现给用户,并询问它的去向:追加为已有 issue 的证据评论、作为新缺陷新建 issue、或明确丢弃。除非用户给了常设授权,否则未经用户同意不要提交任何 issue。
最后强调:discovery 到达你手里时已经过验证(evidence携带具体的file:line事实或命令结果),且adjacent类型的发现从未影响过运行的 readiness——不要拿它们重新评判裁决(verdict),只需负责路由。
当运行看起来不对劲:诊断与恢复流程
| 症状 | 处理 |
|---|---|
| 意外暂停 | get --verbose,查看失败节点的错误与闸门元数据 |
| 中途失败 | 若能命名原因就修复之,然后resume <run-id>(后台任务)。Resume 会跳过已完成节点 |
| “running” 行但没有任何活进程 | 先确认进程真的消失,然后abandon |
补充两个源码级细节,帮助你理解resume的行为边界:
resume是真正的“续跑”而非“重跑”——执行器(executor)不再隐式自动检测恢复,而是由 CLI 定位先前失败的行并把“跳过已完成节点”的语义显式交给执行器(packages/cli/src/commands/workflow.ts 的注释);run <name> --resume与resume <id>是两种不同的恢复形态:前者按当前 checkout 中该工作流最新可恢复的运行选择,后者按你手中的精确 ID选择——当你已经持有 run id 时,请优先使用精确 ID 形式,避免选错行(packages/cli/src/commands/workflow.ts)。
日志、工件与体检
- 日志:位于
~/.archon/workspaces/<project>/logs/; - 工件:位于
.../artifacts/runs/<run-id>/(对应 CLI 层get命令通过listArtifactFiles收集的leave_behind.artifactFiles,见 packages/cli/src/commands/workflow.ts); - 体检:
archon doctor检查安装本身是否健康。
小结
Archon 的 run 管理动词围绕几个关键心智模型展开:JSON 契约下“记录决策 ≠ 执行”、交互循环闸门中“评论本身是一种决策输入”、cancel 杀进程而 abandon 只改状态、终态不代表成功(Terminal ≠ Good)。结合本仓库的 manage-runs.md 与 workflow.ts 源码,你可以把每一次暂停、失败、孤儿运行都处理得精确、可验证、可恢复——并在 SDLC 工作流产生的 discovery 到达你手中时,确保它们被正确路由而不是在某个跳点悄悄消失。
【免费下载链接】ArchonThe first open-source harness builder for AI coding. Make AI coding deterministic and repeatable.项目地址: https://gitcode.com/GitHub_Trending/archon3/Archon
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考