用 Archon 编排 Issue 到 PR:分流、独立验证与预算控制

20 阅读12分钟

用 Archon 编排 Issue 到 PR:分流、独立验证与预算控制

一条公开 Issue 进入自动编码流程前,要回答三个问题:它是否属于项目范围,是否已经有人处理,以及本次运行允许花多少资源。实现完成后,还要由独立的验证环节检查原始需求。本文以 Archon 的工作流能力为基础,设计一条从分流到 PR 的流水线,并把权限、失败升级和成本停止条件放进同一套状态流转中。

先把自动化目标拆成明确职责

Archon 官方仓库提供 YAML 工作流,将规划、实现、验证、审查与 PR 创建串联起来,并支持工作树隔离。它提供编排能力;具体仓库怎样分流公众请求、执行预算和批准合并,仍由项目定义。

本文选择四个阶段:Triage 负责范围判断,Fix 负责实现,Validate 负责独立验证,Regression 负责回归检查。先让前三个阶段停在可审查的 PR,再根据项目风险决定是否启用自动合并与部署。

“黑暗工厂”只描述自动化方向

可以把协作方式从人工补全、局部委托、整项任务委托,一直排列到无人值守执行。但这种分档是讨论人机分工的示意,不是统一成熟度标准。代码生成比例提高,并不能推出验证、权限和恢复能力已经成熟。

目标越接近无人值守,就越需要把退出条件写清:任务超出范围时由谁停止,测试失败后最多修复几次,哪些文件和操作始终需要额外授权。把这些责任落实到执行器,比给系统贴某个等级更有用。

四阶段流水线怎样交接

阶段输入输出失败去向
TriageIssue、项目范围、现有 PR结构化决策与优先级请求补充、拒绝或人工审查
Fix已接受任务与固定基线代码变更、测试结果和 PR有限修复或人工接管
Validate原始 Issue、固定 Diff、可重复测试需求是否满足及具体问题退回修复或停止
Regression固定版本与用户旅程回归结果与可重放失败去重后建立问题记录

编排入口可以是定时器、手动触发或平台事件。选择轮询时要记录已处理任务与游标;选择事件时要处理重复投递。两者都需要去重、限额和持久化状态,不能靠“触发次数应该不多”维持稳定。

独立验证隔离什么

验证者可以阅读需求、基线、变更与测试代码,但不继承实现者的自证结论和整段推理记录。独立目录或工作树有助于固定输入、避免读到未提交改动;它不会让验证者“看不到实现”,因为 Diff 本身就是实现信息。

验证问题应具体到行为:原始失败能否复现,修复后是否消失,边界输入是否仍正确,是否为通过测试而放松了条件。独立上下文能减少确认偏误,仍应辅以确定性测试和必要的人工审查。

Triage 五节点:先收集,再判断,最后执行

节点 0:读取候选 Issue

先只读取仓库信息,不在收集阶段改变状态。下面按 GitHub CLI 的 JSON 输出获取候选;实际仓库应显式指定,避免在错误目录操作:

gh issue list --repo OWNER/REPO --state open --limit 10   --json number,title,body,labels,url

“每批 10 个”是本文的起步配置,不是 Archon 内建上限。持续运行还需要记录分页、排序及候选去重规则,否则每次都取前十项会让后面的请求长期得不到处理。

节点 1:读取项目规则

将目标用户、项目范围、允许修改路径和质量要求放入项目治理文档。本文用 mission.md 描述方向,用 factory_rules.md 描述执行条件。它们是项目自定义文档,内容应由维护者审定。

文档可以要求“小 PR”“有限修复”“禁止改测试以掩盖失败”,但文字不是执行器。若以 500 行作为一次变更的示例上限,应由差异统计实际检查,并明确生成文件、重命名和删除如何计数。

节点 2:查询现有工作并领取任务

读取开放 PR 和现有运行记录,检查同一 Issue 是否已被处理。GitHub 标签可以展示状态,却不是原子锁:两个执行器可能同时看到没有 in-progress 标签,然后都开始工作。

并发领取需要由持久化状态提供条件更新或租约,领取成功后再更新展示标签。运行结束、超时与接管都记录在同一条任务历史里,防止旧执行器恢复后覆盖新结果。

节点 3:生成结构化决策

模型只输出受限的决策数据,执行器不接受自由文本命令。下面是本文定义的中间格式:

{
  "decisions": [
    {"number": 42, "action": "accept", "reason": "范围内且有可重放失败"},
    {"number": 43, "action": "needs-human", "reason": "涉及权限设计,需要维护者判断"}
  ]
}

reason 是解释文字,不能被拼接成 Shell 命令。执行器只接受本批查询到的 Issue 编号、已知动作与满足长度限制的说明;出现额外字段或重复编号就停止该批,而不是猜测模型意图。

节点 4:校验后应用允许的动作

def validate_decisions(payload, allowed_numbers):
    if not isinstance(payload, dict) or set(payload) != {"decisions"}:
        raise ValueError("决策顶层字段不符")
    rows = payload["decisions"]
    if not isinstance(rows, list) or len(rows) > len(allowed_numbers):
        raise ValueError("决策数量不符")
    seen = set()
    for row in rows:
        if not isinstance(row, dict) or set(row) != {"number", "action", "reason"}:
            raise ValueError("决策字段不符")
        number = row["number"]
        if type(number) is not int or number not in allowed_numbers or number in seen:
            raise ValueError("编号越界或重复")
        if row["action"] not in {"accept", "reject", "needs-human"}:
            raise ValueError("未知动作")
        if not isinstance(row["reason"], str) or not 1 <= len(row["reason"]) <= 1000:
            raise ValueError("说明长度不符")
        seen.add(number)
    return rows

通过校验后,调用方仍需刷新任务状态,确认仓库、权限和领取关系没有变化。执行 GitHub CLI 时使用参数数组传值,避免把 Issue 文本、理由或标签拼成待执行的 Shell 字符串。部分操作失败后,保存已完成动作,再决定如何恢复。

模型选择与预算:先算整条任务

单价低不代表一次任务便宜。需要把输入、输出、推理或缓存计费、工具执行、重试和并行任务合并估算,再看同一组仓库任务的成功率与总成本。供应商兼容接口也不保证工具行为完全相同,必须重测消息、工具调用和错误路径。

选择项应比较的内容
模型同一任务集上的需求理解、代码与验证结果
接口所用执行器支持的协议与模型标识
费用输入输出及其他计费项、每任务实际消耗
延迟排队、生成、工具执行和修复总时间
可恢复性限流、超时与中断后的状态证据

成本停止条件要先于新请求

调度器应在启动前预留预算,并给每次调用设置输出和时间上限。达到阈值后停止新任务,已经在运行的请求仍可能继续产生费用,因此需要为在途工作留出余量。

关闭自动充值、使用供应商账户限额可以作为额外控制,但不能代替任务预算,也不能保证最后一个在途请求没有超出预估。记录实际账单与本地估算差异,下一轮据此调整余量。

限制自动修复与回归建单

本文示例把连续两次失败作为升级人工的起点。次数应按同一任务的实际尝试累计,不能因换进程或换工作树就归零。缺少凭据、服务不可用与代码错误要分别记录,避免把同一个环境问题重复交给实现 Agent。

回归检查发现失败时,先保存固定版本、输入和错误证据,再按指纹查找现有 Issue。相同故障只更新一次问题记录;环境恢复后重测,防止“测试失败—自动建单—再次失败”制造无尽队列。

权限控制:规则、工具权限与系统隔离分层

模型读到“禁止读取密钥”是行为指令;工具权限能拒绝部分调用;操作系统或容器隔离限制进程实际可访问的资源。这三层不能混为一谈。跳过交互确认不会自动创建沙箱,一个 Hook 脚本也不等于系统级文件隔离。

下面是本文的策略需求清单,用来核对执行环境,而非把字段当作 Archon 的现成配置:

{
  "governance": {
    "protected_paths": ["mission.md", "factory_rules.md", "agent_rules.md"],
    "maintenance_owner": "human-maintainer"
  },
  "runtime_requirements": {
    "secrets_not_mounted_into_agent": true,
    "write_scope": "leased-worktree",
    "network_egress": "explicit-allowlist",
    "merge_and_deploy": "separate-authorization"
  }
}

部署者应把这些要求落实到账号、挂载、文件权限、网络策略与执行器设置,并用实际拒绝用例测试。若 Agent 能通过另一种工具、子进程或路径别名访问同一资源,单个工具名的拦截就不完整。

治理文件保护要放在执行边界

把治理文件列为只读,再检查每次变更是否触及受保护路径。仓库分支保护、必需检查和受控的合并凭据也应独立配置。Agent 不能因认为规则不方便就修改预算、测试阈值或审批条件;规则变更走维护者审查。

对可能引入依赖、数据库迁移、权限变更和部署动作的任务,先划出单独授权边界。代码测试通过只能证明已覆盖的检查通过,不能单独授权这些外部效果。

标签显示状态,持久化记录决定动作

标签展示含义执行器还需要什么
factory: accepted已接受,等待领取范围与预算检查
factory: in-progress正在处理有效租约与执行者标识
factory: needs-fix验证提出具体问题固定 Diff 与失败证据
factory: needs-human自动处理停止明确接管原因与当前状态
factory: rejected不进入实现可解释的拒绝理由
factory: rate-limit资源预算暂停真实预算记录与恢复条件

初始化标签可以使用 GitHub CLI。执行前指定自己的目标仓库;下列只是建立标签,不会实现任务锁或预算控制:

gh label create "factory: accepted" --repo OWNER/REPO --color "0E8A16" --description "已接受,等待领取"
gh label create "factory: in-progress" --repo OWNER/REPO --color "FBCA04" --description "正在处理"
gh label create "factory: needs-fix" --repo OWNER/REPO --color "D93F0B" --description "验证未通过"
gh label create "factory: needs-human" --repo OWNER/REPO --color "5319E7" --description "需要人工接管"
gh label create "factory: rejected" --repo OWNER/REPO --color "B60205" --description "不进入实现"
gh label create "factory: rate-limit" --repo OWNER/REPO --color "F9D0C4" --description "预算暂停"

暂停时不再启动新任务,保留在途任务的租约与实际结果。恢复时重新检查预算、权限和目标版本,避免把旧标签当作仍然有效的执行许可。

Issue 表单帮助收集信息,入口仍要校验

Bug 表单至少收集现象、复现步骤、预期行为和环境。GitHub Issue Forms 支持必填字段;表单校验本身不会替你创建自动关闭流程,经其他入口提交的内容仍须检查。

name: Bug 报告
description: 提供可重放的失败信息
labels: ["untriaged"]
body:
  - type: textarea
    id: description
    attributes:
      label: 问题描述
    validations:
      required: true
  - type: textarea
    id: repro
    attributes:
      label: 复现步骤
      description: 写出输入、操作和实际结果
    validations:
      required: true
  - type: textarea
    id: expected
    attributes:
      label: 预期结果
    validations:
      required: true

收到不完整请求后,可以要求补充、拒绝或升级人工,具体策略应与项目维护方式一致。不能把“保持队列短”当作关闭所有复杂问题的理由,也不能让模糊请求无限占用执行预算。

用一次受控任务验收整条链路

先选一个范围小、能复现、没有外部生产效果的 Issue。检查 Triage 的判断是否可解释,领取是否唯一,工作树是否固定,失败时预算是否停止;再让验证者按原始需求检查结果。

随后主动制造几个失败:模型超时、测试错误、重复触发、预算不足与受保护路径修改。每一种失败都应落到明确状态,保留实际证据,允许维护者继续处理。等这些路径跑通,再扩大任务范围和并发度。

自动化的价值在于把重复执行和证据收集做得更稳定。是否启用自动合并或部署,应由任务风险、权限隔离、回归覆盖和恢复能力共同决定。先交付一条可以解释失败、可以停止、可以接管的 Issue 到 PR 流程。

参考来源