Eosphor
Vyane 功能

goal 与额度接力

主力模型额度用光后,怎么自动接力到备选模型继续把长任务干完,且中间有人把关。

这一页解决什么

一个长任务跑着跑着,主力模型(比如通过 Codex CLI 调 GPT)的额度突然用光了——这在几个小时的自主任务里很常见。传统做法是任务卡死在那儿,等你回来手动换个模型重开,上下文和进度往往也丢了。

Vyane 的 goal 接力(goal continuity)就是为这件事设计的:把「主力被额度挡住」变成一个可观测的状态,自动把接力目标(换个还有额度的模型)准备好,等你点头之后接着往下干,干完再交回主力审查恢复。

一句话

主力额度用光 → 系统看见并标记 → 备选模型准备接手 → 你批一下 → 接力模型继续干 → 主力恢复前先审查接力的成果。全程留痕、不偷偷换人。

goal 不是 Codex 自带的 /goal 记录,而是 Vyane 自己的一等公民:每个 goal 用 JSONL 持久化,SQLite 做派生索引,进度和状态都记在同一本账上。

三个角色:primary / takeover / reviewer

接力这件事围绕三个执行目标(execution target)转,写策略(continuity_policy)时就得把它们各自定清楚。注意每个目标不能只写「用某某模型」这种模糊话,得写清楚 provider(谁给额度)、protocol(wire 形态)、model、harness(执行壳)和 profile——因为「换模型」本质上是四层里某几层被替换了,替换必须记下来、不能藏。

角色中文理解干什么
primary主力优先执行目标,比如通过 Codex CLI 调 GPT。正常情况下活都是它干。
takeover接力primary 被额度挡住时,允许继续把活干下去的目标,比如换一个兼容 harness 去调另一个模型。
reviewer审查primary 恢复之前,负责审查接力成果的目标;额度刷新后的 primary model 本身也可以充当这个角色。

为什么要有 reviewer

主力额度刷新回来后,Vyane 不会直接一把覆盖、假装接力那段没发生过。如果策略里 require_review_before_resume 为真,就得先让 reviewer 审过接力改了什么、测试过没有、验收标准满足没有,审过了才让主力恢复。这样避免把「额度回来了」误当成「接力干得对」。

状态机:一个长任务怎么流转

接力过程是一条明确的状态链,每一步都由可观察的事实(额度事件、审批决策、审查结果、GitHub check 信号)驱动,不会凭空跳步:

in_progress            正常执行中
  -> primary_blocked          主力被额度挡住
  -> takeover_ready           接力目标已就绪,等批
  -> takeover_running         接力模型正在干
  -> takeover_waiting_review  接力干完,等审查
  -> review_running           审查进行中
  -> primary_resume_ready     审查通过,主力可恢复
  -> primary_running          主力恢复执行
  -> completed / failed / paused / cancelled

驱动这条链往前走的是每一步(step)自己的小状态机:ready(就绪)、in_flight(执行中)、done(完成)、blocked(卡住)。前置步骤 done 了,依赖它的等待步骤才会变成 ready。这些状态写进 metadata.continuity_state,重复写同一个状态是幂等的,不会重复触发。

几条硬规则(scheduler 必须守)

没有配 takeover 目标就不启动接力;终态的 goal(已完成/失败/取消)不启动接力;同一个额度事件不重复启动同一个接力;require_review_before_resume 为真时审查前不恢复主力;不能只凭一个额度事件或接力事件就断定验收标准满足了。

四步操作:从「被挡住」到「接手」

日常你会用到的是这四个 CLI 命令,一步步把接力推进,每一步的边界都很清楚——扫描只读事实、预览只展开命令、审批只排队记录、执行也只是构建请求,真正启动接力 worker 需要审批决策里带明确的 execute=true

最短路径先记住这个骨架(细节看下面每步说明):

uv run vyane goal continuity-scan                    # 1. 谁被挡住了
uv run vyane goal continuity-preview --id <goal_id>  # 2. 打算怎么接力(只读)
uv run vyane goal continuity-approvals --id <goal_id> # 3. 写进审批队列
uv run vyane goal continuity-execute <goal_id> <step_id> --approval-id <id>  # 4. 执行
  1. continuity-scan — 扫描额度账本,把「谁被挡住了、哪个接力已就绪」标记出来

    读取 Codex / GPT 的 quota ledger,把额度事件匹配到正在进行的 goal,幂等地写进 continuity_state,并记一条 quota-handoff 进度事件。这一步回答:「哪个 goal 被挡住了,哪个 takeover target 已 ready?」

    vyane goal continuity-scan --json
    # 只想算不想写:加 --scan-dry-run
  2. continuity-preview — 把就绪的接力步骤展开成待批准的命令(只读)

    把 ready 的 handoff step 展开成将要执行的命令,并带上解析好的目标 metadata(provider/protocol/harness/model),给你看清楚「接手前到底要发生什么」。它不写状态、不启动任何进程。

    vyane goal continuity-preview --id <goal_id> --json
  3. continuity-approvals — 把待批命令写进共享审批收件箱

    为就绪的接力命令排队 approval record(approval_kind = "goal_continuity_handoff"),按 goal id、step id、额度事件 id 幂等。这一步只记录「有个决策等待确认」,不修改 goal 状态,也不启动模型。它回答:「takeover 开始前,使用者到底在批准什么?」

    vyane goal continuity-approvals --id <goal_id> --json
  4. continuity-execute — 为已批准、已就绪的步骤构建可派发的执行请求

    给一个 approved、ready 的 step 构建 dispatch-ready 请求,保留 provider/protocol/harness/model 边界。它本身只构建或记录执行,不直接拉起 worker;只有当审批决策明确带 execute=true 时,受控启动路径才会提交 worker,而且只支持已经接住的 harness(codex-cliclaude-code)——opencode、direct chat 这类目前只报告不启动。

    vyane goal continuity-execute <goal_id> <step_id> --approval-id <id> \
      --workdir <path> --sandbox write --timeout 3600

不自动瞎切

整套设计的底线是:系统会把接力准备到「就差你点头」,但绝不自动替你换模型、启动进程。额度用光是可见的、接力目标是记好的、审批是显式的、执行边界(工作目录 / sandbox / 超时)也是写进审批记录的。没有明确批准 + 明确请求执行,接力 worker 不会跑起来。

continuity-runner:周期扫描,但不越权

前面四步是手动一步步来;continuity-runner 是把「扫描 + GitHub 信号桥接 + 审批排队」这几件事打包成一个可周期运行的入口,适合挂 launchd 定时跑,且不依赖 daemon

vyane goal continuity-runner
# 只跑额度扫描、跳过 GitHub 看门狗:加 --skip-gh-watchdog

它每次跑会做三件事:调用和 continuity-scan 同一套额度控制器;(未跳过时)调 gh-watchdog 把 GitHub 上 PR review / check 的终态转成 goal continuity 信号;扫描后为新就绪的步骤排队或复用审批记录。配套的 launchd plist 装好后每 300 秒跑一次。

runner 不是自动执行器

这一点必须说死:runner 不 approve、不 apply、不 execute,也不启动任何 model / provider / harness worker。它只是周期性地把事实刷新、把待批的事排好队。真正的启动,永远卡在「显式审批 + 显式请求执行」这道关后面。

额外的信号来源

接力的「就绪」判断不只看额度,还能吸收外部信号:

  • 额度刷新vyane goal continuity-signal <goal_id> quota_reset 可以记录一条 ready signal。但注意——记录额度回来了,不等于自动恢复主力;如果策略要求审查,还得等 review 那步 done。
  • GitHub review / checkgh-watchdog 能把某个 PR 的 check 终态写成 continuity 信号(通过写 review_checks_passed,失败写 review_checks_failed),用来唤醒下一个可见的 goal step,同样不启动 worker。
  • 查下一步该干嘛vyane goal continuity-next-action 把当前 step、所有 handoff step、接力 run、ready signal 的可读证据一起返回,让你(或调度器)不用翻完整 goal state 就知道下一个动作是「审查接力成果 / 等额度刷新 / 批准恢复主力 / 修失败的 check / 无动作」。

相关

On this page