# AgentRun 控制面

AgentRun YAML-only lane 以 `config/agentrun.yaml` 为部署真相；node/lane、source workspace/branch、image build、GitOps branch/path、runtime namespace、Secret、外置数据库、manager env、git-mirror 和 edge 暴露都从 YAML 进入 CLI。

## 明确 legacy/manual authority 的 YAML-only lane

本节 mutation 命令只适用于 owning YAML 精确解析为 `legacy-manual` 的 lane。PaC 或 `unknown` authority 必须在远端调用和异步 job 创建前 fail-closed；当前 migrated consumer 的默认入口见下一节。

```bash
bun scripts/cli.ts agentrun control-plane plan --node D601 --lane v02
bun scripts/cli.ts agentrun control-plane apply --node D601 --lane v02 [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane secret-sync --node D601 --lane v02 [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane restart --node D601 --lane v02 [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane trigger-current --node D601 --lane v02 [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane cleanup-runners --node D601 --lane v02 --dry-run
bun scripts/cli.ts agentrun describe runnerjob/<runnerJobId> --run <runId> --node D601 --lane v02 -o json
bun scripts/cli.ts agentrun control-plane status --node D601 --lane v02 [--pipeline-run <name>|--source-commit <sha>] [--full|--raw]
bun scripts/cli.ts platform-infra gitea mirror status --target JD01 [--full|--raw]
bun scripts/cli.ts platform-infra pipelines-as-code status --target JD01 [--full|--raw]
```

- `plan`: 只读解析 YAML，输出控制面、source、image build、GitOps、runtime 和 Secret plan，不打印 Secret value。
- `apply`: 按 YAML 渲染并 apply Tekton RBAC/Pipeline、Argo AppProject/Application 和 runtime namespace。
- `secret-sync`: 按 YAML 的 Secret sourceRef/keyMapping 同步 runtime Secret 和外置 DB Secret，只输出 fingerprint。
- `restart`: patch manager Deployment restart annotation 并等待 rollout，用于 Secret export/DB 连接串变化后让 workload 读取新 Secret；不要手工删除 Pod。
- `trigger-current`: legacy v0.2 lane source authority 只读 k8s git-mirror snapshot。confirmed 运行先触发受控 `git-mirror sync`，为 source branch tip 创建 `refs/unidesk/snapshots/agentrun-yaml-lane/<branch>/<commit>`，再从该 snapshot 构建并推送 YAML 声明的 image，渲染 GitOps/artifact catalog，flush git-mirror 并创建 provenance PipelineRun。迁移到 PaC/Gitea 的 lane 不再通过该自维护触发器提交 CI。
- `cleanup-runners`:
  - 只读分类 YAML 选中 lane 中匹配 `deployment.runner.retention.selectors` 的 runner Job/Pod；
  - 默认有界显示 observation、capacity、最近活跃、heartbeat、业务进展、Pod waiting reason 和 `stale-pending`；
  - capacity 摘要必须显示 `<runnerJobCount>/<maxRunners>`、`status`、`availableSlots`、typed blocker 和 `degradedReason`；
  - `runnerJobCount === maxRunners` 时必须返回 at-capacity degraded，不能在下一 runner 已依赖 manager retention 时继续报告健康；
  - UniDesk 不提供 runner 强杀入口，也不按名称删除 Job/Pod；
  - AgentRun manager 的既有周期 reconciler 与 pre-create retention 负责自动分批回收；
  - 终态事实必须优先于历史 claim、heartbeat 和 Pod 活性观察；
  - `runner-dispatch-retry` 不属于业务进展，不能永久保护 pending runner；
  - 空闲运行面的验收值是 `runnerJobCount=0`、`protectedActiveRunnerCount=0`。
- `describe runnerjob/<runnerJobId>`:
  - 先通过 manager 精确读取 runner job identity；
  - 再按精确 Job name、`job-name` Pod label 和 Pod name Warning Event 查询运行面；
  - 不复用全 namespace retention scan，也不计算 UniDesk 删除结论。
- `status`: 默认返回 compact commander JSON，关键结论在 `.data.summary` 和 `.data.alignment`；完整 YAML target、原始 source/runtime/gitMirror payload 和 probe tail 只在 `--full|--raw` 展开。

Provider profile 的 YAML-first 入口是：

```bash
bun scripts/cli.ts agentrun provider-profile plan --node <NODE> --lane <lane> --profile <declared-profile>
bun scripts/cli.ts agentrun provider-profile runtime-status --node <NODE> --lane <lane> --profile <declared-profile>
bun scripts/cli.ts agentrun provider-profile status --node <NODE> --lane <lane> --profile <declared-profile>
bun scripts/cli.ts agentrun provider-profile apply --node <NODE> --lane <lane> --profile <declared-profile> --confirm
bun scripts/cli.ts job status <jobId> --tail-bytes 12000
bun scripts/cli.ts agentrun provider-profile validate --node <NODE> --lane <lane> --profile <declared-profile> --wait
```

- `plan`:
  - 只读检查 YAML 声明及 owner source 是否具备装配条件；
  - 不打印 Secret value。
- `runtime-status`:
  - 只检查目标 runtime Secret/key 和 YAML endpoint 对应的 Kubernetes Service/port 是否存在；
  - 不得读取 owner source、计算或比较 fingerprint；
  - 不得解码 runtime Secret value。
- `status`:
  - 读取 owner source；
  - 用编码 fingerprint 对齐 YAML 期望与 runtime；
  - 不得解码 runtime Secret value。
- `apply`:
  - lane parser 必须拒绝重复 Secret `id` 或重复完整 `targetRef`；
  - 执行期必须按 `namespace/name/key` 完整 `targetRef` 分类 provider Secret，不能按 `id` 绕过 activation gate；
  - Pod、Job 和 manager DB 观察只用于诊断，不能作为 Provider Secret 写授权；
  - Secret create、key add 或 key change 在异步 job 创建前和 worker sync 前均 fail-closed；
  - Kubernetes 编码态 fingerprint 完全一致时跳过 provider Secret patch；
  - 先由 AgentRun manager 完成 admission fence、DB fence、既有 runner 收敛和 Secret resourceVersion CAS，再解除非 no-op 阻断；
  - retention #280/#281/#282 不等于 Provider Secret 激活 fence，后者由 [AgentRun #284](https://github.com/pikasTech/agentrun/issues/284) 跟踪；
  - 只改 manager env、Kafka 开关、provider config 或 runner egress 时，复用当前 image；
  - no-op gate 通过后跳过 profile Secret 写入，发布 GitOps、刷新 Argo 并重启 manager；
  - 不创建 PipelineRun；
  - `--confirm` 默认立即返回异步 `jobId`；
  - 后续只通过返回的 `job status` 命令查看有界进展。
- `validate`:
  - 只读验证 YAML 与 live profile 装配；
  - 给出 HWLAB web-probe 原入口验收指引；
  - 不替代真实 Workbench 用户路径验证。

Legacy YAML-only lane 的长步骤必须由 CLI 拆成短提交和状态轮询：k8s git-mirror snapshot sync、image build、GitOps publish、git-mirror flush 和 PipelineRun 创建不得塞进一个顶层 `trans` 长连接。GitOps publish 必须使用隔离临时 clone/worktree，不能切换或污染 YAML 声明的固定 source workspace。

AgentRun YAML-only lane closeout 必须同时看当前 k8s git-mirror source snapshot、目标 PipelineRun、GitOps revision、Argo revision 和 manager source commit。发布过程中如果 source branch 被并行 PR 推进，`status --pipeline-run <name>` 会通过 `summary.branchDrift` / `alignment.branchDrift` 标记目标 PipelineRun 是否已被当前 snapshot tip supersede。最终只用最新 PipelineRun 的 `status` 中 `aligned=true`、`blockers=[]`、`argoSyncedToGitops=true` 和 `managerSourceMatchesExpected=true` 收口。

## JD01/NC01 v0.2 Gitea / Pipelines-as-Code lane

JD01/NC01 `agentrun-<node>-v02` 已迁移为单一路径：GitHub PR merge -> GitHub webhook -> Gitea controlled mirror -> immutable snapshot -> Gitea webhook -> Pipelines-as-Code -> Tekton -> GitOps/Argo -> k8s runtime。不要保留 Gitea Actions、act_runner、legacy branch-follower 或第二套 trigger fallback。CLI 必须组合 `config/platform-infra/gitea.yaml` 与 `config/platform-infra/pipelines-as-code.yaml` 精确解析 consumer；未知、歧义或 source identity drift 都必须 `mutation=false` 并 fail-closed。

Gitea 只作为受控 mirror/source authority 和 PaC webhook 源。公开 Web UI 是 `https://gitea.pikapython.com`；k8s 内部 clone/read 必须走 `http://gitea-http.devops-infra.svc.cluster.local:3000/...`，不要让内部 CI、Argo 或 runtime 通过公网域名回环。需要 CI 匿名内部 read 的 mirror repo 必须在 YAML 中声明 `publicRead: true`，bootstrap/apply 必须修正既有 repo/org visibility，而不只依赖 create-time 默认值。

PaC 默认只读状态入口是：

```bash
bun scripts/cli.ts platform-infra pipelines-as-code status --target JD01
```

默认状态必须显示 controller/CRD/webhook ready、最新 PipelineRun 和 TaskRun duration、`IMAGE_STATUS`、env identity、image digest、GitOps commit、Argo revision/health 和 runtime source/env annotations。env reuse 机制和证据解释统一见 [env-reuse.md](env-reuse.md)，本文件不重复维护第二套口径。

PaC lane 的 runtime boot repoURL、Argo repoURL 和 CI git read URL 必须使用 Gitea internal read URL。若仍指向 legacy git-mirror read URL，runtime 可能因 `git-mirror-exact-commit-unavailable` 崩溃。GitOps commit 已推进但 Argo revision 未追上时，只用 status/history 定位并修 Gitea write path、Argo repoURL、controller 或 owning YAML；不得执行 AgentRun refresh 或 legacy git-mirror flush 补齐当前交付。

Runner egress proxy、持久化、idle timeout 和 retention 只从 `config/agentrun.yaml` 的 `deployment.runner.*` 进入部署。验收不能只看 manager Deployment/Pod env；必须用 HWLAB/AgentRun 原入口创建新 turn 或 runner Job，并检查新 runner Job env、session PVC、`AGENTRUN_SOURCE_COMMIT` 和 trace/result 是否复用同一 run 且没有 `reuse-blocked`。

Kafka event stream 验收也必须创建真实 runtime facts：manager event 用 `./scripts/agentrun kafka tail agentrun --run-id <runId>` 查 `agentrun.event.v1`；Codex stdio raw 用真实 runner Job 后的 `./scripts/agentrun kafka tail stdio --run-id <runId>` 查 `codex-stdio.raw.v1`，并确认 runner Job env 包含 `AGENTRUN_KAFKA_STDIO_*`。默认不要加 `--values`，除非正在做受控裸帧排查。

Provider credential 的 `config.toml` 变更同样走 YAML `sourceRef`、`secret-sync` 和 `restart`；lane config 只声明该 lane 需要的 Codex CLI runtime options。模型、provider 和 endpoint 需要由 lane YAML 拥有时，使用 `sourceMode: codex-config` 加 `codexConfig` 渲染 Secret 中的 `config.toml`；不要修改或复制指挥机全局 `~/.codex/config.toml` 作为长期事实。

## AgentRun v0.1 legacy 兼容入口

```bash
bun scripts/cli.ts agentrun control-plane status [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane trigger-current [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane refresh [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane cleanup-runs [--min-age-minutes N] [--limit N] [--dry-run|--confirm]
bun scripts/cli.ts agentrun control-plane cleanup-released-pvs [--limit N] [--dry-run|--confirm]
```

- `status`: 只读汇总 source commit、PipelineRun、Argo、manager image、git mirror 和 `aligned` 结论。
- `trigger-current`: 快进 `G14:/root/agentrun-v01`，mirror sync，创建 `agentrun-v01-ci-<short12>` PipelineRun。
- `refresh`: Argo hard refresh，不 patch runtime workload。
- `cleanup-runs`: 只清理 `agentrun-ci` 中已完成 PipelineRun 和临时 PVC；不清理 runtime runner Job/Pod/Secret。
- `cleanup-released-pvs`: 回收 Released PV。

AgentRun compact JSON 关键字段在 `.data.summary.sourceCommit`、`.data.summary.expectedPipelineRun`、`.data.summary.runtimeAlignment`、`.data.summary.gitMirror`、`.data.summary.ci.pipelineRun`、`.data.summary.argo` 和 `.data.alignment`，不要假设存在 `.data.status`。

## AgentRun legacy Git mirror

```bash
bun scripts/cli.ts agentrun git-mirror status [--full|--raw]
bun scripts/cli.ts agentrun git-mirror sync [--dry-run|--confirm] [--wait]
bun scripts/cli.ts agentrun git-mirror flush [--dry-run|--confirm] [--wait]
```

- `status`: 返回 `localV01`/`githubV01`/`localGitops`/`githubGitops`/`pendingFlush`/`githubInSync`。
- `sync`: 拉取 GitHub `v0.1` 和 `v0.1-gitops` refs。
- `flush`: 推送本地 `v0.1-gitops` 到 GitHub。

AgentRun mirror 与 HWLAB mirror 共用 `devops-infra` 服务和 cache PVC，但 repo path、refs、status 文件和 CLI 命令彼此独立。
