# Tekton And Argo Control Plane

控制面负责 PipelineRun、RBAC/Pipeline/Argo、node-scoped runtime lane 和 D601 节点本地 infra bootstrap。正式入口都必须使用 `bun scripts/cli.ts`，不要把裸 `kubectl`、`argo` 或 `tkn` 当长期操作面。

微服务契约版本、source/runtime commit、镜像 provenance 或部署对齐检查只能显示非阻塞 warning，不得成为线上用户业务、admission、dispatch、readiness 或 CI/CD public gate。控制面仍可报告 drift 并引导修复，但业务健康与用户入口成功证据不因 drift 被改写。

## G14 legacy Control Plane

本节 `trigger-current` 只适用于 YAML 明确解析为 legacy/manual authority 的 G14 lane。

```bash
# 最新 head
bun scripts/cli.ts hwlab g14 control-plane status --lane v02

# 定点 PipelineRun
bun scripts/cli.ts hwlab g14 control-plane status \
  --lane v02 --pipeline-run hwlab-v02-ci-poll-<short-sha>

# 定点 source commit
bun scripts/cli.ts hwlab g14 control-plane status \
  --lane v02 --source-commit <full-sha>

# 手动触发
bun scripts/cli.ts hwlab g14 control-plane trigger-current \
  --lane v02|v03 [--dry-run|--confirm]

# 应用 RBAC/Pipeline/Argo
bun scripts/cli.ts hwlab g14 control-plane apply --lane v02 [--dry-run|--confirm]
```

定点 status 输出 `targetValidation.state=passed|superseded`，只检查指定 target 的证据。confirmed trigger 创建 commit-pinned PipelineRun；同名 PipelineRun 存在时默认复用现有状态，不做隐式 delete/create。

## Node-Scoped Runtime Lane

```bash
bun scripts/cli.ts hwlab nodes control-plane status --node <node> --lane v03 [--pipeline-run <name>|--source-commit <sha>] [--full|--raw]
bun scripts/cli.ts platform-infra pipelines-as-code status --target <node> --consumer <consumer>
bun scripts/cli.ts platform-infra pipelines-as-code history --target <node> --consumer <consumer> --limit 10
bun scripts/cli.ts hwlab nodes control-plane platform-maintenance --help
bun scripts/cli.ts hwlab nodes control-plane legacy-cicd --help
```

`status` 默认返回 compact summary，只保留 source commit、PipelineRun、Argo、runtime readiness、public probe、git mirror 和 next action；完整 expected YAML/render target、kubectl result tail、Secret/sourceRef 详情和 probe 原始结果只在 `--full` 或 `--raw` 下展开。

- `status` 可见性契约：
  - 启动后立即在 stderr 输出 `started` 和当前阶段；
  - 等待期间按 `config/hwlab-node-control-plane.yaml#status` 输出有界 heartbeat；
  - 正常完成、总预算超时和中断都返回阶段耗时、已完成探针、未完成探针和 typed reason；
  - 超时或中断由 observed worker 终止整组子进程，并在 closeout 中披露进程组清理结果；
  - worker 启动或解析失败时，closeout 返回过滤 progress 后的有界脱敏错误摘要；
  - 显式 `--json` 的 stdout 只包含一个 compact JSON 文档，progress 保持在 stderr；
  - `--full` 保留有界文本 drill-down，`--raw` 保留完整 JSON 的渐进披露入口。
- `status` 配置真相：
  - 总预算、heartbeat 周期、终止宽限期和探针开关只由 `config/hwlab-node-control-plane.yaml#status` 维护；
  - `--timeout-seconds` 只作为本次调用的显式总预算覆盖，不能变成代码默认值或第二份长期配置。

`control-plane apply --confirm` 是显式平台配置维护入口：从 `config/hwlab-node-control-plane.yaml` 收敛 node-local infra、RBAC、Tekton/Argo 前置对象，再应用 runtime namespace、Pipeline 和 Argo Application。它只从 `platform-maintenance` scoped help 发现，不得作为 PaC source PR 合并后的交付、恢复或补跑。

`trigger-current|refresh|sync` 只属于 owning YAML 明确解析为 `legacy-manual` 的 lane，并且只在 `legacy-cicd` scoped help 中可发现。PaC 与 `unknown` authority 必须在任何远端调用或异步 job 创建前结构化拒绝，默认/失败态 Next 只能指向 status/history 与自动链修复引用。

Legacy 一键入口的端到端预算只由 owning YAML 声明，不是每个子阶段各等一轮。嵌套 git-mirror sync/flush 必须按剩余预算裁剪；超预算只输出阶段分解和下一条只读 status。PaC consumer 从 GitHub PR merge 事件计时，不适用操作者一键入口。

CI/CD closeout 的 public gate 只验证选中 node/lane 的 formal public HTTPS `/health` 入口和必要 provenance。`web-probe`、Playwright、远程浏览器、DOM quick-verify 和用户路径 E2E 只能作为发布后的独立业务验证证据，不能作为 CI/CD gate、timeout blocker 或 closeout 必要条件。public gate 失败时先对齐 YAML publicExposure、GitOps 渲染出的 `frpc` ConfigMap/Deployment、Secret key presence、frpc 日志、PK01/Caddy loopback 和目标侧 HTTPS probe；不要把裸 FRP 端口、legacy 端口或 web-probe 超时当作 CI/CD 结论。

FRP/Caddy 类 closeout 要同时看 ConfigMap 与 Pod 实际加载状态。ConfigMap 或 Secret 对象存在不等于 frpc 已登录成功；必须检查运行中 Pod 日志是否有目标 proxy `start proxy success`，并区分 `port already used`、`port not allowed`、`token in login doesn't match token from configuration` 和 upstream service 502。frpc token 必须通过 YAML sourceRef 下发为 Kubernetes Secret，再由源码渲染以 SecretRef/env/template 消费；不要把 token 明文写入 GitOps ConfigMap、issue、日志或 reference。

Legacy `sync --confirm` 是 YAML 声明的 Argo runtime 收敛修复入口。PaC consumer 不得调用它补齐交付；平台 Secret 维护与 source delivery 必须分开。不要手工裸删 pod。

## D601 Infra Bootstrap

```bash
bun scripts/cli.ts hwlab nodes control-plane infra plan --node D601 --lane v03
bun scripts/cli.ts hwlab nodes control-plane infra status --node D601 --lane v03
bun scripts/cli.ts hwlab nodes control-plane infra apply --node D601 --lane v03 --dry-run
bun scripts/cli.ts hwlab nodes control-plane infra apply --node D601 --lane v03 --confirm
bun scripts/cli.ts hwlab nodes control-plane infra ci-build-benchmark --node D601 --lane v03 --profile no-mirror-full --confirm
bun scripts/cli.ts hwlab nodes control-plane infra ci-build-benchmark status --node D601 --lane v03 --profile no-mirror-full
bun scripts/cli.ts hwlab nodes control-plane infra ci-build-benchmark logs --node D601 --lane v03 --profile no-mirror-full
```

从 `config/hwlab-node-control-plane.yaml` 渲染 D601 HWLAB v03 的节点本地 CI/CD、git-mirror、Tekton、runtime dependency image preload 和 Argo 前置对象。confirmed apply 只做 control-plane bootstrap，不触发 runtime rollout，不创建 PK01 DB，也不修改 Caddy/FRP。D601 Argo CD 安装也必须由 YAML 声明：官方 manifest URL、版本、镜像 rewrite/preload、CRD、期望 workload 和 AppProject/Application 都来自 YAML。

`ci-build-benchmark` 是 HWLAB v0.3 k3s CI/CD 全量无缓存构建出网测速入口。profile、独立 catalog path 模板、cache policy、必须输出的 timing 阶段和失败族来自 `config/hwlab-node-control-plane.yaml`；实际 service set、git mirror URL、Pipeline、ServiceAccount、registry prefix 和 base image 仍以 `config/hwlab-node-lanes.yaml` 为准。`forbidBuildkitCache=true` 时会向 PipelineRun 传 `build-cache-mode=disabled`。通过证据必须包含每个 `build-<service>` TaskRun；PipelineRun 成功但缺少 build task 要按 `cache-hit-forbidden` 处理。

## Runtime Base Image

```bash
bun scripts/cli.ts hwlab nodes control-plane runtime-image status --node G14 --lane v03
bun scripts/cli.ts hwlab nodes control-plane runtime-image preload --node G14 --lane v03 --confirm
```

runtime base image 走 `config/hwlab-node-lanes.yaml`：`baseImageSource` 是公开来源，`baseImage` 是 node-local registry 目标。缺失 base image 时先用 `runtime-image status` 判断 `registryTagPresent`，再用 `preload --confirm` seed；不要手工 `docker tag/push`。

## Failure Triage

PipelineRun 失败或长时间未完成时，先按定点 status/history 和 bounded 只读诊断定位 TaskRun/Pod/container。PaC consumer 即使是单个 transient 也不得用 `trigger-current --rerun`；应修 `artifact-publish`、envRecipe、controller 或 owning YAML 的有限 retry，再通过新的正常 PR merge 验收。只有明确 legacy/manual authority 才能使用旧 rerun。

小范围 PR 触发 120s 时必须看 plan artifacts 的 `affectedServices/buildServices/reusedServices`：如果 source diff 很小却出现所有 envreuse 服务都在 `buildServices` 且 `reusedServices=[]`，优先怀疑 current GitOps artifact catalog 没有 hydrate 到 source plan 阶段，而不是继续盲目重跑 PipelineRun。

Migrated consumer 出现 registry half-state、GitOps 超预算或 runtime 未对齐时，只用 PaC `status|history`、PipelineRun id、只读 sentinel image status 和 bounded logs 下钻。不得把 PaC closeout、GitOps flush、async mutation job 或 consumer 专用 publish 放入 Next；定位后修 owning YAML、planner、controller 或源码，并用新 PR merge 后的 plan 与手动 webhook 验收。
