# R4 任务报告

## 目标

- 关联 [UniDesk #2281](https://github.com/pikasTech/unidesk/issues/2281)。
- 将模板更新流程从以下三步：
  - `runtime list`；
  - 人工抄写账号 ID；
  - `runtime apply --accounts ...`；
- 收敛为一个受控 dry-run 命令。

## 实现

- 新增显式自动选集参数：
  - `--select-configured-policy`；
  - `--account-type apikey`；
  - `--exclude-accounts <id-or-exact-name,...>`。
- 自动选集只覆盖当前 credentials 已存在临时不可调度字段的账号：
  - 不把未配置账号隐式纳入；
  - 不提供隐式 `all`；
  - 不带 `--confirm` 时保持 dry-run；
  - confirm 复用既有批量预检、顺序写入和自动回读对账。
- 默认 Kubernetes 风格输出新增：
  - 候选账号数；
  - 已配置策略数；
  - 类型匹配数；
  - 请求排除数与实际从候选移除数；
  - 排除账号名称、ID、selector 和原因；
  - 每个最终账号的 `SELECTED_BY`。
- 显式 JSON 增加 mutation 专用紧凑投影：
  - 保留 request selector、selection provenance、汇总和每账号结果；
  - dry-run noop 不重复输出相同的 before、desired、actual 三份策略；
  - update 和 confirmed 对账仍保留必要差异。

## 设计修正

- 没有使用 `matchingTemplate` 自动选集：
  - owning YAML 模板内容变化后，旧 runtime 与新模板不再精确相等；
  - 本次真实运行面在更新前已显示 `TEMPLATE=-`；
  - 以精确模板匹配选集会错误选中 0 个待更新账号。
- 因此使用“已配置同类策略 + 显式账号类型 + 显式排除”的通用选集，并要求先看 dry-run 最终名单。

## 验证

- 单命令 PK01 dry-run：
  - `candidateAccounts=11`；
  - `configuredPolicyMatches=9`；
  - `accountTypeMatches=9`；
  - `selected=9`；
  - `changed=0`；
  - 9 个账号全部 `noop`；
  - `mutation=false`。
- `--exclude-accounts 15` 明确显示：
  - `lyon9801 0.0`；
  - ID 15；
  - 原因 `explicit-exclusion`。
- 缺少 `--account-type` 时命令在本地 fail-closed：
  - 非零退出；
  - 明确提示 `--select-configured-policy requires --account-type apikey`；
  - 不访问写入路径。
- 显式 JSON 最终完整返回：
  - 未触发 10 KiB 输出保护；
  - 保留所有 9 个账号和 selection provenance。

## 边界

- 本任务所有真实 Sub2API 调用均未携带 `--confirm`。
- 未修改 Sub2API 源码、版本、runtime、YAML、账号配置或外部哨兵。
