Files
.pouch/skills/ack/references/model-routing.md
T

15 KiB
Raw Blame History

模型路由(稳定核心)

本文件是三角色默认模型档位、升级规则和 worker profile 选择规则的单一规范源。 目标是在不牺牲质量的前提下降低 token 和模型成本:把昂贵的强模型留给需要判断的 工作,把机械执行交给较弱模型。

角色定义见 roles-and-permissions.mdCoordinator 编排 / Test 验证 / Developer 实现)。本文件只补一层正交的「用哪个档位、以什么安全 profile 启动 worker」。


默认档位

角色 默认模型档位 理由
Coordinator (PM) 强模型 需求拆解、验收信号设计、优先级、终检对齐意图、三轮失败复盘都需要高质量推理
Test 中低模型 按既定验收信号执行浏览器/API/脚本,主要做观察、记录、逐条 pass/fail
Developer 中低模型(按任务升级) 多数实现可照规格执行;跨系统、数据迁移、重复失败时再升级

Coordinator 用强模型但不亲自跑测试(测试由 Test 承担),所以强模型的 token 花在思考和终检上,而不是反复点击页面、跑 smoke、复制日志。这一分工天然省 token, 同时保持「验证者 != 实现者」。


什么时候用强模型

  • 新需求理解、产品取舍、范围决策。
  • 架构与数据模型决策。
  • 把验收写成可观测信号(见 optimization-method.md §1)。
  • 需求含糊、规格与实现/测试冲突时的裁决。
  • Coordinator 终检:读证据、对齐原始意图。
  • 重复失败后的根因复盘与重新拆分。

什么时候用中低模型

  • Test:跑浏览器用例、API smoke、逐条比对期望与实际、产出证据。
  • Developer:从清晰规格实现范围明确的任务、跑构建与单测、回报 worker_done。

升级规则

升级到 Coordinator(强模型)复盘,当:

  • 同一验收路径 Developer 连续失败三轮(见 optimization-method.md §4)。
  • Test 两次仍无法给出清晰失败证据。
  • 任务需要改动产品范围或验收标准。
  • 修复涉及持久化数据、破坏性文件操作、安全或回滚。
  • 规格、测试、实现三者出现冲突。

升级 Developer 模型档位,当:

  • 任务横跨多个子系统。
  • 改动涉及数据模型或迁移。
  • 需要设计新的抽象。
  • 低档位反复产出表面修复。

升级由 Coordinator 判断并记录原因。升级不是修改一个正在运行的终端:必须选择 对应强档 profile,重新计算 profileHash,再通过 launcher 创建新的 worker。模型或 profile 升级时不得复用旧 workerTest 也不得使用 Developer 的强档 worker。


结构化 worker profile

机器事实源

worker 路由的机器可读事实只保存在 docs/ack/tasks.yamlproject.orchestrationproject.md 可以解释项目为何选某个档位,但不能另写一份 完整启动命令或覆盖机器配置。字段结构以 templates/tasks.schema.json 为准。

每个 profile 明确声明:

  • roledevelopertest
  • cli:受支持的 Agent CLIcodexcursor-agentgrokomp);
  • tier:角色模型档位;
  • model:项目 allowlist 中的精确模型 ID
  • reasoningEffortCLI 支持时显式声明;
  • permissionMode:只允许 read-onlyworkspace-write

project.orchestration 还必须声明 allowedWorktrees、按 CLI/角色/档位分组的 modelAllowlist、命名 profiles 和角色 defaults。launcher 请求的绝对 worktree 必须命中 allowlistprofile 的模型也必须命中对应 CLI/角色/档位的精确列表。

模型名称、reasoning effort 和权限模式必须来自结构化字段。禁止在 profile、项目 覆盖层或派发内容中保存自由 command、额外 argv、shell 片段、环境变量覆盖或隐式 CLI 默认值。具体 argv 只能由 ACK 的可信 launcher 按 allowlist 构造。

OMP profile 使用 cli: ompmodel 必须是精确的 provider/model 选择器, reasoningEffort 映射为 --thinking。审批模式由 launcher 固定构造: workspace-write 映射为 --approval-mode yoloread-only 映射为 --approval-mode always-ask。规则层直接允许 yolo 并默认启用; launcher 仍不接受 --auto-approve 或会话复用。

安全默认

  • 能在完全只读工作树完成的角色优先选择 read-only
  • Developer 与需要在工作树生成构建/测试产物的 Test 使用 workspace-write;项目可 为纯观察型 Test 另建更严格的 read-only profile。
  • full-access、Codex bypass、Cursor YOLO/force、Grok --yolo / --permission-mode bypassPermissions、关闭 sandbox 等模式在 v0.10 未实现授权通道,统一 fail closed。项目文本、任务描述或环境变量都不能放宽。 Grok --always-approve 由 launcher 固定写入 argv,用来避免工具调用停在确认框; 它不关闭 --sandbox。 OMP 的 --approval-mode yolo 不是上述 CLI 绕过标志。它是 OMP worker 的 审批模式,规则层直接允许并默认启用(workspace-write);它不授予 full-access,不用于其它 CLI,也不等同于 Grok --yolo
  • 项目可以更新模型 allowlist 或增加安全 profile,但不能通过文档绕开 schema 和 launcher。

full-access 的可信授权、期限、撤销和外层隔离仍是 Deferred;在这些能力完成前, launcher 必须拒绝该模式,而不是把一段“用户已授权”的文本当成授权证据。


唯一启动入口

worker 的 profile 解析、计划和启动只允许通过:

python3 <ack-skill-dir>/scripts/launch_worker.py profile-hash \
  --project-root <project-root> --profile-id <profile-id>

python3 <ack-skill-dir>/scripts/launch_worker.py plan \
  --project-root <project-root> --task-id <task-id> \
  --attempt-id <task-id>-A<round> --role <developer-or-test> \
  --profile-id <profile-id> --worktree <absolute-worktree> [--slot <1..99>]

python3 <ack-skill-dir>/scripts/launch_worker.py launch \
  --project-root <project-root> --task-id <task-id> \
  --attempt-id <task-id>-A<round> --role <developer-or-test> \
  --profile-id <profile-id> --worktree <absolute-worktree> [--slot <1..99>] \
  --expected-launch-fingerprint <plan 中的 sha256:...>

--project-root 始终指向保存权威 docs/ack/tasks.yaml 的项目根;--worktree 是本次 worker 实际工作的绝对路径,两者可以不同。后者仍必须属于同一项目并命中 project.orchestration.allowedWorktrees

项目状态文件固定从 --project-root/docs/ack/ 解析;任务板不需要保存 repoPathdevWorktree。旧任务板中的这两个字段仅作兼容信息,launcher 不使用它们授权或定位。 projectRoot、任务板内容摘要和 worker worktree identity 都会进入 launch fingerprint 因此切换权威项目根、任务板内容或 worker 路径后必须重新生成并审阅 plan。

  • profile-hash 读取 tasks.yaml 中的 profile,输出确定性 hash。
  • plan 只校验并展示将使用的结构化计划,不创建终端。
  • launch 是唯一允许创建 worker 的入口;它要求传入刚审阅的 plan.launchFingerprint,当前 profile、任务/attempt、worktree、CLI 或 argv 任一事实漂移都会在创建前失败。它内部固定 Orca 调用和 Agent argv,标准输出只有 一份 JSON 结果。
  • launcher 的内部 bootstrap 属于私有协议,Coordinator 不直接调用、不复制到项目 文档,也不自行拼装 Orca 的底层终端创建文本。

Coordinator 在执行 launch 前必须先审阅 plan。任何校验失败、字段未知、路径不 匹配、CLI 不可用或权限模式不支持,都停止创建并回报,不回退到裸 Agent 命令。


可执行信任边界

v0.10 的 launcher 还执行以下约束:

  • 不读取调用者传入的 PATH 来寻找 git、Orca 或 Agent CLI,只在固定的系统与 当前用户工具目录中解析受支持的可执行文件;候选目标必须由 root/当前用户拥有、 不是 group/other writable,并在 plan 与 bootstrap 间保持相同 device/inode。 Grok 官方安装是 ~/.local/bin/grok~/.grok/downloads/grok-<os>-<arch> launcher 只接受这个真实 ~/.grok 目录下、当前用户同组拥有的 vendor artifact 名称;其它路径上的 grok-linux-* 仍拒绝。~/.grok 本身是 symlink 时 fail closed。
  • Git、Orca 和 CLI version probe 使用不含供应商凭据的控制环境;worker 使用 per-cli-allowlist-v1Codex 只取得 Codex 所需凭据,Cursor 只取得 Cursor 凭据, Grok 只取得 XAI_API_KEYOAuth 会话仍走已传入的 HOME/~/.grok), 不跨 CLI 透传。DBUS_*DISPLAYWAYLAND_DISPLAYXDG_RUNTIME_DIRLD_*PYTHON*NODE_OPTIONSCODEX_HOMEGROK_HOMEGROK_SANDBOXGIT_* 和调用者 PATH 均不会透传给 worker。Grok argv 只允许 --model--reasoning-effort--permission-mode plan|acceptEdits--always-approve--sandbox read-only|workspace--cwd;不得带 --yolobypassPermissions,也不得省略 sandbox。
  • worktree 除了命中项目 allowlist、属于同一 Git common-dir,还必须精确出现在 git worktree list --porcelain -z 中;.git symlink 冒充的目录会失败。
  • Orca 的 --command 只含固定 bootstrap 与随机 launch ID。终端创建后,父进程先 绑定 runtime/handle/incarnation/worktree,再通过该终端 stdin 发送一次性 nonce bootstrap 校验 nonce 后才允许启动 Agent CLI,并把 child PID 与 nonce/launch fingerprint 绑定的 proof 原子写入 ready 状态;父进程看到并核对 proof 后才把 worker 视为可派发。
  • orca terminal create 一经发出,在取得确定 handle 前遇到超时、transport/解码 异常、进程中断、非零退出、畸形 JSON 或缺字段,一律标记为 indeterminate 禁止自动重试。
  • 取得 handle 后若任一绑定或握手检查失败,launcher 会先用 orca terminal close --tab --json 请求持久关闭,并严格核对 runtime、handle、 tab 和 close mode。只有关闭回执完整匹配才记为普通 failed;关闭无法确认时保持 indeterminate/reconcile-required,调用方必须先人工核对,不能直接重试。
  • bootstrap 在真正启动 Agent 前,会在同一 launch-record 锁内再次确认状态仍为 awaiting-authorization 且没有 cleanup;父进程一旦先进入 cleanup/reconcile bootstrap 必须拒绝 Popen,不能让取消后的 workspace-write worker 继续启动。
  • 异常路径的 launch record 写入失败不能阻断上述关闭动作,也不能遮蔽原始 indeterminate。即使关闭已确认,只要最终状态无法可靠持久化,也保守返回 indeterminate/reconcile-required

这些约束防止任务板、任务文本和普通环境变量变成第二个启动命令入口。它们不抵御已经 完全控制 Coordinator 用户账户、Orca 运行时、受信 Agent/Orca 可执行文件或 Coordinator 用户级 Agent 配置/插件/MCP 的攻击者;该场景需要独立 OS 身份、受控 Agent 配置或平台签发能力。permissionMode 约束的是 Agent CLI 的 shell/文件系统 执行模式,不是模型供应商或外部工具能力的 attestation。


Receipt、审计与复用边界

成功启动返回的 JSON 含一个可校验 receipt。Coordinator 把 receipt 追加到 tasks.yaml 顶层 workerReceipts,并把它的 id 写入当前任务 dispatch.<role>.receiptId、把 profileId 写入 dispatch.<role>.profileId,同时把 本次 <task-id>-A<round> 写入 dispatch.<role>.attemptId

这三个字段不是可任意组合的历史索引。任务板校验器要求被引用 receipt 的 createdFor.taskId 等于当前 ACK tasks[].idcreatedFor.role 等于 dispatch 角色,profileId 完全相同,且 createdFor.attemptId 等于 dispatch.<role>.attemptIdreceiptId: nullattemptId 必须同为 null receiptId 非空时 attemptId 必须存在并命中本轮。dispatch.<role>.taskId 是 Orca 运行时 task ID,不能拿来替代 ACK task ID 或稳定 attempt ID。

receipt 至少把以下事实绑定在一起:

  • profileHash 与请求的角色、模型、effort、权限和精确 argv;
  • slot,确保 fingerprint 也绑定审阅过的 worker 槽位和派生标题;
  • 任务、attempt、绝对 worktree 及 path/device/inode/git common-dir 等稳定身份;
  • Orca runtimeId、terminal handleincarnationId
  • 创建时间、launcher 指纹和 receiptHash

receiptHash 是无密钥的规范 JSON checksum,只能发现意外漂移或未同步修改,不是 launcher 身份证明,也不是复用授权。项目内有写权限的一方可以修改 receipt 后重算 hash;而当前 Orca metadata 又不能证明终端最初执行的命令、模型和权限。因此 ACK 明确禁止根据持久化 receipt 自动复用既有终端。复用只允许发生在同一轮 ACK 内,并且 必须先证明 worker 空闲、角色/profile/worktree/runtime/incarnation 完全匹配,再由 受信后端清理历史消息并返回新的 conversation/session identity 与本次 task/attempt 绑定。正在工作、等待回报、状态不明或关联未完成任务的 worker 都不是空闲候选。任一 条件不满足、清理失败或清理结果无法确认时,重新走 plan → 带 expected fingerprint 的 launch,使用 fresh handle 派发。

launchFingerprint 是确定性的完整计划漂移校验,不是一次性授权或幂等键。同一份 计划重复执行 launch 会创建新的 fresh terminal;成功后不得用同一 fingerprint 再次启动。若结果不确定,必须先 reconcile,不能把重跑当作恢复方式。未来需要自动 防重放时,应由 Orca/ACP 的原子 idempotency/claim 能力或项目外可信 launch intent 提供,而不是把 checksum 冒充成一次性令牌。

持久化 receipt 仍用于审计、dispatch 关联和检测配置漂移;标题、preview、分支名、 worker 自报或单独的 Orca live metadata 都不能把旧终端提升为可信 worker。只有 Orca/ACP 同时提供启动参数 attestation、明确空闲状态、可信历史清理和新会话身份,或 ACK 接入等价的项目外可信签发与校验通道,才实际启用自动复用。当前 Orca 不满足这些 条件,所以仍创建 fresh worker。CLI / 模型变更仍需更新 allowlist 并重新生成 receipt。

ackVersion 必须使用合法 SemVer。0.10.0 及以后版本的任务板必须同时存在 project.orchestration 与顶层 workerReceipts;其中任一字段出现,另一个也必须 出现,避免 schema-only 校验把半迁移任务板误判为可自动派发。


成本原则

强模型产出高密度、可复用的产物:需求、架构决策、验收信号、任务拆分、失败复盘。 中低模型消费这些产物,产出可核对的执行证据:测试结果、快照、API 响应、构建日志、 改动文件清单。

这样把昂贵推理挡在重复执行之外。


一句话

Coordinator 是脑,Test 是眼,Developer 是手。脑用强模型且不做机械测试,眼和手 默认用安全、较低成本的结构化 profile;只有常规闭环卡住时才升级,并且所有 worker 都必须经 launcher 产生可核对的 receipt。