# AgentRun Queue 与旧 Code Queue 指挥监督策略

本文定义在人工或 lead-agent 指挥官监督下，使用 AgentRun Queue 作为新任务并行交付基础设施、使用旧 Code Queue 作为历史归档和残留任务停止入口的长期运行模型。本文是协同策略，不替代 `docs/reference/microservices.md`、`docs/reference/observability.md`、`docs/reference/user-service-delivery.md`、`docs/reference/agentrun.md` 或 Code Queue runtime 合同。

## 范围

当一个交付目标过大，无法由单个 AgentRun task 完成，并且必须拆分到多个队列、服务或基础设施 lane 时，使用本策略。

本策略适用于：

- 用户服务 CI/CD 推广；
- 需要多个隔离 worktree 的跨服务修复；
- 用户服务开发过程中暴露出来的基础设施缺陷；
- 后续验证、retry、验收和任务接力协调；
- 指挥官为了保持 AgentRun 任务推进而做的手动监督工作，但不接管 worker 的具体实现。

本文不授权绕过正常部署、Git 或生产安全规则。

## 运行原则

指挥官对最终结果负责，AgentRun task 对边界明确的执行负责。

指挥官应维护交付目标、活跃队列、阻塞点、证据缺口和下一步恢复动作的实时地图。AgentRun worker 应收到自包含 prompt，prompt 中必须有足够上下文，不能依赖 GitHub issue 可见性或聊天历史。

集中指挥的目标是提升交付吞吐和可用性，而不是把每个缺陷都变成一次性的人工修补。

指挥官的最终目标是推动整体开发波次持续前进：跟踪队列进展、及时纠偏、审查完成质量，并安排下一轮任务，让交付计划持续复利式推进，而不是一批任务结束后停滞。

## HWLAB / #20 监督口径

`pikasTech/unidesk#20` 只承载 UniDesk 指挥控制面：command/control、AgentRun Queue、旧 Code Queue 归档、CLI、基础设施、PR 收口和治理态势。HWLAB 产品功能、用户体验、M3 验收、DEV runtime、发布收敛和用户反馈必须进入 `pikasTech/HWLAB` issue/PR，并由 `pikasTech/HWLAB#7` 或 HWLAB 侧对应看板承载；#20 只能保留指挥侧路由行、关联 task、阻塞分类和回链，不复制 HWLAB 产品验收口径。更新 #20 时优先使用 `bun scripts/cli.ts gh issue update|board-row ... --board-issue 20`，该 guard 会拒绝把 HWLAB 产品 issue 行写入 #20，并提示改写到 `pikasTech/HWLAB`。HWLAB 指挥侧固定入口、热修边界和长期 source of truth 见 `docs/reference/hwlab.md`。

当 HWLAB 是当前优先级最高的推进对象时，所有派单 prompt 的开头都必须显式引用 `DC-DCSN-P0-2026-003`，并说明任务究竟服务于 M3 虚拟硬件可信闭环的哪一环。如果任务只是在做发布前置、诊断、证据收口或文档治理，也必须明确写出它不抢占 M3 P0。

HWLAB 业务目标、验收和实现优先级归 `pikasTech/HWLAB#7`；UniDesk 指挥治理、队列监督、并发窗口、PR handoff 和 runner 能力归 `pikasTech/unidesk#20`。#20 可以记录 HWLAB #7 的调度状态和证据链接，但不能替代 HWLAB 业务 issue。

审阅 HWLAB runner 输出时，不能把 `SOURCE`、`LOCAL`、`DRY-RUN`、fixture 或只读报告误当成 `DEV-LIVE`。除非输出真的证明了 `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` 的真链路，并且带有 operation / audit / evidence 关联，否则只能归类为 support、diagnostics 或 contract。

`split-brain live` 且 heartbeat/trace 新鲜时，指挥官必须继续监督，不把它当作服务中断。此类状态的优先动作是继续轮询、继续审阅和在 AgentRun Queue 中派发新任务，而不是默认 interrupt、cancel 或重启旧运行面。旧 `codex task/tasks/output/read/unread/queues` 的 bounded summary 仍用于历史监督；旧 `codex submit` 不再作为新任务写入确认来源。需要 raw drill-down 时使用返回的 `queue.listPreviewPolicy.rawCommand`，即 `bun scripts/cli.ts microservice proxy code-queue /api/tasks/overview?limit=30 --raw --full`。

`codex tasks --view commander --limit N` 是指挥官高频轮询入口，必须保持默认 stdout 严格有界。它优先展示 active runner 精确计数与少量 active item、queued/retry_wait count、terminal unread compact counts、关键 risk counts 和 drill-down commands；历史 terminal unread item details、prompt preview、final response preview、trace/output 和 raw overview 不在默认 commander 输出中展开。需要审阅 terminal unread 详情时使用 `bun scripts/cli.ts codex unread --limit N`、`bun scripts/cli.ts codex tasks --unread --view supervisor --limit N`、`bun scripts/cli.ts codex tasks --view full --limit N` 或 per-task `bun scripts/cli.ts codex read <taskId>`。

live-read browser audit 只用于观察已部署 UI，不授权写入。未获得显式 live mutation 授权时，审计浏览器只能放行 `GET`、`HEAD` 和 `OPTIONS`；`POST`、`PUT`、`PATCH`、`DELETE` 以及其他可能改变状态的方法必须被拦截并 abort，报告时统一标记为 `audit guard blocked page mutation attempt`，同时记录 method、path、触发的页面动作和已拦截事实。这个证据只能证明页面渲染、只读请求和某个交互会尝试发起写请求；它不能证明 backend outage、写入失败、写入成功、持久化状态变化或 mutating workflow 已验收。需要真实点击、提交、启动、停止、保存、删除、训练或其他 live-mutating acceptance 时，必须先取得针对目标服务、动作和环境的明确授权，并按授权后的验证规则单独记录结果。

每次新派一批任务、接收一批 completed unread 结果，或者发生实质态势变化时，都要同步更新 `#20` 的正文主表；如果当天有滚动简报，则同时更新当日简报 issue 的正文主内容，而不是只在聊天中补上下文。

## DEV 测试授权分级

`DEV` 只说明目标环境，不自动说明允许的写入级别。所有 runner prompt 和 supervisor closeout 都必须把 DEV 验证分成 `read-only`、`live-read` 和 `live-mutating` 三类；如果 prompt 没有显式分类，默认按 `read-only` 处理。

| 分级 | 含义 | 常见允许动作 | 禁止动作 |
| --- | --- | --- | --- |
| `read-only` | 不连接或不观察正在运行的 DEV 服务，只验证源码、fixture、mock、dry-run 或静态输出。 | `git diff`、`rg`、语法检查、CLI `--dry-run`、生成计划或补文档。 | 访问 live service、触发任务、写数据库、部署、重启、rollout、真实硬件或虚拟硬件动作。 |
| `live-read` | 读取正在运行的 DEV 服务、日志、health、status、metrics、Kubernetes 只读对象或只读 API，不改变 live 状态。 | `GET /health`、`GET /status`、只读 proxy、`kubectl get/describe/logs`、只读 CLI status/diagnostics。 | `POST/PUT/PATCH/DELETE`、`kubectl apply/delete/rollout restart`、触发 schedule/job/task、写 issue/PR 之外的 runtime 状态、任何会创建 operation/audit/evidence 的动作。 |
| `live-mutating` | 在 DEV 环境执行会改变 live 状态的命令，即使目标是 smoke、复测或诊断。 | 经 prompt 明确授权的 dev deploy/apply/rollout、trigger/run/retry、task submit/steer、写配置、创建 operation/audit/evidence、HWLAB M3 DO/DI 链路触发。 | 任何未被 prompt 精确列出的 live mutation；生产写入、密钥读取、数据库手工 patch、Code Queue 高风险干预仍按更高安全边界处理。 |

`DEV smoke`、`M3 smoke`、`live smoke`、`复测`、`验证` 这类词本身不构成 live mutation 授权。只要命令会改变 DEV runtime、触发真实或虚拟设备动作、创建任务/operation/audit/evidence、改变 deployment 或写入服务状态，就必须归入 `live-mutating`。

派单 prompt 必须显式写出：

- `DEV test class`：只能是 `read-only`、`live-read` 或 `live-mutating`。
- `允许的 live mutation`：若 class 是 `live-mutating`，必须逐项列出允许的命令形态或动作、目标环境/服务/namespace、可接受的状态变化、观察和回滚步骤；若没有授权，写 `none`。
- `禁止动作`：至少说明 prod mutation、密钥明文、数据库手工 patch、Code Queue backend 重启/重建、运行中任务 interrupt/cancel 是否禁止；未写明的高风险动作一律禁止。
- `closeout 字段`：runner final response 必须报告实际执行的 test class、是否发生 live mutation、执行命令摘要、目标环境、证据链接或 ID，以及未覆盖风险。

runner 收到未分类或含糊的 prompt 时，只能执行 `read-only` 范围；如果完成任务需要 `live-read` 或 `live-mutating`，必须停在计划和待授权状态，列出拟执行命令、风险和需要指挥官补充的授权，不能自行把“DEV”解释成允许写入。

supervisor closeout 不能只看 runner 的成功自述，必须核对 prompt 授权和实际命令级别：

- `read-only` closeout 应证明没有 live service 写入，证据来自 diff、静态检查、语法检查或 dry-run 输出。
- `live-read` closeout 应记录读取的 DEV endpoint、service、namespace 或日志范围，并明确没有触发 runtime 状态变化。
- `live-mutating` closeout 应指出 prompt 中的明确授权、实际变更目标、operation/audit/evidence/task/job ID、回滚或恢复观察，以及 prod 未触碰。
- 如果 runner 在没有明确 prompt 授权时执行了 live mutation，即使 smoke 结果成功，也不能把任务验收为正常完成；指挥官应先核实 live 状态和 blast radius，再把它记录为治理缺陷或 follow-up，并修正后续 prompt 模板。

HWLAB M3 口径使用同一分级：只读报告、fixture、LOCAL/DRY-RUN 和 diagnostics 只能算 `read-only` 或 `live-read`；触发 `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` 的可信闭环属于 `live-mutating`，必须有 prompt 明确授权并在 closeout 中给出 operation / audit / evidence 关联。

## 任务设计

每个 AgentRun task 都必须有清晰且狭窄的 ownership 边界。

- 尽量每个任务只负责一个服务、模块或基础设施缺陷。
- 每个任务使用共享 workspace 下自己的 detached worktree。
- 在 prompt 中直接写明写入范围、验证范围、提交/推送要求和禁止动作。
- 相关背景必须写进 prompt；issue 链接只能作为辅助引用，不能作为必要上下文。
- 优先复用已有队列；只有现有 lane 无法表达 ownership 边界时，才创建新队列。
- 队列并发必须受真实执行能力约束。通常目标是约 5 条并发 lane；当活跃任务写入范围彼此独立、heartbeat/trace 证据健康、成功率可接受时，指挥官可以把并发提高到约 10。若完成质量下降，应先降并发再继续扩张。

靠近生产的任务 prompt 必须明确禁止在 master server 上跑已知可能 OOM 的重型本地检查，并说明哪些验证应在 D601 CI、dev env 或目标服务容器中执行。

当一个指挥机需要突发创建大量 AgentRun 任务时，`agentrun create task` 或 `agentrun apply -f -` 默认应串行或接近串行。为了避免控制面在确认任务前被打爆，可以使用短本地锁或短延迟，尤其是在低内存主机上。目标是保持任务创建可观测且稳定，而不是最大化瞬时入队吞吐。

## 模型和成本路由

AgentRun 新派单和历史 Code Queue 审阅都按成本、可信度和 blast radius 分层：GPT-5.5/Codex 处理高风险和复杂任务，DeepSeek/OpenCode 处理中等复杂度且边界清晰的任务，MiniMax/OpenCode 处理简单、低权限、可复核任务，生产重启、密钥、数据库手工写入和运行中任务控制保留给指挥官或人工。

当前新任务派发合同由 `bun scripts/cli.ts agentrun get|describe|events|logs|result|ack|cancel|dispatch|create|apply|send` 资源原语暴露：`get tasks --queue commander` 查看指挥官队列，`create task --aipod Artificer --prompt-stdin` 或 `apply -f -` 创建任务，`dispatch task/<taskId>` 派发，`events/logs/result/ack/cancel/send` 读取和控制 AgentRun task、run 与 session。UniDesk 是 render-only client：日常一次性 YAML/JSON 和 prompt 输入优先用 quoted heredoc/stdin，客户端按 `config/agentrun.yaml` 直连 AgentRun REST API 并保留 k8s 风格渲染；`send session/<sessionId>` 是唯一用户级 session follow-up 写入口，服务端按 durable session/run/command 状态自动决定内部 `steer` 或新 `turn`，旧 CLI `turn/steer` 路径不保留兼容。`--json-file`、`--prompt-file` 和 `--runner-json-file` 只是客户端输入来源。该路径不经过 HWLAB runtime、SSH official CLI 或旧 bridge wrapper，不做旧 Code Queue 双写，也不迁移旧历史。
旧 `codex submit/enqueue`、`codex steer`、`codex resume`、旧 queue mutation、task move 和旧 workdir mutation 已冻结。CLI 必须返回 `ok=false`、`frozen=true`、`degradedReason=legacy-code-queue-frozen` 和 AgentRun 替代命令；服务端旧 API 写入口必须返回 410。旧 `codex task/tasks/output/read/unread/queues` 继续作为历史归档和只读排障入口，`codex interrupt|cancel` 只用于停止残留旧任务。

新任务模型由 AgentRun task payload 和 AgentRun runtime 配置决定；旧 Code Queue 的 `CODE_QUEUE_MODELS` 只作为历史任务审阅和残留运行面配置参考，长期合同至少包含 GPT-5.5、GPT-5.4、GPT-5.4 Mini、DeepSeek Chat、MiniMax M3 和 MiniMax M2.7 两路并行配置；`deepseek`/`deepseek-chat`、`minimax-m3` 与 `minimax-m2.7` 会走 OpenCode port，其余模型走 Codex port。PROD 集群把 `MINIMAX_MODEL` 切到 `MiniMax-M3`（M3 是新任务的默认 provider model），judge 与 opencode 跟随；M2.7 仍然作为并行配置存在，切换只需把 `MINIMAX_MODEL` 改成 `MiniMax-M2.7` 后 rollout restart。两者不存在自动 fallback 关系：M3 任务失败不会自动改派 M2.7，task 要用 M2.7 必须显式 `--model minimax-m2.7`。只有当执行面 `/health` 或等价配置已经显示 DeepSeek 模型可用、并完成轻量 runner smoke 后，才允许真实提交 `--model deepseek-chat`。

AgentRun 派单边界由指挥官直接审查和负责，不再通过额外本地派单审查命令。新任务 prompt 仍必须自包含，并写清写入范围、验证范围、禁止动作、是否允许运行态变更、提交/推送/PR/merge 边界和 closeout 字段；这些要求属于调度质量责任，不是额外 CLI guard。



Device Pod 类 DS 派单必须把工具可用性设计进 prompt，而不是靠事后强制纠偏。prompt 应明确唯一 pod、workspace selector、目标工程/target、允许的 live mutation、禁止的 pod/BOOT/生产/密钥/数据库范围和 closeout 字段；文本源码修改默认要求 `hwpod ... workspace apply-patch`，新文件使用 `apply-patch --add-file`，整文件替换使用 `apply-patch --replace-file`，不要优先 `workspace put`。命令入口默认写短别名 `hwpod`，不要写长路径 `node /app/skills/device-pod-cli/scripts/device-pod-cli.mjs`；`hwpod` 必须作为 Code Queue 镜像和 provider dev container 的 PATH 命令存在，并从 `DEVICE_POD_CLI`、`UNIDESK_SKILLS_PATH/device-pod-cli`、当前 workspace 的 `skills/device-pod-cli` 或 `tools/device-pod-cli.mjs` 解析真实 CLI。添加 Keil 源文件、build clean、download、UART/JSON-RPC smoke 也应走 `hwpod`。prompt 中只允许把 `/app/tools/tran.mjs`、`/app/tools/hwlab-gateway-tran.mjs`、临时 Python/PowerShell/JS 上传脚本列为禁止绕行；如果 DS 仍然需要这些绕行，指挥官应先把缺失能力补进 `device-pod-cli`/`hwpod`，再重置 workspace 让 DS 复测。

Device Pod 类 DS 验收不能只看最终回复。指挥官必须用 `codex task <taskId> --trace` / `codex output <taskId>` 审计实际命令面：确认是否使用 `hwpod`，是否出现长 CLI 路径、`tran.mjs`、`hwlab-gateway-tran.mjs`、临时脚本上传、`workspace put` 或构建产物 patch/put/delete；同时核对 build job、download job、UART/JSON-RPC 或屏幕/串口等硬件证据。若任务因为模型上游 429/503、transport 断连或 Code Queue continuation 被错误降级而没有进入工具调用，不应把它记作 device-pod-cli 失败样本，应先处理调度/运行面摩擦，再重新派发干净任务。

并发治理按模型和风险一起决定。GPT-5.5 常规并发目标是 5 条 lane；当写入范围互不重叠、heartbeat/trace 健康、完成质量稳定时可以短时提高到 10。MiniMax 只承接简单任务时可以提高到 10，但必须保留指挥官审阅和证据核验。DeepSeek 用于中等复杂度任务，默认按约 5 条 lane 观察质量，再根据成功率和 reviewer 负载逐步调整。并发扩张的前提永远是任务质量和可观测性，而不是模型价格。

模型选择矩阵：

| 首选模型 | 适用任务 | 必须满足 | 禁止下放 |
| --- | --- | --- | --- |
| GPT-5.5/Codex | 高风险、复杂、跨模块、运行态、CI/CD、release、deploy、安全、最终质量裁决 | 多信号诊断、可回滚边界、必要的轻量或 dev 验证 | 不因成本把运行态和生产风险降级 |
| DeepSeek/OpenCode | 中等复杂度的前端功能、局部用户服务模块、局部 CLI/helper、明确 dry-run 或语法验证 | prompt 自包含、写入范围窄、无生产/密钥/DB 写入、验证命令明确、指挥官审阅 | 不处理 Code Queue runtime、backend-core、provider-gateway、k3sctl-adapter、release/v1 或部署变更 |
| MiniMax/OpenCode (M3 / M2.7 并行) | 只读调查、文档、简单前端/样式、低风险样板、轻量 dry-run/preflight 和小范围测试补齐 | issue 只作辅助引用、必须给出 diff/路径/命令证据、完成后保持未读待审 | 不处理共享核心、隐式远端状态、生产、密钥、DB、重启、复杂 bug 或最终裁决 |
| 指挥官/人工 | 真实生产动作、运行中任务控制、密钥/数据库/破坏性 Git、批量已读和高风险恢复 | 用户授权、只读诊断、恢复方案、记录 issue/#20/#24 | 不把执行权交给普通 worker |

外部 token provider、模型 API 和上游服务限流遵循本文监控章节的退避规则；`policyContract.externalProvider429` 只是把同一规则暴露给 dry-run 调度判断。

MiniMax/OpenCode 可承担任务必须同时满足这些条件：

| 类型 | 适用边界 | 必须证据 | 不可越界 |
| --- | --- | --- | --- |
| 只读调查 | 查找文件、梳理现有实现、列出候选入口、对比文档口径 | 文件路径、行号、命令输出摘要 | 不得把 issue 内容当唯一输入，不得声称读取了无法验证的远端状态 |
| 中文文档初稿或长期参考补丁 | `docs/reference/`、`AGENTS.md` 索引、一句话摘要、表格治理规则 | diff、文档位置、轻量格式/grep 检查 | 不写流水账，不改 release/v1 runtime |
| 轻量 CLI dry-run/preflight | 只读或 dry-run 输出、参数校验、错误分类 | dry-run JSON、语法检查或原入口命令输出 | 不改 runtime 调度核心，不触碰生产服务 |
| 局部回归验证 | 用户明确要求时才补最小测试，否则只做语法/命令形态检查 | 验证命令、失败前提、通过输出 | 不跑 heavy check、E2E、Playwright，不默认新增测试脚本 |
| 小范围样板代码 | 非共享核心、可快速 review、可用类型检查或 dry-run 验证 | 修改文件、轻量类型/脚本验证、commit | 不跨多服务，不改凭证、网络、部署或数据库 |
| 数据整理和看板候选草案 | 生成 #20/#24 更新草案、任务表、验收 checklist | 草案 diff、来源列表、人工待审标记 | 不直接替代指挥官审阅，不自动清空未读任务 |

GPT-5.5/Codex 必须承担这些任务：

| 类型 | 原因 | 验收重点 |
| --- | --- | --- |
| Code Queue/backend-core/provider-gateway/k3sctl-adapter 运行态修复 | 运行面错误会影响调度、观测和恢复路径，MiniMax 误判成本高 | 多信号诊断、轻量 contract、必要时 dev 验证；不隐式 prod rollout |
| 跨模块架构或共享契约调整 | 需要理解系统边界、兼容性和长期演进 | 文档、代码、测试和回滚边界一致 |
| CI/CD、artifact、deploy、release/v1 治理 | 易影响发布真相和稳定维护线 | dry-run/plan、commit-pinned 证据、release governance 一致 |
| 安全、凭证、网络、egress/proxy 变更 | 涉及 secret 泄漏、访问路径和外部服务 | 不输出 token，最小权限，结构化失败 |
| 复杂 bug 修复和最终质量裁决 | 需要辨别不完整证据、伪造、隐藏失败 | trace/output/commit/test 交叉验证 |
| 生产部署方案设计或回滚方案 | 生产 blast radius 高，即使只写方案也需高可信推理 | 明确非目标、授权点、验证和回滚 |

只能由人工或指挥官处理的任务包括：真实生产重启、Code Queue backend 重建、运行中任务 interrupt/cancel、密钥读取或轮换、数据库手工写入、破坏性 Git 操作、强制回滚、把完成未读任务批量标记已读、以及任何需要用户授权的高风险恢复动作。这类任务可以让 worker 起草方案或 checklist，但执行权不下放给 MiniMax，也不应下放给普通 GPT worker，除非用户明确授权并给出边界。

MiniMax prompt 必须自包含：目标、背景、写入范围、禁止动作、验证命令、final response 字段都要写进 prompt；GitHub issue 只能作为辅助引用，不能作为唯一来源。禁止使用“读取 issue 后按里面做”这类 prompt。若确实需要 issue 内容，指挥官先把关键需求、约束和验收点摘入 prompt，再附 issue URL。

MiniMax 风险控制必须固定包含：禁止 prod/重启/密钥/DB 写入；禁止 release/v1 runtime 修改；禁止 heavy check/E2E/Playwright，除非任务明确改为 GPT-5.5 且用户授权；必须给出可验证证据，包括修改文件、命令、测试输出、commit 和未覆盖风险；完成后保持未读，由指挥官用 `codex task <taskId>` 审阅后再单独 `codex read <taskId>`。

MiniMax 任务涉及远端文本修改时，prompt 必须显式指定标准写入入口和失败恢复动作：

- 默认使用 workspace-prefixed `trans <route> apply-patch <<'PATCH'`，或对应业务 CLI 的 `apply-patch` 子命令；补丁正文直接进入 quoted heredoc，不先创建 patch 文件。
- 若 stderr 报 `failed to find expected lines`，必须重新读取当前目标块，缩小或拆分 `Update File` hunk 后继续 `apply-patch`。
- 不得把上下文过期当作改用 `download` / `upload`、远端 Python/Perl/sed heredoc、`cat >` / `tee` 整文件重写或 `apply-patch-v1` 的理由。
- 指挥官验收 MiniMax trace 时应搜索这些 forbidden command 形态；若出现，优先修 CLI hint/prompt 或拆小任务后复测，不把绕行作为合格完成。

对 MiniMax 的验收不能看 final response 自述。指挥官至少核验 diff、commit 是否在声明目标分支可 fetch、轻量验证命令是否真实存在、输出是否和任务范围匹配；遇到推测、遗漏、伪造证据或把失败写成成功时，先拆成更小任务或改派 GPT-5.5。

## GitHub Issue 和 PR 使用

GitHub issue 是长期需求、缺陷、阻塞和决策的 source of record。聊天上下文、Code Queue final response 和指挥简报可以帮助恢复现场，但不能替代 issue 中的可检索记录。指挥简报自身也按 issue 主体维护：#24 是兼容的长期入口，每日滚动简报可以使用标题形如 `YYYY-MM-DD 指挥简报（北京时间）` 的独立 issue。简报更新只改 issue 正文，不在评论区追加，且所有时间统一使用北京时间。

指挥官应在以下情况创建或更新 GitHub issue：

- 新需求需要跨多个 Code Queue task、跨服务或跨部署阶段推进；
- 运行中发现可复用的基础设施缺陷，例如 CLI 能力缺口、凭证注入缺口、runner 局部观测误导、部署路径不可达；
- 任务完成但缺少远端 commit、live verification、dev/prod 部署证据等验收闭环；
- 某个手动临时绕行暴露出长期产品化需求；
- 战略、流程、发布线或 CI/CD 规则发生需要后续任务遵循的决策。

issue 内容必须自包含，至少写清楚背景、外部收益、当前观察、需求范围、非目标、验收标准和关联任务。不要只贴聊天摘要或只写“见某任务”；Code Queue worker 可能看不到 issue，也可能无法访问完整历史，因此 issue 是人类和指挥官恢复全局态势的记录，不是 worker prompt 的替代品。

长任务和跨回合排障应把专题 issue 的评论区作为进展锚点。调查结论、细化方案、阶段性修复、rollout 状态、阻塞原因、复测 trace、最终验收和后续风险都应追加到同一个专题 issue 评论中，并引用相关 PR、commit、job、trace 或 runtime revision；正文只保留稳定背景、范围、验收标准和当前摘要，不写成每一步流水账。每次从上下文压缩、切换指挥官、resume 或中断恢复后，都必须先读取专题 issue 最新评论；只要任务已有或应有专题 issue，继续任何实质操作前还必须先写一条“恢复锚点”评论，说明当前北京时间、已完成内容、当前运行 / PR / commit / PipelineRun、剩余下一步和阻塞点。即使压缩摘要看起来完整、状态未变化或 agent session memory 可用，也不得跳过恢复锚点评论。写评论必须使用 `bun scripts/cli.ts gh issue comment create ... --body-file <file|->`，长正文不得用 shell 参数拼接。

如果某个 worker 任务需要依赖 GitHub issue 内容，但 runner 的 issue 可达性尚未被单独验证，指挥官不能默认 worker 已能读取该 issue。此时 worker prompt 必须直接内嵌完整需求、约束和验收点，issue URL 只能作为辅助引用。若要把 issue 作为任务输入源，先单独做可达性探测，再决定是否把 issue 作为常规前置条件。

### 长期总看板治理

`#20` 是指挥入口和当前态势摘要，不是全量 issue 仓库、历史流水账或验收直播页。它必须帮助指挥官在低上下文成本下判断当前最高约束、当前阶段、P0/P1 直达项、用户反馈和专题入口；具体证据、历史表格、完成记录和专题展开应放在归档 issue、专题 issue、每日指挥简报或对应业务 issue 中。

当总看板正文超过约一百二十行、正文体量接近或超过一万五千字符、OPEN/CLOSED 明细行超过四十行，或指挥官需要滚动很久才能看到当前重点时，应触发总看板瘦身。瘦身流程固定为：先用 `gh issue board-audit --board-issue 20 --dry-run` 记录旧正文长度、行数和 body SHA；再创建归档 issue 保存清理前完整正文；随后把 OPEN 项按业务域归纳成约四到六个专题 issue；最后替换 `#20` 正文，只保留当前指挥入口、当前阶段、P0/P1 直达表、用户反馈表、专题总表、每日简报索引、维护规则和归档入口。当前阶段表固定使用 `维度`、`当前判断`、`关键约束` 三列；用户反馈表必须包含百分比进度；专题总表必须包含 `承接入口` 和 `下一步重点`。已关闭事项和历史更新段不得继续留在 `#20` 正文中。

专题 issue 的职责是承接展开信息，不替代单个业务 issue。每个专题 issue 应写清范围、关联 issue、当前判断、主要阻塞、下一步推进方式和验收口径；专题 issue 只做归纳和入口，不应复制每个业务 issue 的完整历史。总看板中的专题总表只保留专题 issue、范围、当前状态、最高优先级项和下一步动作。

每日指挥简报必须独立成 issue，并由 `#20` 的简报索引引用。日内滚动记录、completed unread 审阅摘要、任务证据和历史更新都写入当日简报或对应 issue；不得在 `#20` 追加日期段落。若需要向用户展示近期指挥官工作情况，在 `#20` 的当前阶段区域放简短表格索引，不写长段流水。

每日或专题进展简报默认采用语义化写法，而不是 PR/commit 时间线复读。指挥官先按用户可理解的能力域归类，再用中文列表说明“完成了什么能力、解决了什么摩擦、对使用者有什么影响”；PR 号、commit、测试命令和 live revision 只作为证据补充，不作为正文主语。HWLAB v0.2 类工作常用三段是 `Code Agent 改进`、`device-pod 改进`、`基础设施改进`；其他项目应按真实工作内容选三到五个语义域。每段保留四到八条短句，优先描述当前可复用能力、体验变化、稳定性提升和仍需观察的风险，避免写成“几点几分合并某 PR”的流水账。若需要列出审阅发现或风险，把它们放在简报前后的独立小节，不能混入进展 bullet 冒充已完成成果。

`#20` 当前仍受 body profile 保护，正文必须保留 `## 看板（OPEN）` heading；该 heading 可用于承载紧凑的 P0/P1 直达表或当前活跃入口，不再要求恢复旧式 OPEN/CLOSED 全覆盖明细表。`gh issue board-audit` 只做只读结构审计，不再负责检查 GitHub open/closed issue 是否被表格完全覆盖；维护旧式表格时才使用 `board-row` 系列命令。

GitHub issue/PR 操作应优先使用 UniDesk CLI 的安全入口：`bun scripts/cli.ts gh auth status`、`gh issue list/read/view/create/update/comment create/comment update/comment edit/comment delete/close/reopen/scan-escape/cleanup-plan/board-audit/board-row list/board-row get/board-row update`、`gh pr list/read/view/create/update/comment create/comment update/comment edit/comment delete/close/reopen`。该入口默认 repo 是 `pikasTech/unidesk`，支持 `--repo owner/name`，输出稳定 JSON，并把 `missing-binary`、`missing-token`、`auth-failed`、`github-transient`、`network-proxy-failed`、`permission-denied`、`repo-not-found`、`repo-forbidden`、`issue-not-found`、`pr-not-found`、`scope-insufficient`、`validation-failed`、`invalid-response`、`unsupported-command` 等失败原因结构化。失败对象必须包含 `runnerDisposition=infra-blocked|business-failed`，runner 应用它区分基础设施阻塞和业务/参数失败。`github-transient` 专指 GitHub DNS 或 API 连接在收到 HTTP 状态前失败，例如 `Temporary failure in name resolution`、`Could not resolve host: github.com/api.github.com` 或 `error connecting to api.github.com`；它必须带 `retryable=true` 或等价 retry/backoff 指示，并且不是 `missing-token`、`auth-failed`、`scope-insufficient`、`validation-failed` 或 PR 语义失败。指挥官看到这类结果时，优先重试或退避；如果对应 Code Queue 任务 heartbeat/trace 仍新鲜，应保持任务运行并继续监督，不要立即 close/requeue 业务工作。runner 不应直接运行系统 `gh auth status` 并把输出贴入 Code Queue 日志；系统 `gh` 的 masked token 行仍会暴露 token 前缀和 scope 片段。需要验证当前 runner GitHub auth 时使用 `bun scripts/cli.ts gh auth status --repo pikasTech/unidesk` 或 `bun scripts/cli.ts codex pr-preflight --remote`，输出只能保留 token 是否存在、来源、长度和掩码，不得打印 token 值或 token 片段。Code Queue 输出层必须在保留 command output、trace、raw output 页面和 commander 摘要前 redaction `gh auth status` 风格 token 行，并给出 UniDesk CLI wrapper 提示。`gh issue list --state open --limit N --json number,title,state,closed,closedAt,url` 是有界 issue 发现入口，`--state` 只接受 `open|closed|all`，list 字段白名单是 `number,title,state,closed,closedAt,url,updatedAt,createdAt,author,labels`；未知 state 或未知字段必须失败，不能静默返回空数组。`gh issue view <number> --json body,title,state,closed,closedAt` 是 canonical 入口，`read` 只保留为兼容别名，正文仍应从 `.data.issue.body` 读取。单 issue/PR/comment 数字目标命令兼容 `--number N`，但成功响应必须带 `standardSyntaxHint` 提示标准位置参数写法；comment update/edit/delete 中的 `--number` 表示 commentId。未知 `--json` 字段必须失败，不得让调用方把空正文或缺失生命周期字段误判为读取成功。`gh issue scan-escape --limit N [--dry-run]` 与 `gh issue cleanup-plan` 只读扫描 issue body/comments 的字面量 `\n`、shell escape、短 body、blank/null body，输出 `classification=suspected-pollution|explanatory-mention|risk`、body/comment id、预览和清理建议；说明性提到 `\n` 不应被当成污染，cleanup-plan 永远不真实清理历史评论。`gh issue board-audit --board-issue 20 --limit N --dry-run` 只读审计目标 board issue 正文结构，返回正文长度、行数、body SHA、可解析 Markdown board sections、section 行数和 parser warnings；它不再拉取 GitHub open/closed issue 列表，也不再校验 OPEN/CLOSED 表覆盖关系。兼容字段 `missingOpenIssues`、`closedInOpenRows`、`missingClosedRows`、`rowValidationWarnings`、`ignoredIssues` 和 `recommendedActions` 仍保留为空数组或 0。显式 `gh issue update <number> --body-profile commander-brief` 可用于 #24 legacy 简报和每日滚动简报 issue；每日简报 issue 应用标题 `YYYY-MM-DD 指挥简报（北京时间）` 或在既有正文首行/关键 heading 中标明简报身份，且新正文必须包含 `## 常驻观察与长期建议`。对非简报 issue 使用该 profile 应失败为 `profile-issue-mismatch`。需要维护旧式 OPEN/CLOSED 明细表时，继续使用 `gh issue board-row list --board-issue 20 --state open|closed|all`、`gh issue board-row get <issueNumber> --board-issue 20` 和 `gh issue board-row update <issueNumber> --board-issue 20 --field progress|status|validation|branch|tasks|focus --value <text>`；`board-row update` 只替换一行一个单元格，输出 old/new row、body SHA、body guard 和 request plan，且默认 dry-run，正式写入必须带 `--expect-body-sha` 或 `--expect-updated-at`。字段映射中 `status`/`validation` 都指向 `验收状态`，`tasks` 指向 `相关 Code Queue 任务`，`focus` 指向 `当前关注点`；单元格管道会转义、真实换行会折叠为空格，避免新增字面量 `\n`。`gh issue board-row upsert` 可更新既有行或按 section 生成完整新行；`board-row add/move/delete` 已支持行级新增、OPEN/CLOSED 迁移和删除，全部默认 dry-run，正式 PATCH 必须带 `--expect-body-sha` 或 `--expect-updated-at`。`gh pr list --json ...` 支持 `body,title,state,number,url,author,head,base,draft,createdAt,updatedAt` 字段白名单；`gh pr read|view --json ...` 还支持 `stateDetail,closed,closedAt,merged,mergedAt,mergeCommit,headRefName,baseRefName,mergeable,mergeStateStatus,statusCheckRollup`。`stateDetail=open|closed|merged` 用于区分 REST `state=closed` 中的普通关闭和已合并；`closed*`、`merged*`、`mergeCommit` 和分支名字段都来自 REST。只有 mergeability/check rollup 需要请求 GraphQL，适合 PR 收口前判断可合并性和检查汇总。GraphQL 权限不足、网络失败、GitHub 仍返回 `UNKNOWN`/null、或需要 UniDesk CLI 尚未开放的官方字段、review/merge 操作时，回退系统 `gh` 只读观察或 GitHub UI；不要把缺失元数据当成已可合并。issue/PR 创建、更新、评论创建、评论编辑、评论删除、关闭和重开使用 GitHub REST API；只要有 `GH_TOKEN` 或 `GITHUB_TOKEN`，就不依赖系统 `gh` binary。`gh` binary 只作为状态探测和 `gh auth token` fallback，不是写操作的主路径。GitHub 不支持 issue/PR 硬删除，`gh issue delete` 和 `gh pr delete` 必须结构化返回 `unsupported-command`；生命周期删除语义使用 `close`。`gh pr merge` 是 guarded write：先执行 closeout preflight，只在 open、非 draft、无冲突、merge state CLEAN 且 checks 无失败/pending 时调用 GitHub REST merge；`--dry-run` 只输出计划不写远端。

需要按标题规范做去重时，不要只依赖 GitHub 全文搜索命中；例如 `[FEEDBACK]` 反馈池去重应使用 `bun scripts/cli.ts gh issue list --repo pikasTech/unidesk --state all --search "[FEEDBACK]" --title-prefix "[FEEDBACK]" --json number,title,state,url`。`--title-prefix` 的完整语义和 bounded scan 边界以 `docs/reference/cli.md` 为权威。

CLI 是短 shout 的需求原语，不是长驻服务器进程。CLI 功能不好用、兼容性不足、安全 guard 不够或输出不利于 runner/指挥官使用时，应默认创建 GitHub issue 并用 Code Queue 推进；这类 CLI 问题走 `master`、remote commit、语法/命令形态验证和文档更新，不套用 backend-core、Code Queue runtime 这类运行态服务的重部署门禁。除非用户明确要求，CLI 改动不做单元测试、合同测试或新增测试脚本。若 CLI 缺陷已经阻塞当前指挥，可以先做最小安全绕行，同时把长期修复写入 issue 并派单。

所有 GitHub Markdown 正文写入优先使用 `--body-stdin` 或 `--body-file <file|->`。不要使用 `gh issue comment --body`、`gh api -f body=...` 或把多行正文直接拼进 shell 参数；这些路径容易把真实换行、反引号和 Markdown 表格污染成字面量 `\n` 或 shell escape。从 shell 生成正文文件时使用 quoted heredoc，例如 `cat <<'EOF' > /tmp/body.md`，保证反引号和反斜杠不被展开；JSON 请求体场景优先使用对应 CLI 的 `--body-file` 或 `--body-stdin`，不要把长 JSON 塞进命令行参数。`gh issue comment create|update|edit` 和 `gh pr comment create|update|edit` 都支持 `--body-stdin` 作为多行 Markdown 的第一等入口，`--body` 仅适合短单行文本。`gh issue` 正文更新主入口仍是 `update --mode replace|append --body-stdin|--body-file`，`edit` 只是兼容别名；`append` 会先读取当前正文再追加文件字节，保留真实换行、反引号和 Markdown 表格，不走 shell 拼接。`gh issue update --body-file` 默认拒绝 `null`、空白和过短正文；#20 自动要求 `## 看板（OPEN）`，指挥简报 profile 自动要求 `## 常驻观察与长期建议`，并允许 #24 legacy 或每日滚动简报 issue。更新 body-only issue 前优先跑 `--dry-run`，查看旧/新正文长度、body SHA、关键标题、字面量 `\n` 和 shell 污染信号；正式写入长期正文时优先带上 `--expect-updated-at` 或 `--expect-body-sha`，避免旧缓存覆盖新正文。指挥简报更新正文时默认只写 GitHub issue，不自动向 ClaudeQQ 推送；#24 legacy 可用 `--notify-claudeqq-brief-diff` 通知 helper，如确需提醒用户，按本文的 ClaudeQQ 通知门槛单独发送。提交前或巡检时可用 `gh issue scan-escape --limit N --dry-run` 或 `gh issue cleanup-plan --limit N` 只读扫描污染并生成建议，不自动修复。

PR 是审查型交付入口，不是所有 Code Queue 任务的默认出口。UniDesk 默认集成目标仍是 `master`，但不再禁止任务分支；当变更风险高、跨模块、需要人工审查、或任务目标明确要求 PR 交付时，worker 可以创建 PR。PR 型任务必须报告源分支、目标分支、PR URL、关联 issue、测试证据和未完成风险。禁止把 PR 当成隐藏分支仓库；PR 分支必须来自最新目标线，保持小而可审查，并在合并后确认目标分支远端 commit 可 fetch。

PR handoff 的职责默认分开：runner 实现、测试、提交、push head branch 并创建 PR；指挥官监督并发、steer、审阅、确认 checks 和合并裁决。短期内 GPT-5.5 runner 如果收到明确 PR 收口授权，并且 PR 是普通 UniDesk source 变更、checks 满足任务要求、无冲突且不涉及 prod/runtime/release/security/database/破坏性回滚，可以自行用 repo-owned GitHub merge/close 路径完成收口并报告 SHA。高风险、边界不清、checks 失败或用户/指挥官保留 final action 的 PR 仍必须交回 commander 审查。host commander 也不把直接编辑业务代码当成常规 PR 替代路径。

PR 支持本身是 Code Queue 能力的一部分。当前 UniDesk CLI 支持 `gh pr list|view|create|update|comment create|comment update|comment edit|comment delete|close|reopen`，其中 create 需要显式 `--title`、`--base`、`--head` 和正文来源，update 需要显式 PR number、正文来源和 `--mode replace|append`，comment create/update/edit 需要显式 commentId 或目标 shorthand 和正文来源，且推荐使用 `--body-stdin` 或 `--body-file`。PR 收口观察应使用 `gh pr view <number> --json state,stateDetail,closed,closedAt,merged,mergedAt,mergeCommit,headRefName,baseRefName,mergeable,mergeStateStatus,statusCheckRollup` 获取普通关闭/已合并区分、merge commit、目标分支、源分支、mergeability 和检查汇总；该路径仍是只读元数据，不执行 merge，且 `closeoutMetadata.ok=false`、`missingOrUnknownFields` 或 GraphQL failure 都只能作为“需要人工复核/重试”的信号。`pr create --dry-run`、`pr update --dry-run` 与 `pr comment create/update/edit --dry-run` 只返回 planned operation，不创建 PR、不更新正文、不写评论；非 dry-run 创建前会校验 repo、base、head 和 compare ahead 状态，append 更新会先读取当前 PR body。`gh pr list` 不开放 mergeability/statusCheckRollup 列表字段，避免默认拉取 noisy/raw 状态汇总。`gh pr delete` 在 UniDesk REST CLI 中返回 `unsupported-command`，不能伪造硬删除；需要移除活跃 PR 时使用 `gh pr close`。`gh pr merge` 是 guarded REST write，没有 `--confirm` 可以绕过 preflight；获得收口授权的 GPT-5.5 runner 可使用 UniDesk `gh pr merge`、GitHub UI 或等价 repo-owned GitHub merge path 处理普通 PR，并报告结果 SHA。需要 PR 交付时，prompt 必须明确允许的人工、runner 或后续工具路径，并报告未覆盖范围。

### PR 驱动派单模板

PR 驱动是 Code Queue 协作的未来默认方向：worker 在独立 head branch 上提交，创建面向目标分支的 PR，指挥官审查后再合并并更新 issue/#20/#24。当前仍处于 runner GitHub 可达性补齐阶段；在 #19 的 runner GitHub 可达性未验收前，派单 prompt 必须自包含完整需求、约束、写入范围和验收标准，不能只贴 GitHub issue 链接。issue URL 只能作为辅助引用。

PR 型派单 prompt 至少包含以下字段：

- `目标 issue`：写明 issue 编号、URL 和本次任务要关闭或推进的验收点；不要假设 runner 能读取 issue。
- `目标分支`：明确 `master` 或经批准的维护分支；普通开发集成使用 `master`。
- `head branch`：使用可追踪命名，例如 `code-queue/issue-35-pr-dry-run-probe`、`code-queue/issue-<number>-<short-topic>` 或包含 task id 的等价短名；head branch 必须从最新 `origin/<目标分支>` 创建。
- `禁止动作`：禁止直接 push 目标分支；除非 prompt 明确授予普通 PR 收口权，否则禁止 merge PR；禁止改 release/v1 运行态服务，禁止输出 token，禁止跑本任务未要求的重型 check/e2e/Playwright。
- `必须动作`：提交前运行轻量自测；push head branch；创建面向目标分支的 PR；PR body 写清关联 issue、修改文件、验证命令和风险；若创建 PR 前需要探测，先运行只读或 dry-run preflight。
- `final response 字段`：实际分支、目标分支、head branch、PR URL、远端 head commit、是否已创建 PR、merge/close 状态和 SHA 或未 merge 原因、修改文件、验证命令和结果、遗留风险；如果 PR 未能创建，报告结构化原因和 runnerDisposition。

PR 型 prompt 可直接嵌入以下 Git 指令约束：

```text
Git/PR 交付要求：
- 目标分支：master。
- 从最新 origin/master 创建 head branch：code-queue/issue-<number>-<short-topic>。
- 不得直接 push master 或 release/v1。
- 必须 push head branch 并创建 PR 到 master；除非本 prompt 明确授权普通 PR 收口，否则不得 merge PR。
- 创建 PR 前先运行只读/dry-run preflight，确认 GH_TOKEN/GITHUB_TOKEN、GitHub egress 和 repo 可见性，不得打印 token。
- final response 必须报告 head branch、PR URL、远端 head commit、修改文件、验证命令、merge/close 状态和 SHA 或未 merge 原因。
```

GPT-5.5 PR/收口类 prompt 由指挥官在提交前直接审查。legacy `codex submit` 已冻结，新任务 payload 只走 AgentRun `create/apply` 资源原语；不得再把额外本地审查命令当成派单 admission、业务 PR 门禁或生产风险豁免依据。

Runner preflight 优先使用执行面诊断入口：

```bash
bun scripts/cli.ts codex pr-preflight --remote --issue 20
```

`codex pr-preflight --remote` 的 `auth-missing` 只表示 scheduler/runtime preflight surface（`scheduler-runner-env`）没有看到 `GH_TOKEN/GITHUB_TOKEN` 或 auth-broker，不得被简化成“当前 active runner/dev container 不能创建 PR”。默认输出必须优先给出有界的 `authScopeSummary`、`scopeBoundary`、`activeRunnerDevContainer` 和 `recommendedActions`：`authScopeSummary` 用一句话说明 scheduler auth missing 只是 scoped finding；`scopeBoundary` 明确 scheduler env 与当前 CLI/dev container 是独立 scope；`activeRunnerDevContainer` 只报告当前 CLI 进程是否看见 token，且不打印 token 值；`recommendedActions` 保持低噪声，先给 active task 内的 `bun scripts/cli.ts gh auth status --repo pikasTech/unidesk` 和 `gh pr create --dry-run`，再给 scheduler 侧长期的 auth-broker 或 runtime secret 修复。指挥官看到 remote preflight `auth-missing` 时，应继续用当前 runner 内的 `bun scripts/cli.ts gh auth status --repo pikasTech/unidesk`、`gh pr create --dry-run`、`gh pr comment create --dry-run` 验证实际 PR 能力；只有这些 active runner 检查也失败时，才能把它判成当前 turn 不能 PR。

该命令经 backend-core 稳定 `code-queue` proxy 访问 D601 scheduler 的 `/api/runtime-preflight`，报告 scheduler/runner 环境里的 `GH_TOKEN`/`GITHUB_TOKEN` 覆盖、工具、Git worktree、GitHub egress、repo/issue/PR 只读探测和可选 push dry-run。需要复核 PR body/创建命令 guard 时追加 `--pr-create-dry-run --pr-create-dry-run-head <head>`；该 guard 只执行 dry-run，不创建 PR。缺少 env token 时必须返回 `ok=false`、`runnerDisposition=infra-blocked`、`tokenCoverage.missing=["GH_TOKEN","GITHUB_TOKEN"]` 和 `authBroker.source="broker/auth-broker-needed"`，因为 provider dev container 只能转发 scheduler 已经拥有的 token，除非后续接入 broker-held GitHub credential。GitHub DNS/API 瞬时连接失败必须返回 `failureKind=github-transient`、`degradedReason=github-dns-api-transient`、`retryable=true` 和低噪声 `githubTransient.failedProbes` 摘要；这与 `auth-missing`、`git-remote-gap`、`proxy-gap`、`validation-failed` 或 PR 语义失败分开处理。系统 `gh` binary 缺失只能作为 `tools.systemGhBinary.ok=false` 观测，不得把它误判为 UniDesk REST `bun scripts/cli.ts gh` 不可用。`--remote` 在 runner-like 环境里不再要求本地 `unidesk-backend-core`、`unidesk-database`、`baidu-netdisk-backend` 容器存在；这些本地 target stack 缺失只作为证据，不是最终主阻塞，并应额外标成 `blockingDisposition=runner-local-observation-gap` 或 `localObservationGap.kind=runner-local-observation-gap`。若远程控制面可达，输出继续保留 ready preflight；若远程控制面不可达，结构化失败归类为 `failureKind=control-plane-missing` / `degradedReason=remote-control-plane-unreachable`，并额外标成 `blockingDisposition=control-plane-observation-gap`。`runnerDisposition` 可以为了旧调用方兼容继续保持 `infra-blocked`，但 observation-gap 字段才是判断“观测路径缺口，不是 scheduler 停摆”的稳定口径。输出中的 `prCapabilityContract` 用于指挥官快速审查 runner handoff：目标分支固定显示、push/PR create dry-run 标记为不写远端、系统 `gh` binary 与 UniDesk REST `bun scripts/cli.ts gh` 可用性分开报告，且 merge 能力必须指向 guarded `gh pr merge --dry-run` 预检路径。

本地 runner preflight 示例：

```bash
bun scripts/code-queue-pr-preflight-example.ts --repo pikasTech/unidesk --base master --head code-queue/issue-35-pr-dry-run-probe --comment-pr 1
```

该脚本只读调用 `gh auth status`，并执行 `gh pr create --dry-run` 与 `gh pr comment --dry-run`。它检查当前 shell 的 `GH_TOKEN/GITHUB_TOKEN` 是否存在、GitHub REST egress 是否可达、repo 是否可见，并且只输出 token 来源和存在性，不输出 token 值。它不能证明 Code Queue default scheduler 已注入 token；跨 queue 派单 admission 应使用 `codex pr-preflight`。

### Runner Skill 可用性

D601 Code Queue runner 的长期 skills source of truth 是宿主 `/home/ubuntu/.agents/skills`，生产和 dev Code Queue Pod 都必须只读挂载到容器内 `/root/.agents/skills`，并设置 `UNIDESK_SKILLS_PATH=/root/.agents/skills`。provider dev container 由 scheduler 通过 Docker 启动时，也必须把同一宿主 source 只读 bind 到同一 target，并把 `UNIDESK_SKILLS_PATH` 显式传给 Codex/OpenCode 进程。target 缺失时即使 approved source 可读也不能 fallback 给 runner；health/preflight 必须标记 `runnerUsable=false`、`contractOk=false`、`resolvedPathSource=missing`、`degradedReason=skills-target-missing` 与 `resolution.hostRolloutRequired=true`。不要使用或传播任何拼错的 skills 路径；如果配置的 source 或 target 命中拼写错误路径，health/preflight 必须直接返回 `blocker=forbidden-skills-path-configured`，并在 `pathSpelling.forbiddenPathConfigured=true` 与 `pathSpelling.forbiddenPathRoles` 中标明是 source、target 或两者，而不是降级成普通 missing path。

执行面 `/health`、`/api/dev-ready` 和 `/api/runtime-preflight` 必须输出同一份只读 skill availability report。稳定字段包括 `source`、`target`、`resolvedPath`、`resolvedPathSource`、`resolution`、`requiredSkills`、`missingSkills`、`sourceSkillCount`、`targetSkillCount`、`degraded`、`degradedReason`、`blocker`、`pathSpelling` 和 `valuesPrinted=false`。`requiredSkills` 至少覆盖 `docs-spec`、`cli-spec`、`frontend-design` 与 `playwright-cli`；如果 source 与 target 都缺失、必需 skill 均不可用、拼写错误路径被配置或拼写错误路径已存在，报告必须显示 `ok=false` 和结构化 `blocker`，不能把 runner 能力缺口伪装成业务任务失败。target symlink 到 approved source 属于可接受的兼容修复，必须显示 `resolvedPathSource=target-symlink` 和有界 skill count。

`codex pr-preflight --remote` 默认视图必须保留同一份可操作 `skillsContract`，不能只给出模糊的 `skills-target-missing`。稳定字段包括 `source`、`target`、`resolvedPath`、`resolvedPathSource`、`requiredSkills`、`missingSkills`、`sourceSkillCount`、`targetSkillCount`、`sourceMissingSkills`、`targetMissingSkills`、`hostRolloutRequired`、`degradedReason`、`blocker`、`repairHint`、`pathSpelling` 和 `valuesPrinted=false`。当 `/api/runtime-preflight` 的旧 `skills` report 缺少 `resolution` 或 counts，但 `skillsSync` 已证明 approved source 可读且 target 未投影时，CLI 必须从 `skillsSync` 合成同一份 `skillsContract`，并显示 `hostRolloutRequired=true` 与修复指令。`--full` 或 `--raw` 可以展开完整 `skills`、`skillsSync`、tool 和 transport 观测；默认输出仍保持低噪声，只保留指挥官能直接判断和恢复的字段。

执行面还必须提供 dry-run skills sync/preflight 合同：稳定入口是 `GET /api/skills-sync?dryRun=1`，CLI 入口是 `bun scripts/cli.ts codex skills-sync --dry-run [--full]`。该合同只描述受控 hostPath 生命周期，不复制文件、不从任意路径静默加载、不重启服务、不 rollout Pod、不读取 Secret。默认输出保持紧凑，必须报告 source、target、expected env/mount、required skill 列表、source/target skill counts、missing source/target skills、permission failure count、plannedActions 和修复指令；逐 skill 细节、完整 permission failure 和原始报告只能通过 `--full` 显式展开。非 dry-run 请求必须失败。

受控生命周期是更新宿主 `/home/ubuntu/.agents/skills` 这一 approved source，然后让生产和 dev Code Queue Pod 通过 manifest 中的 read-only hostPath 挂载读取 `/root/.agents/skills`；provider dev container 还必须通过启动脚本把同一 source bind 到同一 target。在线热更新只能作为临时恢复手段，长期验收必须以 manifest/source-of-truth、runner container bind、dry-run sync surface 和结构化 health/preflight 为准。需要验证时优先运行：

```bash
bun scripts/cli.ts codex skills-sync --dry-run
bun scripts/cli.ts codex pr-preflight --remote --issue <issue-number>
```

指挥官审查 checklist：

- PR base 是声明的目标分支，head branch 命名可追踪，远端 head commit 可 fetch。
- diff 只覆盖派单 ownership，未混入 release/v1 运行态服务或无关 dirty worktree。
- PR body 和 final response 都包含关联 issue、修改文件、验证证据、未完成风险和 merge/close 状态。
- contract/dry-run 证据覆盖本次 PR 能力：`pr create --dry-run`、`pr list/view`、`pr comment --dry-run` 和 `pr merge --dry-run` guarded plan；若 runner 被授权最终 merge/close，还要报告使用的 repo-owned GitHub 路径和结果 SHA。
- 没有 token、凭证、临时日志或构建产物进入 commit、PR body 或评论。
- 未授权 runner 收口的 PR 由指挥官审查并决定是否 merge；已授权 runner 收口的普通 PR 在合并后仍要验证目标分支远端 commit 可见，并按态势更新 issue/#20/#24。

### Runner Resume 收口

PR 小修、冲突、rebase、补测和 reviewer feedback 的新执行入口是 AgentRun 资源原语。仍在 AgentRun session 内的工作只使用 `bun scripts/cli.ts agentrun send session/<sessionId> --prompt-stdin`；已沉淀成新工作项时使用 `bun scripts/cli.ts agentrun create task --aipod Artificer --prompt-stdin` 或 `agentrun apply -f -`。旧 `codex resume` 已冻结，不再作为 follow-up 入口。

旧 Code Queue task 只保留历史审阅和残留停止；需要基于旧任务产出继续推进时，在 AgentRun payload 中显式引用旧 task id、PR/branch 和审阅结论，而不是把旧 task 重新入队、resume 或 double-write。

AgentRun turn 的 timeout 监督按无响应空闲时间处理，而不是固定 wall-clock `backend-timeout`。只要 result/session liveness 的 `lastActivityAt`、`lastActivitySeq` 或 events 仍在刷新，指挥官应继续轮询，不应 interrupt、重派或判定 backend 死亡。若 command 因 idle timeout、provider stream disconnect、runner stdio inactive 或其他非业务终态停止，指挥官本人必须先读 `result`、`events` 或 `logs/trace`，确认最后有效工具输出、已完成修改、失败原因和下一步，再把这个摘要作为后续 prompt 发送给 Artificer；不能要求 Artificer 自己去猜旧 trace，也不能因为一次 timeout 就停止整个交付。

Artificer 默认应携带可续跑 `sessionRef`。仍有 `sessionId` 的 follow-up、补测、reviewer feedback 和 timeout 恢复，只使用 `bun scripts/cli.ts agentrun send session/<sessionId> --aipod Artificer --prompt-stdin` 继续同一个 session；只有历史任务没有 `sessionRef`、session 已 evicted、或同 session 已证明不可恢复时，才创建新 AgentRun task。新 task 必须在 prompt 中写明“这是基于旧 task/trace 的 manager-read continuation”，并记录旧 task/run/branch、管理者读 trace 得出的当前状态和下一步。

replacement runner 只用于方向明显错误、质量不可接受、原 task 上下文不可恢复、原分支/PR 已废弃，或 AgentRun 同 session `send` 已证明无法继续的情况。关闭或替换旧 PR 时必须在 PR/body/final response 中说明 superseded/replacement 关系，避免 competing branch 扩散。

## 监控

指挥官必须用 task 级和 queue 级证据监控 Code Queue，不能只看单一状态字段。

常用入口：

- `bun scripts/cli.ts codex tasks --view commander --limit N`：host commander 轮询的推荐入口。输出是有界 action map，必须直接显示 `activeRunners.count`、计数来源、split-brain/heartbeat 处置、queued/retry_wait 精确计数、terminal-unread 总数和已省略行数、active 风险数、stale/heartbeat/trace gap、`finalResponse` 已出现但仍非终态的 awaiting terminal/judge、blocker-like final response、HWLAB#7/#99/#116/#164/#317 与 UniDesk#20/#118 命中、任务分类和下一步 drill-down 命令。默认不得输出完整 prompt、完整 final response、raw output、完整 trace 或 raw overview；需要详情只能按 task id 使用 `codex task`、`codex task --trace`、`codex output`、`codex read` 或 `rawOverview` 命令渐进展开。
- `bun scripts/cli.ts codex tasks --view supervisor --limit N`：查看旧 Code Queue 历史默认低噪声监督视图，包括 `activeRunning`、running、完成未读、少量最近完成、queued/runnable、activity、commanderConcurrency、execution diagnostics、任务分类和下一步 drill-down 命令。默认行只保留 task id、队列、短 prompt/body 预览和原始字符数；`--limit` 是扫描/分页预算，不是返回几十条肥行的开关，CLI effective limit 安全上限为 100，输出必须用 `filters.requestedLimit`、`filters.effectiveLimit`、`filters.limitCapped`、`source.requestedLimit` 和 `source.effectiveLimit` 区分用户请求、CLI cap 和 overview 源拉取预算。新任务派发和 follow-up 不再使用旧 `codex submit/resume/steer`，统一走 AgentRun 资源原语。
- `bun scripts/cli.ts codex queues`：默认是 commander-first 队列态势摘要，`--commander` 是显式同义开关。输出前部固定使用 `.data.queues.commander`，先给出 `activeRunnerCount`、`source`、`target=15`、`slotDeficit`、`queuedCount`、`runningTasks`、`heartbeat.fresh`、`heartbeat.risk`、`heartbeat.staleRecoveryCandidates`、active/runnable queue 小页和 drill-down 命令；历史 queue item 列表保留在 `.data.queues.items[]`，但只是分页的次要行。需要完整队列行视图时加 `--full`，但 `--full` 仍默认分页，继续用 `--limit N`、`--page N` 或 `--offset N` 渐进展开。summary 和 full 都使用稳定 JSON path `.data.queues.items[]` 读取队列行，并从 `.data.queues.commander`、`.data.queues.commanderConcurrency`、`.data.queues.activity`、`.data.queues.counts` 与 `.data.queues.executionDiagnostics` 读取全局活跃计数和执行诊断；完整 upstream 只通过输出中的 raw command 显式获取。若 `/api/queues` 没有返回 task row，`runningTasks.items[].name` 会是 `null` 且 `nameSource=not-returned-by-api-queues`，此时按返回的 `codex task <taskId>` 或 supervisor 命令展开，不要假设任务没有名称。
- `bun scripts/cli.ts codex execution-plane [--full|--raw]`：只读巡检 D601 原生 k3s `unidesk` namespace 下的旧 Code Queue 执行面。该命令用于历史归档和残留任务诊断，不作为新任务能力门禁；新任务真实运行面验收走 AgentRun `v0.1` queue/session 原入口。默认不打印完整 Kubernetes Deployment JSON、环境变量全集、SecretRef 值或命令 stdout；需要逐项展开时使用 `--full`，需要安全裁剪后的原始观察对象时使用 `--raw`。
- `bun scripts/cli.ts codex unread --limit N`：查看完成未读审阅积压的默认 triage，按 repo、issue、status 和 queue 汇总，并给出有界最新任务紧凑行；默认行只包含 task id、状态、queue、issues、updatedAt/finishedAt 和一条 `nextStep`，不重复每任务 `show/detail/trace/output/read` 命令，也不输出 raw prompt、final response、trace 或 output。完整 per-task 命令必须显式使用 `codex unread --full`、`codex unread --view full`、`codex unread list` 或单任务 `codex task <taskId>`/`codex read <taskId>` 展开；默认输出必须保留一次性的模板命令和分页命令。
- `bun scripts/cli.ts codex unread mark-read --repo owner/name --issue N --limit N --confirm`：批量已读入口，必须显式 `mark-read` 和 `--confirm`，否则结构化失败且不 POST `/read`。
- `bun scripts/cli.ts codex tasks --unread --limit N`：兼容查看完成未读审阅积压；`--unread` 与 `--unread-only` 等价，不能被静默忽略。
- `bun scripts/cli.ts codex tasks --status succeeded --unread --limit N`：按具体终态过滤监督结果；不支持的 status filter 必须显式失败，不能扩大为未过滤结果。
- `bun scripts/cli.ts codex task <taskId>`：默认只查看原始 prompt、最终 response、最后错误和 drill-down 命令，这是完成未读任务审阅的第一步。
- 当默认审阅摘要不足时，再逐级使用 `bun scripts/cli.ts codex task <taskId> --detail`、`bun scripts/cli.ts codex task <taskId> --trace --limit N` 或 `codex output`。
- `bun scripts/cli.ts agentrun send session/<sessionId> --prompt-stdin`：对 AgentRun 中仍可继续的 session 追加修正；服务端按运行状态决定内部 `steer` 或新 `turn`，旧 `codex resume` 已冻结。
- 当 master 控制面状态和 D601 scheduler 状态看起来分裂时，使用 `docs/reference/observability.md` 中的活性规则判断。

默认 commander/supervisor 视图必须保持低噪声。commander 视图用于回答“现在需要处理什么”，supervisor 视图用于看分区小页和红线细节。commander 的 `activeRunners.count` 是指挥官 active runner 计数，supervisor 的 `activeRunning.count` 是 running+judging 状态计数；两者都必须标明 exact/source，不能把返回行数当成并发总数。`activeRunning.count` 来源是 queue summary 的 status counts 时 `activeRunning.exact=true`，用于 redline 判断；`activeRunning.rowPage.returned` / `running.returned` 只表示本次返回的紧凑任务行。`activeRunning.redline` 必须写明 `countField`、routine target、burst redline、hard redline、`state` 和 `decisionReady`；只有 `decisionReady=true` 时，才能直接用该 count 做红线/补派判断。commander 的 `attention.items` 只返回最需要处理的有界任务，`attention.total/returned/omitted` 必须保留省略计数；`sections.recentCompleted` 不得重复 `sections.terminalUnread` 的未读终态。`running`、`completedUnread` 和 `queued` 即使传入较大的 `--limit`，默认也只返回一个很小的有界页，并通过 section `commands.next` 继续分页；`--limit` 保留为扫描/分页预算和 full view 返回预算，不得让一次 commander/supervisor 调用输出几十条肥行。每个任务行只应带 task id 和必要摘要，`show`、`detail`、`trace`、`output`、`full`、`read` 使用 section template 或 row commands 表达，让下一步渐进披露动作明确且不重复；默认不得嵌入完整 queue 列表、完整 final response、raw output 页或完整 trace 行。`recentCompleted` 必须默认限量，且不得重复 `completedUnread` 里的未读终态，避免完成历史把当前 running、阻塞和未读审阅挤出视野；需要完整当前页时显式使用 `--view full`。`executionDiagnostics` 只能展示有界 task-id/reason 预览、总数、截断标记和 omitted counts；需要全量诊断时使用输出中的 raw command。`commands.read` 只是在人工审阅后的建议命令，listing 命令绝不能自动执行。

commander 视图的任务分类必须是确定性字段，至少区分 `user-facing`、`cd-artifact`、`infra-governance`、`noise-report`、`workflow`、`infrastructure-blocker` 和 `unknown`。`infrastructure-blocker` 只能由强基础设施故障信号触发，例如 storage/PostgreSQL degraded、provider/k3s/proxy/auth 等基础设施上下文同时出现 blocked/failed/unreachable/timeout 等阻塞信号；普通 prompt 中的 runner、CLI、commander、supervisor、治理或历史任务上下文不得单独升级为 blocker，没有把握时使用 `workflow` 或 `unknown`。分类只用于监督优先级和噪声折叠，不替代任务验收；当 final response 带 blocker-like 语言、failed/terminal-unread、heartbeat/stale risk、trace gap 或 awaiting terminal/judge 时，分类再低噪声也必须进入 attention 或风险计数。

`codex tasks` 中的 `status` 永远是 scheduler/control-plane 原始状态，不因为看到 worker final response 而改写。若某个非终态任务的最后 assistant 文本来自 `finalResponse`，CLI 会额外显示 `statusLabel`、`awaitingTerminalJudge=true`、`closeoutState=awaiting-terminal-or-judge` 或 `awaiting-judge`，并附带 closeout hint。指挥官应把这类行理解为“worker 已经产出最终回复文本，但 Code Queue 还在等待 agent terminal event、scheduler 写回或 judge 结果”；它仍占用 active/running 监督窗口，不能按完成任务 `read` 或验收，直到 `status` 进入 `succeeded`、`failed` 或 `canceled` 并可审阅 judge/terminal 记录。

这条规则直接服务 HWLAB #132：指挥官要优先看到真实业务推进、部署修复、阻塞和需要人工审阅的未读结果，Gate/报告/审查/诊断类任务只能作为折叠的分类信号存在，不能在默认输出中用长 prompt/body 抢占上下文。

完成未读任务的审阅也必须遵循渐进披露。指挥官默认只拉取原始 prompt 和最终 response，用它判断任务是否声称完成、是否有明显越界、是否缺少验收证据；不要默认拉完整 trace、全量 tool summary 或 raw output。`codex task --detail` 也是有界摘要，只提供少量 attempt/tool 行和短文本预览；需要完整证据时再继续展开 `--detail --full --tool-limit N`、分页 `--trace`，或按 seq 读取 `codex output`。`codex output` 默认仍会限制返回行数和单条文本预览；只有明确使用 `--full-text` 且选定 seq window 时才读取该页全文。只有当 final response 与目标不一致、证据不足、远端 commit 无法验证、任务疑似造假、或需要追溯失败原因时，才进入这些展开路径。这条规则的目标是降低上下文压力，同时保留通过多步查询拿到完整证据的能力。

队列诊断中的 `split-brain` 表示控制面/执行面观测分裂，不自动证明任务已经死亡。只要任务 heartbeat 还在刷新、trace 仍在推进，就不能把它判成服务中断或要求立刻 stop；应把它视为 `splitBrainLive=true` 的 live 任务，继续监督并推进 #20 里的已排任务，而不是 interrupt、替换或把 backend 当成已经挂掉。队列摘要应显示 `effectiveLiveness=live`、`splitBrainLive=true` 和 `recommendedAction=continue-supervision`；compact 输出还应在 `executionDiagnostics.liveness` 中重复这些低噪声字段，并突出 `activeHeartbeatCount`、有界 `heartbeatFreshTaskIds`、`databaseActiveTaskCount` 和 `schedulerActiveRunSlotCount`。当 master/control-plane 的 `schedulerActiveRunSlotCount=0` 但 `heartbeatFreshTaskIds` 非空时，active 数应优先按 scheduler heartbeat 摘要解释为 live，而不是按 master 本地 slot 0 解释为执行停摆。只有 heartbeat expired/missing 或满足 stale-recovery 条件时，才应显示 `effectiveLiveness=at-risk` 并进入恢复判断。

旧 Code Queue 的 bounded snapshot 只作为历史监督证据，不再作为新派单或恢复判据。新任务派发后应通过 `bun scripts/cli.ts agentrun get tasks --queue commander --limit 20`、`describe task/<taskId>`、`events run/<runId>`、`logs session/<sessionId>` 和 `result run/<runId> --command <commandId>` 观察 AgentRun 队列、run 与 session。

默认 supervisor poll 也遵循同一低噪声语义：heartbeat expired/missing、`heartbeatRiskTaskIds` 和 `staleRecoveryCandidateTaskIds` 必须可见，但第一次 poll 只表示 `transient-needs-repoll`，`activity.recovery.hint` 应为 `re-poll supervisor before recovery`。只有 repeated poll 仍确认 owner heartbeat expired、scheduler local no active run、database-active task 仍存在，并且输出显式带 `repeatedPollConfirmed=true` 或 confirmed stale candidate，才允许进入 bounded dry-run reconcile；真实恢复仍受高风险边界约束。

stale-active 恢复和 `/api/scheduler/reconcile?staleMs=...` 诊断入口的 heartbeat stale 阈值必须按安全下限归一化：缺省和低于默认 5 分钟的值都按 5 分钟处理，过大值按 24 小时上限截断，并在结构化响应中返回 `requestedStaleMs*`、`staleMsAdjusted`、`staleMsAdjustmentReason`、`minStaleMs` 和 `maxStaleMs`。任何 `staleMs=0` 或过低阈值都不能把仍有 fresh scheduler heartbeat 的任务判成 stale/recoverable。

`codex queues`、`codex tasks --view commander` 和默认 supervisor 视图的 `activity` / `commanderConcurrency` 是指挥官并发治理的主读数。并发决策固定使用 `commanderConcurrency.activeRunnerCount`、`.data.queues.commander.activeRunnerCount` 或 commander `activeRunners.count`，它等于 `activity.effectiveActiveTaskCount`；15 并发策略的可补窗口按 `15 - activeRunnerCount` 计算，CLI 也会直接给出 `.data.queues.commander.slotDeficit`，不能用 `activeQueueIds.length` 或 scheduler-local slot 数替代。`effectiveActiveTaskCount` 表示用于调度判断的有效活跃任务数；`databaseRunningTaskCount` 来自 PostgreSQL 中 `running` 状态计数；`databaseActiveTaskCount` 覆盖 running/judging 等数据库活跃任务；`heartbeatFreshActiveTaskCount` 表示 heartbeat-fresh 的有效 runner 数；`schedulerLocalActiveQueueCount` 和 `schedulerLocalActiveRunSlotCount` 只表示当前控制面本地可见 active run slots。`activeQueueIds` 与 `activeQueueCount` 是 scheduler-local 字段，可能在 `counts.running>0` 且 heartbeat 新鲜时为 0；看到这种组合时应按 `activity.effectiveActiveTaskCount`、`activity.heartbeatFreshActiveTaskCount`、`.data.queues.commander.runningTasks` 和 `splitBrainLive` 决策，不得把空 `activeQueueIds` 当作零并发或停摆证据。`commanderConcurrency.splitBrainDisposition=live-count-as-active` 表示 split-brain 仍是 live 且应计入 active runner；`attentionRequired=true` 表示需要人工看一眼或重新 poll，`interventionRequired=true` 才表示当前输出已经足以进入高风险介入路径。单次 heartbeat risk、stale recovery candidates 或 `recommendedAction=investigate-heartbeat-risk` 应先落到 `attentionRequired=true` 加 `re-poll supervisor before recovery`，不得直接等价为恢复授权。

单次 `provider is not online`、SSH 超时、proxy 超时或 registry 请求失败只能证明“当前观察路径失败”，不能单独升级为 D601 全局离线、CI/CD 全局阻塞或业务任务不可推进。指挥官和 runner 必须用多信号裁决运行面状态，至少区分以下观察面：

- backend-core 节点视图和 provider heartbeat，例如 `debug health` 中的 D601 `status`、`lastHeartbeat` 和 gateway 版本；
- Host SSH / WSL SSH 维护桥，例如 `trans D601 hostname` 或短 argv 命令；
- D601 artifact registry health、k3sctl-adapter health、目标 microservice health；
- Code Queue scheduler heartbeat、任务 heartbeat、trace/output 是否持续入库；
- 当前 runner 容器内 CLI/proxy 路径是否只是局部不可达。

只有多个独立观察面同时失败，或同一关键路径在明确时间窗口内持续失败，才能把问题判为全局阻塞。否则应记录为 transient、`runner-local-observation-gap`、`external-provider-backoff` 或 `control-plane-observation-gap`，优先重试、steer 任务纠偏或拆出基础设施 follow-up；不得让业务 worker 把单次局部失败作为最终 blocker。CLI 和 runtime 必须把错误输出结构化为 `scope=runner-local|external-provider|control-plane|provider-gateway|ssh|registry|k3s|scheduler|service-proxy`、`observedAt`、`retryable`、`decision` 或 `blockingDisposition`、`healthyScopes`、`failedScopes` 和建议的交叉验证命令。当前 runner/local backend-core 容器缺失属于 runner-local observation gap；远程控制面也不可达属于 control-plane observation gap；两者都不能单独写成 active runner 数归零或 scheduler 停摆。

ClaudeQQ 是面向用户的主动提醒通道，不是 #24 简报更新的自动转发器。指挥官只应在三类情况下自主发送 ClaudeQQ 消息：核心服务或关键执行面宕机且需要用户知情，高风险决策需要用户请示，或出现里程碑式进展值得同步。消息必须简明扼要，一次不超过 200 个中文字符，写成一段话，不使用 Markdown 语法。普通轮询、普通 issue 更新、普通 #24 简报追加、外部 token provider 正常限流、以及无用户动作要求的中间状态，不发送 ClaudeQQ。发送失败只记录到 #24 或对应 blocker issue，不回滚已经完成的 GitHub issue 更新。高风险审批通知不得走本机 ClaudeQQ skill、powershell 或本地 server；repo-owned 路径是先用 `bun scripts/cli.ts commander approval request --action <action> --dry-run [--task-id id] [--reason text]` 生成草案，获得授权后才使用 backend-core proxy 命令 `bun scripts/cli.ts microservice proxy claudeqq /api/push/text --method POST --body-json '<payload>' --raw`。

重启 Code Queue backend、重建 Code Queue backend 容器、重启 Code Queue 执行面，或对运行中 Code Queue 任务执行 interrupt/cancel 这类会改变执行状态的操作，都属于高风险干预。即使看起来是最小恢复动作，指挥官也必须先通过 ClaudeQQ 向用户上报原因、影响范围和拟执行动作，并等待用户明确同意；未获得同意前只能做只读诊断、记录 issue、更新看板和准备恢复方案。

host Codex 指挥官正规化后仍受同一条高风险边界约束。`docs/reference/host-codex-commander.md` 中的直管微服务只能把 host Codex 保活、SSH/PTY/stdio bridge、prompt plan、trace summary、#20/#46 issue 入口和 ClaudeQQ 审批记录产品化；它不是 Code Queue runner，也不是 Code Queue 自部署通道。第一阶段 `bun scripts/cli.ts commander ...` 只允许输出 contract/dry-run 计划，不得实际重启 backend、interrupt/cancel task、读取 token 明文、打开 bridge 或发送 ClaudeQQ。若 dry-run 返回 `notification-path-unavailable`，这是正式发送未开放的 blocker；指挥官应记录到 issue/#24，并使用输出里的 backend-core proxy command 作为后续授权后的唯一候选命令。

当多信号裁决显示 provider 服务器、D601 执行面或关键维护桥疑似需要人工检查时，指挥官可以在更新 #24/#40 等记录之外，通过 ClaudeQQ 额外提醒用户检查 provider 服务器状态。提醒只在首次确认、状态恶化、恢复或需要用户介入时发送，不能在每轮轮询中重复轰炸。ClaudeQQ 提醒是 best-effort：若 ClaudeQQ 本身依赖同一条故障 provider/k3sctl 链路而不可达，指挥官应把通知失败的原因写入 #24 或对应 blocker issue，并继续按轮询和恢复规则推进。

在 UniDesk CLI 中，`bun scripts/cli.ts provider triage <providerId>` 是只读多信号裁决入口，适合作为 worker 和指挥官的统一健康判断前置。它必须至少保留这些合同：默认输出只展示裁决、scope、失败/降级/未知信号和有界 evidence 摘要，完整 evidence 必须显式加 `--full` 或 `--raw`；`provider is not online` 这类单路径失败只应落到 `decision=retryable-transient` / `blockingDisposition=runner-local-observation-gap`，不得直接输出 `global-offline`；只有 provider-gateway/SSH/k3s/scheduler 等多个独立关键路径同时失败且缺少健康交叉证据，才允许输出 `decision=global-offline`；registry 或单个 service proxy 失败但 heartbeat、SSH 或节点视图仍健康时，应输出 `decision=service-degraded`。`recommendedCrossChecks` 必须包含 `debug health`、`debug dispatch <providerId> host.ssh --wait-ms 15000`、`trans <providerId> argv true`、`artifact-registry health --provider-id <providerId>`、`microservice health k3sctl-adapter`、`microservice health code-queue` 与 `codex tasks --view commander --limit 20`；需要分区小页时再用 `codex tasks --view supervisor --limit 20`。

D601 artifact registry 的 systemd unit inactive 不等于 D601 全局离线。如果 `artifact-registry health` 或 `provider triage D601` 同时看到 registry container running、loopback listener healthy、`/v2/` 返回 200，且 provider heartbeat、Host SSH、k3sctl-adapter、Code Queue scheduler 或业务 API 有健康信号，这只能判为 `service-degraded`，不得写成 provider offline、D601 offline 或 CI/CD 全局不可推进。只有这些健康面也同时失败，才进入 `global-offline` 判断。

对于 trace 或 heartbeat 新鲜的长任务，通常应保持运行。每几分钟轮询一次优于反复 interrupt/retry。

当 `databaseActiveTaskIds` 非空、scheduler 本地 active run/slot 为空、且 owner scheduler heartbeat 已过期时，运行面应把该任务列为 stale-active recovery candidate，并通过 scheduler reconcile 路径把它恢复为 `retry_wait`，不应依赖 rollout restart 触发 startup recovery。恢复入口必须保留 fresh heartbeat 保护：heartbeat 新鲜的 split-brain live 任务只能继续监督，trace gap 但 heartbeat 新鲜也不能触发 stale retry。只读诊断优先使用队列/health 中的 `executionDiagnostics` 与 `reconcile` 字段；需要人工确认时可先调用 bounded dry-run reconcile，只有明确使用 `POST /api/scheduler/reconcile?recover=1` 且通过高风险恢复边界后才执行恢复。OA Event Flow publisher 积压或 overflow 只能降低 trace/stats 可观测性，必须在 `oaPublisher` 状态中显式暴露并隔离为观测降级，不能阻断 PostgreSQL task state、heartbeat 或 stale recovery。

外部 token provider、模型 API 或上游服务的限流和短时不可用是正常预期，不应自动升级为 Code Queue 基础设施缺陷。典型表现包括 `429 Too Many Requests`、provider transient error、上游 timeout 或模型服务短时失败。runner 必须把这类 OpenAI/模型 provider 429 归类为 `scope=external-provider`、`failureKind=external-provider-rate-limit`、`externalProvider429=true`，并在 attempt 的 `runnerErrorClassification.backoffHint`、任务 output 的 `queue/backoff` 行和日志 `task_retry_backoff` 中暴露指数退避与 jitter 证据。退避策略是保守指数退避加稳定正向 jitter：429 至少等待 30 秒，单次不超过 10 分钟，jitter 按 task id 和 completed attempt count 稳定计算，避免多 runner 同时恢复造成 provider 再次拥塞。只要 Code Queue 的状态机仍在自动退避，task heartbeat 或 scheduler heartbeat 新鲜，且任务仍能从 `retry_wait` 回到 `running`，指挥官应等待外部 provider 自行恢复，不创建额外修复 issue、不重派重复任务、不把该现象写成 blocker。只有当退避机制失效、任务丢失、heartbeat 过期、状态机卡死，或重试耗尽进入不可恢复终态时，才按 Code Queue 基础设施问题介入。

对于大规模 CI/CD 迁移波次，除非发生事故，否则使用稳定但可自适应的监督节奏。指挥官可以根据任务活跃度、完成未读积压、heartbeat 风险和外部等待性质自行决定 sleep 时长，但单次 sleep 不能低于 5 分钟、不能高于 30 分钟。活跃排障、刚派出新任务、存在完成未读或 heartbeat 风险时使用接近 5 分钟的短轮询；长时间等待外部 CI、模型 provider 退避或镜像构建且 heartbeat 新鲜时，可以拉长到 10 到 30 分钟。每轮醒来后读取 `codex queues`，读取 terminal 或可疑任务摘要，然后决定接受、retry、拆分 blocker，或让健康任务继续运行。循环期间指挥官可以做不重叠的有用工作，例如文档或 issue 梳理，但这些辅助工作不能接管 worker 已分配的实现。

当任务离开 `running` 或 `judging` 后，其结果仍然是未读工作。指挥官必须检查 final response 和 judge 记录，然后再决定是否补充并发窗口。

禁止在检查前用批量 read 动作清空完成未读任务。每个完成任务必须先单独审阅，再用 `bun scripts/cli.ts codex read <taskId>` 单独标记已读，使未读状态继续代表“仍需审阅”。

每次新增 Code Queue 任务、补发 follow-up task，或处理一批完成未读任务后，都必须同步更新 GitHub 总看板 issue `#20` 的正文主表；如果发生实质态势变化，还要同步更新指挥简报 issue `#24` 的正文。看板更新应反映当前任务分布、关键 blocker 和粗略进度，不要只改聊天上下文或只改单个 issue，而让总态势图落后于实际调度状态。

成本路由接入 #20 看板时，#20 的每个 AgentRun/历史 Code Queue 任务行都应显式保留推荐或实际 runner/model、风险等级、验证证据和审阅状态。推荐列的语义来自指挥官判断或 AgentRun task payload 审查，不能来自 worker 自评。MiniMax 和 DeepSeek 任务在 #20 中必须先保持“待指挥官审阅”状态；只有指挥官核验 diff、commit、轻量验证和未越界后，才更新为已验收并执行对应的 AgentRun/历史 read 标记。

## 指挥工作流

对每个活跃任务，按顺序评估四件事：

1. 完成质量：是否真的满足任务验收边界；
2. 完成状态：是否已经终态、可 retry，或仍在推进；
3. 自阻塞风险：任务是否卡在它自己无法解决的问题上；
4. 下一步动作：接受、继续、替换为更窄任务，或上报基础设施问题。

如果 blocker 是可复用的基础设施问题，不要盲目反复重跑业务任务。应先把基础设施缺陷记录到 issue，再在 Code Queue 无法越过时手动修复基础设施，然后恢复交付波次。

指挥官应优先做只读分析和派发新的窄范围任务，而不是本地接管实现。手动工作只保留给基础设施 blocker、live recovery，以及队列无法安全自解的问题。

## 干预规则

只有存在明确理由时才干预。

- 如果任务还在运行且 trace 或 scheduler heartbeat 新鲜，应引导而不是 interrupt。
- 对 AgentRun 运行中 session 的引导只使用正式 CLI：`bun scripts/cli.ts agentrun send session/<sessionId> --prompt-stdin`，再用 `logs/events/result/ack` 确认。旧 `codex steer` 已冻结，只保留历史 trace confirmation 查询。
- 真实 `send` 输出必须保持低噪声并直接显示 `dryRun`、`mutation`、`decision`、`internalCommandType`、run/command/runnerjob 摘要和后续命令，不回显 prompt 或完整 task state；失败默认不带 request body、不带 upstream body preview，也不带 raw response，需要上游预览或原始失败对象时显式重跑 `--full` 或 `--raw`。
- 旧 Code Queue 的 provider tunnel 失败只作为历史运行面诊断线索；新任务控制面失败优先按 AgentRun `describe task`、`events`、`logs`、`result`、G14 `agentrun-v01` manager 和 runner job 证据分流。
- 新 AgentRun 任务失败分流以 AgentRun queue/session/runner-job 返回字段为准。旧 Code Queue `.data.diagnostics.reason` 只用于历史任务和残留运行面，不再引导新 `codex submit/steer/resume`。
- 如果任务进入终态但缺少必要验收证据，应使用聚焦 continuation prompt retry 同一任务。
- 如果任务被可复用基础设施缺陷阻塞，应把该缺陷分配给合适的空闲或低风险队列，让原业务任务等待，或在修复后 retry。
- 如果基础设施缺陷影响 Code Queue 控制面可用性，指挥官可以执行恢复队列所需的最小受控部署，然后验证原任务能继续。
- 如果 retry、cancel、move 或 scheduler 行为错误，不要把手动 patch PostgreSQL 当作最终修复。应修复代码路径，必要时部署，然后通过正常 API 恢复受影响任务。

上一条中的“最小受控部署”不包括未经用户同意的 Code Queue backend 重启、容器重建或运行中任务 interrupt/cancel。凡是会改变 Code Queue backend 或执行中任务状态的恢复动作，必须先走 ClaudeQQ 请示；没有用户明确同意时，指挥官只能继续只读观察、拆出基础设施 issue、准备恢复命令和等待授权。

手动干预应尽可能保留原任务身份，以保持上下文连续。创建重复替代任务是 fallback，不是默认动作。

## 完成标准

Code Queue task 不是只要 push 代码就算完成。

对于 CI/CD 交付任务，验收必须包含目标交付策略要求的证据。对用户服务 artifact 交付，这意味着：

- CI artifact producer 从已推送 commit 运行；
- artifact ref 和 digest 已记录；
- dev 环境消费同一个 artifact；
- production CD 消费 artifact，且没有源代码 rebuild；
- live health、live commit 或 image label 证据与请求 commit 匹配。

对于基础设施任务，验收必须证明原本被阻塞的 workflow 可以继续，或明确说明 live 系统消费该修复还缺哪个部署步骤。

完成未读任务仍然是指挥官工作。它们必须被阅读、分类，并被接受、retry，或转成新的窄范围 follow-up task。

## 基础设施缺陷处理

交付计划中发现的基础设施缺陷，只要拆分后能提高吞吐或减少混乱，就应从用户服务工作中拆出来。

基础设施缺陷示例：

- retry API 遗留 stale cancellation state；
- healthcheck 不再匹配 runtime image；
- CLI 可观测性无法快速看到 running、最近完成或完成未读任务；
- WebUI 和 CLI 的 proxy 路径不一致；
- deploy job 报失败但服务 API 实际健康；
- 指挥侧突发 submit 打满 Code Queue manager 或低内存主机，导致队列还没确认任务就被压垮；
- Code Queue 容器缺少监督所需的基础工具或凭证路径，例如 `gh`、`hub`、`tran` 或 GitHub token 注入路径。
- D601、provider-gateway、registry、k3sctl-adapter 或 service proxy 的单路径瞬时失败被 worker 放大为全局阻塞，而缺少多信号健康裁决和可重试错误分类。
- runner、provider 或目标 runtime 缺少 Secret/env 注入、DNS、egress、registry auth、GitHub auth 或受控 rollout 权限，导致业务任务无法通过常规路径完成。

这些缺陷应分配给基础设施队列，prompt 中要包含具体观测失败、期望长期合同，以及原交付任务继续所需的恢复动作。

如果缺陷只存在于 Code Queue 执行环境，且服务可以在 dev 中安全热修而不触碰 prod，应先做最小临时 live remedy。然后把修复持久化到相关 Dockerfile、容器镜像或凭证传播路径，并在 dev 验证持久化修复后再关闭问题。

Code Queue runner 的分布式访问能力必须通过镜像内 `/usr/local/bin/tran` 固化，而不是依赖临时拷贝脚本或手工记忆命令前缀。runner 内 `tran` 走公网 frontend 控制面；其中 `ssh`/provider route 通过 authenticated frontend `/ws/ssh` WebSocket 代理接入 backend-core SSH bridge，stdout/stderr 必须按字节流直通到 runner，不得再通过 `/api/dispatch`、`/api/tasks` 或 task JSON compact 返回。runner 不要求持有 provider token，也不要求能解析 backend-core 集群内 DNS；frontend 是唯一对 runner 暴露的控制面，provider token 只存在于 frontend/backend-core 运行侧。runner 环境中的非 SSH remote frontend HTTP 读写默认使用 `curl` 后端，以降低部分 runner 上 Bun HTTP body 读取 native crash 的风险；这不是绕过控制面，route parser、WebSocket open payload 和 API request 仍由 UniDesk CLI 生成。当前必需验收目标是 D601 的真实 Code Queue pod：至少执行 `tran D601 argv ...`、`tran G14 argv ...` 以及一个 `tran <provider>:k3s ...` 只读命令，并用长 stdout 的长度/哈希证明没有 `...<truncated:N>` 标记，证明 D601 runner 能跨 provider host 与 k3s route 透传。G14 runner 可作为后续兼容性观察，不作为该合同当前阻塞条件。

如果业务任务发现缺少工具、Secret/env、DNS、egress 或凭证路径，指挥官应把它拆成独立 infra task，并标记为 `runnerDisposition=infra-blocked` 或等价基础设施阻塞，而不是埋在业务任务 prompt 中。业务 runner 不应自行摸索 live Secret、打印 env/token、复制凭证命令、扩大网络出口或通过反复 rollout 猜测问题；它只能提交脱敏证据、说明缺失能力和等待指挥官或 infra lane 处理。业务任务在 bridge 存在时应继续推进。

Artifact publish preflight 也属于基础设施问题的只读分类范畴：`artifact-registry status|health` 和 `ci publish-user-service --dry-run` 返回 `runnerDisposition=infra-blocked` 时，通常说明 backend-core/database/provider 通道缺失，而不是用户服务本身的业务错误。此时应先恢复控制通道，再决定是否重试，不要把裸 `No such container` 当成可直接回归的业务失败。

## 指挥边界

指挥官可以：

- 读取 task、queue、health、job 和 service 状态；
- 通过正常 Code Queue 和 microservice proxy API submit、retry、interrupt 或 cancel；
- 创建自包含 follow-up task；
- 在用户允许生产修复且部署路径已验证时，为基础设施恢复执行受控生产部署；
- 当 main worktree 有无关并行变更时，为文档或受控部署动作使用干净 detached worktree。

指挥官自己的 UniDesk 指挥仓库必须保持在单一根 worktree 的最新 `master` checkout 上。不要为指挥、队列判断或日常监督创建额外 worktree，这样指挥官始终看到当前仓库头和生产协调依赖的同一份实时状态。如果 worker 或受控一次性操作需要隔离 worktree，该 worktree 属于 worker 或具体操作，不属于指挥官的常驻环境。

每个由指挥官派发的 worker prompt，都必须在 Git 指令前明确写明目标线。`master` 用于主动开发和集成工作；`release/v1` 只用于明确批准的稳定维护修复。worker 的 final response 必须报告实际推送分支、远端 commit hash，以及该 commit 是否可从 `origin/<target-branch>` 获取。如果 final response 引用的 commit 不能被指挥官从声明的目标分支 fetch 到，该任务不得验收为完成。

指挥官不得：

- 本地重做 worker 已分配的实现，除非用户明确要求手动接管；
- 在 master server 上跑已知可能 OOM 的 full check、full e2e 或 Playwright；
- 回滚无关 dirty worktree 变更；
- 在 Git 远端是 source of truth 时，把本地部署状态当作 source of truth；
- 在缺少验收证据时宣布交付完成。

## 文档反馈回路

每个重复出现或阻塞交付的问题，都应反馈到以下至少一个位置：

- 修复该缺陷的 Code Queue task；
- 记录阻塞条件和恢复依赖的 GitHub issue 或 issue comment；
- 当经验具有长期复用价值时，写入长期参考文档。

长期参考文档应记录可复用规则，而不是完整事故流水账。过程知识应降低未来监督成本，而不是变成又一个一次性日志。
