---
name: unidesk-cicd
description: >-
  UniDesk CI/CD 控制面，覆盖 PaC consumer 首发 bootstrap、Tekton/Argo、GitOps、
  Gitea 单一 source authority、L2/L3 手动计划发布、Secret、observability、CI tools image、PipelineRun 清理、
  Tekton 大对象与 Kine/SQLite 控制面退化、AgentRun 与 HWLAB 部署，
  以及 branch-follower 退役只读诊断。
  用户提到 CI/CD、deploy、rollout、PipelineRun、PaC、bootstrap、GitOps、Tekton、
  git-mirror、control-plane、k8s/k3s 部署、branch follower、agentrun、hwlab g14、
  PipelineRun 对象膨胀、Slow SQL、NodeNotReady、CI/CD 快速恢复、
  monitor-prs 或 trigger-current 时使用。
  任何需要把代码变更推送部署到 G14 k3s 的操作都必须走本 skill。
---

# UniDesk CI/CD

HWLAB G14 和 AgentRun CI/CD 的受控入口。任何 PR 监控、Tekton/Argo、Gitea source authority、Secret、observability、CI tools image、PipelineRun 清理或 AgentRun 部署都必须走 `bun scripts/cli.ts`。

- `$unidesk-devlevel` 用 L2 Development 和 L3 Production 描述两种集群部署方式：
  - 本 skill 负责这两种方式的手动计划发布、运行面操作和事故处理；
  - L0 Function 与 L1 Native 不使用 CI/CD。
  - 能在 L0/L1 复现和修复的问题，不用反复 L2/L3 rollout 代替快速小回环；需要集群回归时必须先 plan，再手动触发对应集群方式。
  - L2 可由代理按任务需要自行判断。
  - L3 必须先完成对应 L2 回归，L2 通过后才请求用户当次明确授权，获授权后再滚动到生产。

- 生产发布分支必须是开发分支同一条提交链上的滞后指针：
  - production/release 分支必须是 development 分支当前 head 的祖先；
  - 生产发布只允许通过受控 fast-forward 把 release 指针推进到已完成 L2 验证的开发提交；
  - 禁止在 release 上直接开发、cherry-pick、重放提交或生成只存在于 release 的修复；
  - 发布前必须验证 ancestry，不能只比较文件内容、patch-id 或版本号；
  - release 与 development 已分叉时，立即停止生产推进；
  - 先把 release 独有语义合回 development，完成冲突解析与 L2 回归，使旧 release 成为 development 的祖先；
  - 恢复祖先关系后，才允许把 release fast-forward 到选定的开发提交；
  - release 漏提交时修复开发到发布的指针关系，禁止再向 release 补同义提交掩盖分叉。

## 高频入口

```bash
bun scripts/cli.ts cicd status --node NC01
bun scripts/cli.ts cicd status --node <NODE>
bun scripts/cli.ts hwlab g14 monitor-prs --lane v02 --once --dry-run
bun scripts/cli.ts hwlab g14 control-plane status --lane v02
bun scripts/cli.ts hwlab nodes control-plane status --node NC01 --lane v03 --json
bun scripts/cli.ts agentrun control-plane status
bun scripts/cli.ts platform-infra gitea mirror status --target JD01
bun scripts/cli.ts platform-infra gitea mirror webhook status --target JD01
bun scripts/cli.ts platform-infra pipelines-as-code bootstrap --target NC01 --consumer <consumer> --dry-run
bun scripts/cli.ts platform-infra pipelines-as-code bootstrap --target NC01 --consumer <consumer> --confirm
bun scripts/cli.ts platform-infra pipelines-as-code release plan --target NC01 --consumer <consumer> --source-commit <full-sha> [--base-commit <full-sha>]
bun scripts/cli.ts platform-infra pipelines-as-code release trigger --target NC01 --consumer <consumer> --source-commit <full-sha> [--base-commit <full-sha>] --confirm
bun scripts/cli.ts platform-infra pipelines-as-code status --target JD01
bun scripts/cli.ts platform-infra pipelines-as-code status --target JD01 --consumer hwlab-jd01-v03
bun scripts/cli.ts platform-infra pipelines-as-code history --target JD01 --limit 10
bun scripts/cli.ts platform-infra pipelines-as-code history --target JD01 --id <pipelinerun>
bun scripts/cli.ts platform-infra pipelines-as-code diagnose-regression --target NC01 --consumer <consumer>
bun scripts/cli.ts platform-infra pipelines-as-code delivery-timing --target NC01 --consumer selfmedia-nc01
bun scripts/cli.ts platform-infra pipelines-as-code delivery-observe --target NC01 --consumer <consumer> --source-commit <full-sha>
bun scripts/cli.ts platform-infra pipelines-as-code closeout --target <NODE> --consumer <consumer> --wait --timeout 120s
bun scripts/cli.ts platform-infra pipelines-as-code debug-step --target JD01 --consumer <consumer>
bun scripts/cli.ts platform-infra pipelines-as-code debug-step --target JD01 --consumer <consumer> --id <pipelinerun>
bun scripts/cli.ts platform-infra pipelines-as-code source-artifact check --target NC01 --consumer <consumer> --source-worktree <absolute-path>
bun scripts/cli.ts platform-infra pipelines-as-code source-artifact verify-runtime --target NC01 --consumer <consumer> --source-worktree <absolute-path> --source-commit <full-sha>
bun scripts/cli.ts agentrun control-plane legacy-cicd --help
bun scripts/cli.ts hwlab nodes control-plane legacy-cicd --help
```

- L2/L3 发布触发：
  - PR merge、push 和 branch update 只更新 source authority，不创建 PipelineRun；
  - 先运行 `release plan`，检查本次请求范围、累计有效范围、env reuse、待构建镜像数量与列表、rollout 范围和全部受影响服务；
  - 当前 GitOps catalog 落后 source 时，plan 必须把累计发布欠账与本次 base 到 source 的请求范围分开显示；
  - HWLAB `release plan` 省略 `--base-commit` 时必须先恢复 catalog，并使用 `catalogSourceCommitId` 作为范围基线；禁止回退到 source parent；
  - 显式 `--base-commit` 只用于诊断请求范围；输出必须披露 `rangeBaseline.catalogAligned`，expanded 的动态 `next` 必须直接给出 catalog-aligned replan；
  - 有效范围大于请求范围时标记 `expanded`，`release trigger` 必须在发送 webhook 前拒绝；
  - 计划范围扩大时先修复 source range、源码、YAML 或项目 planner，再重新 plan；
  - `package.json` 即使同时出现在 runtime deps 与 component paths，也只按运行字段做一次语义判定；scripts-only 变化不得进入服务 changed paths；
  - planner hash 算法变化时，从 catalog source commit 按新算法重算；source tree 未变的 metadata drift 不得触发 build 或 rollout；
  - CLI `release plan` 与 Pipeline 内部 planner 必须使用相同的 source/base、catalog authority、registry probe 和 cache 可用性输入；不得让 CLI 省略 `--verify-reuse-registry` 等会改变 build/rollout 结论的判定；
  - webhook admission 后 Pipeline 必须校验已审阅 plan identity；内部重算的 build/rollout/affected 任一范围扩大时，在进入 build 前失败并要求重新 plan，禁止静默执行扩大后的计划；
  - 真实 TaskRun results 与 CLI plan 不一致时，按控制面合同漂移报告阶段耗时和差异后停止；禁止补跑、提高 timeout 或把实际构建解释成 env reuse；
  - `build=0`、`rollout=0`、`affected=0` 是 no-op 终态，不发送 webhook，不创建 PipelineRun，动态 `next` 不得指向 trigger；
  - renderer rollout 范围必须对应实际 GitOps Pod template diff：
    - renderer 重建完整 runtime tree 并改写未选 workload 的 source identity 时，plan 必须把全部实际受影响 workload 计入 rollout；
    - renderer-only 变化不得误计为镜像构建；
    - 只有未选 workload 的 manifest 和 source identity 均保持不变时才允许显示局部 rollout；
    - renderer 拆分后的全部 materialization 源码路径必须纳入 planner 输入集合；
  - artifact catalog 必须从 owning YAML 声明、且与 Argo/promotion 相同的 GitOps read URL 与 branch 恢复；禁止用 source mirror 中的同名 branch 代替 GitOps authority；
  - 审阅通过后运行 `release trigger --confirm`；该命令只向 PaC 发送 webhook，由 PaC 创建 PipelineRun；
  - 禁止裸创建 PipelineRun、由 CLI 直建 PipelineRun，或恢复 Gitea 自动 hook；
  - PaC migrated consumer 的 Argo downstream：
    - owning YAML 的 `argoBootstrap` 必须声明 GitOps repo、branch、path、namespace 与 `automated=true`；
    - Argo 只自动消费手动 PipelineRun 生成的 GitOps commit，不构成第二发布触发入口；
    - 配置缺失或漂移时先通过 bootstrap dry-run/confirm 收敛控制面，再由新的 plan/trigger 验收；
    - 禁止人工 Argo sync。
  - L3 继续要求对应 L2 已通过和用户对当次生产发布的明确授权。
  - 每次修改发布入口后，必须复核 `pipelines-as-code --help`、`release --help`、`release plan --help`、`release trigger --help` 与一条动态 `next`：帮助必须完整展示 plan/trigger 的参数、范围审阅字段和 `--confirm` 边界；动态 `next` 只能在范围准确时指向 trigger，范围扩大或触发失败时必须指向修复后重新 plan，不得遗漏或引导自动交付。
  - release plan 的 changed paths、domain plan 和 webhook payload 等可增长结构化数据必须通过临时文件或 stdin 传递，禁止放入环境变量或命令行参数；默认/`--json` 输出必须有界保留 env reuse、build、rollout、affected 与 scopeReview，完整 changed-path 明细只在显式 `--full|--raw` 披露。

- 节点级只读状态：
  - 优先用 `cicd status --node <NODE>`；
  - 该入口在目标侧一次批量读取 PipelineRun、Argo Application 与 Deployment，再按 owning YAML consumer 投影，禁止为每个 consumer 并发启动完整 `status`；
  - 默认 JSON 直接披露 `remoteCaptureCount=1`、`observation`、`readErrors` 与 consumer 核心状态，无需 `--full` 或 dump；
  - 任一批量 list 失败时保留 `pipeline-read-failed`、`argo-read-failed` 或 `runtime-read-failed`，禁止把读取失败推导为对象缺失；
  - 单 consumer 再用 `platform-infra pipelines-as-code status --target <NODE> --consumer <id>` 下钻；
  - 状态输出与 registry applicability 的长期判定见 [references/gitea-pac.md](references/gitea-pac.md)。

- 生产事故回退诊断：
  - 唯一推荐入口是 `platform-infra pipelines-as-code diagnose-regression --target <NODE> --consumer <consumer>`；
  - 命令在目标侧只读取 PipelineRun 摘要，一次输出最后成功、首次失败、当前失败连续段、共同失败指纹、source commit 边界和回退候选；
  - 默认共同指纹范围只覆盖 owning YAML 中与选中 consumer 共享 `repositoryRef` 的 lanes，避免扫描节点上无关业务仓库；
  - `ok` 只表示读取成功，`incident` 表示是否存在当前事故，`read-failed` 不得伪装成健康；
  - 默认窗口是每 consumer 20 条，可用 `--limit 1..50` 有界扩大；窗口不足时命令给出 `expand-window`，不得无限拉取；
  - 首次失败需要 TaskRun 或日志证据时，只执行输出中的 `debug-first-failure` 精确下钻；
  - 命令固定 `mutation=false`、`automatic=false`，只提供 review-required 回退候选，绝不执行回退或生成补链动作。

- Tekton 大对象与节点控制面退化：
  - PipelineRun 重复内联大型 `taskSpec` 时，必须同时检查对象总大小、`spec`、`status.pipelineSpec`、Kine compaction、API timeout、node lease 和 kubelet 调和；
  - PipelineRun 已成功且 GitOps commit 已生成、但 Argo 仍停在旧 revision 时，先按传播延迟只读观察，不得立即重启 k3s、人工 Argo sync 或补链；
  - 只有节点/API/kubelet 已实际退化且 Pod 级调和无效时，才进入有界快速恢复；重启和终态对象清理只恢复控制面，不得作为最终修复证据；
  - k3s 先 panic、随后报 credential 文件新于 datastore 时，必须区分原始崩溃与重启闭锁，只可恢复性移动 fatal 点名的单个文件；
  - 根因判定、快速恢复、长期防复发和原入口验收统一见 [references/incident-recovery.md](references/incident-recovery.md)。

- CI/CD 只读等待：
  - 默认使用 `closeout --wait --timeout 120s` 观察 Tekton、Argo 和 runtime 收敛；已处于成功或失败终态时立即返回。
  - 未完成时由目标控制面的 Kubernetes watch 持有单次等待，不得在调用侧每 `1s`、`5s` 重复执行 `status`。
  - delivery 只有 source commit、GitOps exact/descendant ancestry、Argo 与 runtime sha256 digest 全部一致时才 ready；`no-runtime-change` 使用独立保留合同。
  - timeout 必须保留当前状态、`timedOut=true`、耗时、稳定 identity/cursor 与 `next.wait`；零变化也必须有输出。
  - `--timeout` 只接受严格 `<正整数>ms|s|m`，测试使用短 timeout 或虚拟时钟，不真实等待 `120s`。
  - watch 断连或后端错误必须显式失败，不能折叠为 timeout；该入口固定 `mutation=false`，不触发 PipelineRun、Argo refresh、GitOps 或 rollout。

- PaC consumer 最新一次端到端耗时：
  - 唯一推荐入口是 `platform-infra pipelines-as-code delivery-timing --target <NODE> --consumer <id>`；
  - 一次调用直接披露 GitHub PR `mergedAt`、trigger wait、PipelineRun/TaskRun、端到端耗时、Argo、runtime health 和 `evidenceGaps`；
  - 证据不完整时保留已成立的耗时字段并返回 `partial` 与明确缺口，不得手工串联第二状态源；
  - PaC migrated consumer 从 CLI webhook durable admission 开始计时，PR merge 到人工 trigger 的等待不计入发布耗时；
  - 端到端耗时严格超过 owning YAML 预算时输出 `pac-manual-delivery-over-budget`，固定 `blocking=false`、`mutation=false`，并直接披露最长 TaskRun 与 budget evidence gaps；
  - 超预算提示只下钻 env identity、依赖缓存、BuildKit/cache 和 stage timing，不给出人工恢复命令；
  - 该入口固定只读且 `mutation=false`，不得用于同步、触发、补跑或运行面写入。
  - 验收 registry cache 性能时，按 [Gitea + PaC](references/gitea-pac.md) 的冷热两次正常 PR 流程执行，不用人工 PipelineRun 或重复 status/timing 试探。

- PaC consumer 按 source commit 做发布后取证：
  - 唯一推荐入口是 `platform-infra pipelines-as-code delivery-observe --target <NODE> --consumer <id> --source-commit <full-sha>`；
  - 一次 target-side capture 直接返回匹配的 PipelineRun、Argo sync/health 与首个退化资源或 condition、同 namespace exact-source workloads、ready/digest、首断点和 `complete|partial|blocked`；
  - 该入口只复用节点级轻量快照，一次批量读取 PipelineRun、Argo Application 与 Deployment；
  - PipelineRun 必须按 owning YAML consumer namespace 在同一次 target-side capture 内并行读取、合并，并使用 PaC ownership 与 owning Repository label 做服务端过滤；
  - 禁止通过 `-A` 无界扫描节点全部 PipelineRun，也禁止把 namespace 分片变成多个调用侧 capture；
  - 禁止在入口内部调用完整 `status`、同步读取 TaskRun/log、执行 Git fetch 或拼接第二个 history 状态源；
  - 任一批量读取失败时必须保留 typed `readErrors` 和最后成功阶段，不得提高 YAML timeout 或把读取失败投影为对象缺失；
  - 固定 `remoteCaptureCount=1`、`mutation=false`，不得再手工串联 `status`、`history`、`delivery-timing` 或裸 Kubernetes 对象查询；
  - runtime 证据是否适用只读 owning YAML 的 `consumers[].deliveryObservation.runtimeEvidence`：
    - `required` 要求 exact-source workload 存在且 ready；
    - `not-applicable` 用于只有配置/控制面交付、没有独立 workload 的 consumer，缺少 workload 不得阻塞；
    - 字段缺失时按非核心配置回退到 `required`，并输出配置路径、回退值和 `blocking=false` warning；
  - `complete` 表示 PipelineRun、适用的 runtime 证据与 Argo 全部就绪；`partial` 保留已成立的证据并明确 Argo 或适用 runtime 首断点；`blocked` 表示目标读取失败、source 不匹配、PipelineRun 未成功或必需 runtime 未观察到该 source；
  - TaskRun artifact 日志默认延后时只披露 `artifactEvidence.deferred=true`，不放宽既有 status evaluator，也不伪造 provenance。

- 新增 PaC consumer 的首次引导：
  - 先执行一次 `pipelines-as-code bootstrap --dry-run`；
  - 确认后把同一命令改为 `--confirm`；
  - 入口从 Gitea 与 PaC owning YAML 精确解析仓库；
  - 入口只初始化空 Gitea 仓库和 PaC/Tekton/GitOps 控制面；
  - 随后合并 source PR，再通过 `release plan` 和 `release trigger --confirm` 手动发布；
  - 详细最短路径见 [references/gitea-pac.md](references/gitea-pac.md)。

按职责读取拆分后的 reference：

- PR monitor 与自动合并: [references/pr-monitor.md](references/pr-monitor.md)。
- Tekton/Argo、node-scoped runtime lane、D601 infra bootstrap: [references/control-plane.md](references/control-plane.md)。
- legacy git-mirror 退役状态与清理边界: [references/git-mirror.md](references/git-mirror.md)。
- JD01/NC01 Gitea mirror + Pipelines-as-Code 正式架构、三 consumer 覆盖矩阵、target 级 webhook path 和旧入口处置: [references/gitea-pac.md](references/gitea-pac.md)。
- AgentRun/HWLAB env reuse 机制、证据解释和 PaC status/history 观察口径: [references/env-reuse.md](references/env-reuse.md)。
- Secret、observability、platform-infra、CI tools image、PipelineRun 清理和 rollout 补记: [references/platform-ops.md](references/platform-ops.md)。
- AgentRun YAML-only lane、v0.1 兼容入口和 AgentRun git-mirror: [references/agentrun.md](references/agentrun.md)。
- 已退役 K8s branch-follower 的只读状态、事件、日志和历史边界: [references/branch-follower.md](references/branch-follower.md)。
- 生产事故优先回退、consumer 私有配置边界和最短恢复路径: [references/incident-recovery.md](references/incident-recovery.md)。

## NC01 Public Edge 单一 Authority

- `config/platform-infra/public-edge.yaml` 同时拥有共享边缘聚合配置与 delivery authority：
  - 普通业务、L1、领域 CLI、任务 worktree 和人工会话只能修改 owning YAML；
  - 公开入口只允许 `plan`、`apply --dry-run` 与 `status`；
  - `apply --confirm` 必须 fail closed，禁止以紧急修复、验收或补链为由恢复。
- 唯一 mutation 链固定为：
  - GitHub `master` merge；
  - Gitea immutable snapshot；
  - `platform-infra-gitea-nc01` PaC 独立 checkout；
  - YAML SecretRef 控制的 `trans`；
  - NC01 host-local archive helper；
  - `platform-infra public-edge reconcile`。
- reconcile 必须同时满足：
  - source checkout、事件 commit 与 archive marker 完全一致；
  - 绝对外部 `configRef` 由 owning YAML pin 住 40 位 Git commit，
    renderer 只用 `git show` 读取该对象，禁止读取外部 working tree；
  - candidate ancestry 包含 installed source commit；
  - installed authority 与 YAML `authorityId` 一致；
  - host-local lock 已独占；
  - managed block、Compose 与 Caddy候选已验证。
- public-edge 候选验证的阻塞边界：
  - provenance、source ancestry、监听器、Compose 和 Caddy 配置无效继续阻塞；
  - 全站 DNS 与逐站点 public health 只输出具名 `blocking=false` warning；
  - 单个站点 DNS 漂移不得阻塞其他站点路由交付；
  - 禁止把 DNS 聚合检查重新加入 candidate rejection 条件。
- 乱序自动交付处理：
  - installed commit 与 candidate 相同则幂等返回；
  - installed commit 不是 candidate 祖先时，以 `stale-or-diverged-source-commit` 拒绝；
  - 禁止旧 PipelineRun、分叉提交或人工补跑覆盖较新的运行面。
- 精确变更判定：
  - 任意 `master` 事件可以进入 reconcile，但不能直接等同于共享边缘配置变化；
  - 健康运行面的 managed Caddy 与 Compose 指纹均未变化时，只推进 provenance，
    禁止重建 Caddy 或中断既有 HTTPS、流式响应和 WebSocket；
  - 只有受管配置指纹变化或运行面漂移时，才允许进入受控 recreate。
- 共享 Caddy 更新必须使用 owner managed block：
  - public-edge controller只替换 `public-edge-*` blocks；
  - 非 public-edge managed block 必须保留；
  - 领域服务不得生成或安装完整 Caddyfile。
- `status` 必须披露 redacted provenance：
  - installed/desired source commit；
  - installed 与 desired 的 source relation；
  - installed 是 desired 祖先且受管配置指纹一致时视为配置当前，
    不要求无关后继提交强制重写运行面；
  - installed 倒退、分叉或关系无法验证时保持失败；
  - authority、managed fingerprint、Compose fingerprint 与 site count；
  - legacy container 是否已退役；
  - DNS 与 HTTP probe 的失败列表必须直接包含 site id、hostname、
    health path 或 expected A 与稳定错误码；
  - public-edge 失败定位只执行一次 `status`，
    禁止再串联 plan、临时脚本或额外 `trans` probe；
  - 默认 target status 必须返回有界摘要并直接披露 `firstFailure`，
    禁止触发 `outputTruncated` 或依赖临时 dump；
  - 默认摘要必须包含 authority、installed/desired commit、source relation、
    managed/Compose fingerprint、endpoint 健康和 warning 计数；
  - 站点详情使用 `--site <site-id>`，完整对象只通过显式 `--full` 获取；
  - 不披露 Secret、token 或 archive payload。
- public-edge 专站状态：
  - 领域服务统一调用
    `platform-infra public-edge status --target <target> --site <site-id>`；
  - 默认全站状态用于平台总览，不得作为单个领域服务的同步依赖；
  - 专站输出只保留该站点声明、DNS warning 和 health failure；
  - 全局容器、监听器、Caddy、provenance 与配置一致性继续参与判定。

## P0 边界

- 当前业务问题域内的 CI/CD 故障必须直接闭环：
  - 用户要求修复、发布或回归某个业务时，选中 consumer 自有的 owning YAML 配置片段、独立 namespace/lane、独立 source artifact、消费仓 `.tekton` 制品和该业务运行配置均属于主任务授权范围；
  - 确认故障位于上述范围后，直接完成根因修复、PR 合并、手动 plan/trigger 发布和原业务入口回归，不得只登记 issue 后停工；
  - 修复仍须保持最小影响面，并按 L0、L1、L2 的适用层级逐级回归；不得借域内授权修改共享控制面或其他 consumer；
  - 只有致因落入下述公共服务面，或修复必须改变跨 consumer 共享对象时，才转为公共服务面授权判定。
- 未经用户明确授权，不得修改 CI/CD 公共服务面：
  - 公共服务面包括共享 PaC controller/release、admission、Gitea webhook bridge、共享 git-mirror 服务与 PVC、共享 Tekton/Argo bootstrap、公共 edge/FRPC/Caddy 入口，以及被多个 consumer 复用的 renderer、模板和脚本；
  - 默认只允许修改当前选中 consumer 在 owning YAML 中的独立配置片段、独立 namespace/lane、独立 source artifact 和该 consumer 仓库内的 `.tekton` 制品；
  - `repositoryRef`、共享 Repository CR、共享 branch/ref、共享 Secret/RBAC、共享服务 Deployment 或公共网络入口即使能解决当前故障，也不属于 consumer 私有配置；
  - 可以对公共服务面执行受控只读 status、history、events、logs 和 `debug-step`，但不得据此推定写入授权；
  - 只读证据确认致因位于公共服务面时，必须停止写入，向用户报告影响面、致因变更、优先回退候选和验收计划，等待用户明确要求修改公共服务面；
  - 用户只说“修复某个 consumer 的 CI/CD”不等于授权修改公共服务面；授权必须明确指向共享 PaC、Gitea、git-mirror、Tekton/Argo bootstrap 或其他公共组件；
  - consumer 私有修复不得夹带公共服务重构、其他 consumer 配置、共享模板清理或无关 PR；无法在私有边界内修复时按阻塞处理，不得扩大作用域。
- 生产 CI/CD 事故必须优先回退：
  - 把共享发布链连续失败、多个 consumer 同时失败、生产发布停摆、错误变更持续扩散或需要受控入口之外补链才能交付，按生产事故处理；
  - 立即停止与恢复无关的合并、bootstrap、apply、手工同步、补跑和并行架构改造，只保留只读取证与回退动作；
  - 先锁定首个失败事件、最后一个成功事件、共同失败指纹和两者之间的变更集，优先证明“哪一个变更导致失败”，禁止从最新错误状态直接开始连续试修；
  - 最近变更与失败强相关且回退不会造成不可逆数据损坏时，必须先回退该变更，恢复最后已知健康基线；不得以“顺手完善”“已经改了一半”或“继续修可能更快”为由保留错误基础；
  - 回退也必须通过最小单一职责 PR、`release plan` 审阅和受控手动 webhook 交付，禁止用直接 Gitea push、裸建 PipelineRun、Argo sync 或运行面热补伪造恢复；
  - 只有回退后的受控发布已经证明链路恢复，才允许从健康基线重新设计前向修复；前向修复必须拆成可独立验证、可独立回退的最小变更；
  - 回退存在不可逆 schema、数据迁移或外部状态风险时，先停止继续发布并保全证据，再选择已有受控恢复路径；不得在没有恢复边界的情况下继续叠加代码修复。
- PaC 公共 status renderer 故障必须先区分交付失败与观察失败：
  - 先用 PipelineRun、Argo 与 runtime 独立事实确认自动交付是否成功，不得把 `parse-failure` 或 status timeout 直接表述为交付链失败；
  - 引用缺失变量导致非法 JSON 时，优先从最后已知正确实现恢复该赋值，不得整体回退并撤销仍然正确的 fail-closed 业务语义；
  - `status` 不得把慢 TaskRun 日志作为同步必需项，必须复用一次 TaskRun 读取并输出有界阶段标记；精确日志证据留给 id-specific `history` 或 `debug-step`；
  - PipelineRun 成功、Argo `Synced/Healthy` 且 runtime ready 时，同步日志证据延后只能是 `blocking=false` warning，不能制造 false outage；详细案例见 [references/incident-recovery.md](references/incident-recovery.md)。
- PK01 的 CI/CD 默认只允许只读诊断：
  - 普通 PR merge、自动滚动、环境恢复或跨服务交付不构成 PK01 变更授权；
  - 只有用户在当前请求中明确要求修改 PK01，才允许提交或推广会改变 PK01 版本、配置、Secret 绑定、边缘路由、容器或运行面状态的 source 变更。
- PaC migrated consumer 的唯一正式 CI/CD 触发是 `release plan` 审阅后由 CLI 手动发送 PaC webhook。GitHub PR merge 只更新 Gitea controlled mirror 与 immutable snapshot ref，不创建 PipelineRun；禁止恢复 Gitea 自动 hook、直接 Gitea push、裸建 PipelineRun、Argo sync 或受控入口之外的补跑。
- PaC consumer 首次引导必须满足以下约束：
  - 默认使用 `pipelines-as-code bootstrap --dry-run|--confirm`，不再人工串联 Gitea bootstrap 与 PaC apply；
  - `apply` 必须在任何 release、RBAC、Secret、Repository CR、Argo 或 webhook 写入前确认 YAML 匹配的 Gitea 仓库已存在；
  - source PR 合并后不得再次调用 bootstrap 或 apply；先执行 `release plan`，范围准确后才执行 `release trigger --confirm`。
- 发布链路不通时必须修复链路自身，并通过修复 PR 对应的手动 plan/trigger 验收：
  - 已发生错误或首次部署尚未跑通时，允许使用 YAML 已声明的受控单步入口调试具体阶段；
  - 单步调试必须限定目标、输入和阶段，保留结构化结果，并且不得改写 source/ref authority、伪造成功状态或替代完整交付；
  - 单步确认的修复必须回写 owning YAML、renderer 或源码，再由正常 source PR 合并、plan 和手动 webhook 跑通 CI/CD 链；
  - 只有发布链从手动 source event、artifact、GitOps/Argo 到 runtime 原入口全部收敛，才能把首次部署或故障修复判为完成；
  - 禁止人工 mirror sync、直接 Gitea push、人工 PipelineRun、`trigger-current`
    或其他手段补齐当前交付；
  - 调试或临时恢复确需改变运行面时，允许按 `$unidesk-daddev` P2 实施最小、可逆 patch，
    但不得修改 source/ref authority、伪造交付成功或作为最终验收；
  - P2 结论必须收敛到 owning YAML、controller 或源码，
    再由修复 PR 的手动 plan/trigger 交付；临时 patch 必须撤销或被声明式交付覆盖；
  - 只读 status/history/events/logs/debug-step 仍是默认定位入口，
    `closeout` 只属于显式 compatibility diagnostics，不得进入默认观察或恢复路径。
- CI/CD、GitOps、rollout、PipelineRun、Argo、git-mirror 和 AgentRun 的观察、诊断与控制必须走受控 CLI；不要用裸 `kubectl`、`argo`、`tkn`、`curl` 当正式控制入口。PaC migrated consumer 只允许 `release plan` 后由 `release trigger --confirm` 发送 webhook。
- CI/CD 校验默认不得阻塞交付：
  - 除非用户明确要求某项校验成为门禁，禁止新增会让 Pipeline、artifact、GitOps promote、Argo reconcile、runtime rollout 或 `/health` closeout 失败的配置一致性、版本、契约、schema、preflight 或跨对象校验；
  - 全局配置、非选中 target/consumer、跨 consumer 一致性和版本/契约漂移只输出结构化 typed warning，并固定 `blocking=false`；
  - warning 必须保留对象、配置路径、错误码和修复入口，但不得改变交付成功终态、跳过业务功能、写回配置或触发补救 mutation；
  - 发现既有阻塞实例时逐例降级为 non-blocking warning，不以历史测试、旧门禁或旧合同继续阻止滚动；
  - 当前选中对象缺少渲染必需输入、Secret/权限不成立、目标无法唯一解析或 mutation target 不安全时，仍在 mutation 前 fail-closed；这类损害预防不得扩展成全局配置一致性门禁。
- CI/CD source authority 只能来自 YAML 声明的 Gitea authority：
  - GitHub PR merge 只更新 GitHub webhook bridge、Gitea authority branch 与 immutable snapshot ref，禁止合并后人工同步或创建 snapshot；该 source 更新不触发 PipelineRun；
  - build/status/publish 只消费对应 snapshot，host worktree、本地 `git fetch/pull`、可变 branch ref 或 Pipeline 内直连 GitHub 都不能作为 authoritative source。
- source branch、snapshot、GitOps branch、artifact catalog、Argo 和 runtime checkout 必须使用同一 Gitea repository：
  - CLI plan 与 Pipeline 必须从同一个 `gitops_read_url` 恢复 catalog；
  - promotion 只通过 YAML 声明的 Gitea SecretRef 写回同一仓库；
  - AgentRun 不得创建 managed-repository reconciler 或挂载 legacy mirror cache；resource bundle 直接读取 owning YAML 声明的 Gitea repository；
  - 禁止 `git-mirror-http`、`git-mirror-write`、mirror cache、sync/flush Job、fallback 或第二 authority。
- CLI 必须组合 `config/platform-infra/gitea.yaml` 与 `config/platform-infra/pipelines-as-code.yaml`，按 consumer、node、lane、upstream repository、branch 和 Gitea repository 精确解析 delivery authority。不得用 URL 片段或 repo 专属条件判断迁移；当前选中对象零匹配或多匹配时返回 `unknown`、`mutation=false` 并在 mutation 前 fail-closed，非选中对象和全局一致性错误只进入 `blocking=false` warning。
- PaC 与 `unknown` authority 的 help、plan、status、失败态 `Next`、`REPAIR` 和实际执行 guard 都不得包含或执行 legacy source mutation。`trigger-current|refresh|sync|flush` 只保留退役诊断，不得创建 Job 或写 ref；平台 bootstrap、Secret 与配置维护使用独立 scoped help，不得充当 source delivery recovery。
- JD01/NC01 `agentrun-<node>-v02`、`sentinel-<node>-v03`、`hwlab-<node>-v03` 在手动 webhook 后由 PaC/Tekton/GitOps 自动收敛并写入状态。仅在显式调查发布链故障时读取 `cicd status --node <NODE>` 或 `platform-infra pipelines-as-code status|history --target <NODE> --consumer <id>`；`cicd branch-follower` 和 `cicd gitea-actions-poc` 只保留历史/迁移只读用途。
- PaC `.tekton` 文件必须用 Repository CR 的 target/node 参数隔离 JD01/NC01，避免同一个 Gitea push 在一个 target cluster 内额外创建另一个 target 的 PipelineRun。`history --id` 必须按运行面 provenance 和实际 PipelineRun prefix 唯一归属 consumer；零匹配、多匹配或显式 consumer 不一致均 fail-closed，不得回退到默认 consumer 或默认 node。
- PaC source artifact 必须遵循以下边界：
  - 由 `config/platform-infra/pipelines-as-code.yaml#consumers[].sourceArtifact` 显式声明；
  - 通过 `source-artifact plan|check|write|status|verify-runtime` 管理；
  - 新增 service 后，不能只看 PaC plan 的 `buildServices`；必须确认 renderer 生成了对应 plan result、独立 build Task 和 collector 依赖，并在自动事件中看到实际 TaskRun；
  - 修改 source artifact 引用的源码入口时，先以独立 PR 合并源码，使 target branch 提供精确 source identity，再从更新后的 target branch 执行 `source-artifact write --confirm`；renderer 返回 `aligned=true` 时禁止制造无语义的生成文件 PR；
  - `taskRunTemplate` 等运行事实归属 owning YAML，代码只负责校验和渲染；
  - desired 只来自 owning YAML 与共享 renderer，禁止从 live Pipeline/PipelineRun 反向导出；
  - `verify-runtime` 使用干净且 `HEAD` 等于完整 source commit 的独立 worktree；
  - 未声明 owner、worktree 证据不成立或运行面证据冲突时 fail-closed；
  - `plan|check|write` 必须检查内联 Pipeline 的 `command`、`args` 和 shell `script` 实际执行的仓库相对源码入口；入口缺失时在 source PR 前 fail-closed，不读取仓库外路径；
  - 错误和 drift 在默认、`--json`、`--full` 中都只能披露路径、类型、长度、SHA-256 或 URL fingerprint；
  - 禁止回显脚本、URL 凭据、查询参数、Authorization、Secret 和远端 stderr。
- PaC source-only closeout 必须使用目标侧结构化证据：
  - `g14-ci-plan` 的 source commit、affected/build/rollout 计数必须完整；
  - `collect-artifacts` 与 `gitops-promote` 必须同时明确 `no-build-no-rollout-plan`；
  - 三者一致时才允许返回 `no-runtime-change` 和 `retained` provenance；
  - 仍要求 PipelineRun 成功、原 Argo `Synced/Healthy`、runtime ready、sha256 digest pin 与 health ready；
  - 证据缺失、冲突或 source commit 不匹配必须 fail-closed，不得等价为 delivery disabled，也不得伪造新 artifact、GitOps revision 或 runtime source commit。
- PaC 自动事件的阶段判定必须分层：
  - webhook `202` 只表示 durable admission；以 branch、snapshot 和 delivery `committed` 证明 source authority 已提交；
  - source committed 后仍需唯一匹配 source commit 的 PipelineRun；PaC create timeout 不能表述为构建失败；
  - PipelineRun `Completed` 后必须检查 promote 结果；`skipped-stale-source` 表示沿最新后继 source commit 继续验收，不表示当前提交已部署；
  - GitOps push、Argo revision、Deployment ready 和原入口分别取证；任一上游成功不能替代下游收敛。
- BuildKit cache import/export 只属于加速能力：
  - 镜像构建、manifest/digest 和 push 仍可阻塞；
  - registry cache export 必须使用 BuildKit 原生 `ignore-error=true` 或等价非阻塞配置，禁止在镜像已成功发布后仅因 cache 写入抖动把 TaskRun 判失败。
- PaC `status|closeout|history` 的 `--json` 是有界 machine contract；`--full` 展开单条详情，`--raw` 才展开目标侧原始 payload。`history --id --full` 不得重复嵌套同一 rows/consumer payload或依赖 `/tmp/unidesk-cli-output` 才可读。
  - `history --json` 默认 list 只保留 run id、consumer、时间、终态、耗时、完整 source commit、delivery class/owner、env reuse、trace、首断点、typed error、读取 observation、warning 和只读 next；
  - source observation、classification、artifact、collector 与 TaskRun 详情只进入 `--id` 精确下钻或显式 `--full|--raw`；
  - 默认 JSON 超过输出预算并退化成 `outputTruncated` 时，优先继续收紧 projector，不要求操作者使用临时 dump。
- PaC `status` 必须在 `observability.readOnlyCapture.timeoutMs` 内完成：
  - 目标侧通过 `pac-status-progress` 披露最后阶段，CLI 将其投影为 `observation.remoteStage`；
  - PipelineRun 按 YAML 选中的 Repository CR label 做服务端 selector；TaskRun 与 Argo 原始对象各只读取一次并复用，禁止 status 为同一 run 串行读取每个 Pod 日志或重复读取 Argo；
  - YAML 总 capture 预算由调用侧作为整次观察的硬上限；单次读取上限可以使用同一预算，禁止按预估调用次数切分成更短的隐藏上限；
  - PipelineRun 读取 timeout 或失败必须返回 `pac-pipelinerun-read-failed`，不得改写为空数组并误报 `pipeline-missing`；
  - default ServiceAccount 的 Tekton mutation provenance 只执行一次 `kubectl auth can-i --list` 并在目标侧聚合，禁止串行枚举 verb/resource；
  - status 的 TaskRun 日志证据模式固定为 `taskrun-status-only`，需要日志时使用 id-specific 下钻；
  - 不得通过提高 YAML timeout 掩盖重复采集、同步日志或无界远端查询。
- PaC `debug-step --id <pipelinerun>` 必须读取目标侧真实 PipelineRun、TaskRun condition/result 与合同 Task 日志：
  - 默认输出每个 terminal role 的 presence、status、source 与首个断点；
  - 同时披露 artifact catalog、digest、GitOps commit 和 collector 读错；
  - 默认一次返回失败 TaskRun、step、container、exit code、termination reason 和脱敏有界日志尾，不再要求操作者另行拼接 `trans logs`；
  - 该入口只读且 `mutation=false`，不能创建 PipelineRun 或写 GitOps/runtime；
  - 未带 `--id` 时才只运行 evaluator fixture。
- PaC `diagnose-regression` 必须保持只读、轻量和有界：
  - 目标侧只聚合 PipelineRun 元数据，不默认读取所有 TaskRun 日志；
  - 默认只比较同一 `repositoryRef` 的 consumer lanes，并从 owning YAML 解析 owner，禁止按名称猜测；
  - 必须区分 `ok`、`incident` 与 `state=read-failed`，timeout、空响应和读取错误均在默认输出中可见；
  - `scopeAssessment=public-service` 或作用域未知时必须返回 `authorizationRequired=true`；
  - `rollbackCandidate` 只能包含 compare 范围、候选 commit、置信度与 review 要求，固定 `automatic=false`；
  - 禁止提供自动 revert、人工 PipelineRun、mirror sync、Argo sync、bootstrap 或 apply。
- GitHub/Git 相关 egress 必须走 YAML-first host proxy/sourceRef：branch-follower controller 读 `config/cicd-branch-followers.yaml#controller.source.githubSsh`，runtime legacy git-mirror 读 owning lane/control-plane YAML 的 host proxy 和 `githubTransport`，Gitea/PaC 迁移 lane 读 `config/platform-infra/gitea.yaml` 与 `config/platform-infra/pipelines-as-code.yaml`；禁止依赖未声明 host env、trans proxy、裸直连 GitHub 或 CLI 输出解析。
- Gitea/PaC lane 的 GitHub -> Gitea 自动同步由 owning YAML 渲染的 webhook bridge 与 durable inbox worker 承担：
  - receiver 验签并校验 GitHub payload 后，只有在 delivery 通过 fsync 与 atomic rename 写入 YAML 声明的 PVC inbox 后才能返回 HTTP `202 Accepted`；
  - `202 Accepted` 只证明 delivery 已持久接收，不证明 Gitea refs 已提交；状态必须分为 `accepted`、`processing`、`committed`、`failed`；
  - 只有同一 deliveryId 的 exact-after immutable snapshot 与 authority branch 经 atomic push 后重新读取 refs 证明一致，才能进入 `committed`；
  - 同 deliveryId 与同 payload 必须幂等，异 payload 必须返回 `409`；PVC 不可用或容量满必须返回 `503` 并使 readiness=false；
  - inbox worker 使用 YAML 声明的有界 backoff 自动重试，重启后恢复 `accepted` / `processing`；Caddy 只可在请求尚未持久化时做小于 10 秒的 body-safe 有界重试。
- Durable inbox 只是 webhook delivery 的持久接收与重试 journal，不是业务 source/ref 的第二份真相，也不得被 PaC、Tekton、GitOps、Argo 或 runtime 当作源码/read model。最终 source authority 仍只有 Gitea authority branch 与 immutable snapshot。默认只使用 `platform-infra gitea mirror webhook status` 观察 accepted -> committed 分层。会 POST hook test 的 mutation 测试入口已经删除；连通性只能通过真正只读的 status、GET 与 readiness 观察。平台 bootstrap 必须先落入 Git-backed YAML/controller/source，并由 PR 合并后的 source authority 状态、手动 plan 和手动 webhook 验收；禁止 Gitea -> GitHub 回写、轮询/read-model fallback、Gitea Actions/act_runner fallback 或第二 source authority。
- Gitea webhook/public-edge 自动链变更的 closeout：
  - 必须观察修复 PR 合并后的真实 delivery、rollout 和只读 status/GET/readiness 证据；
  - Secret、ConfigMap 或 public-edge 候选已生成不等于 connector Pod 与公网 route 已加载新配置；
  - 不得用人工 apply 或 hook test 补齐。
- Sentinel 内部 publish capability 的唯一真相是 `config/platform-infra/pipelines-as-code.yaml#capabilities.sentinelInternalPublish`，当前默认关闭。Pod env、ownerReferences、ServiceAccount 与 metadata 不能证明 creator；#1769 的 admission-owned provenance 落地前不得启用。`.tekton` 保持既有自动 `publish-current` 入口，禁止改成人工 publish。
- PaC PipelineRun 必须区分外层 `outer-pac-event`、内层 `inner-deterministic-publish` 与 `unknown`。只有唯一外层事件可驱动 latest/status/debug-step/closeout；内层只能作为未绑定执行观察，缺少 admission-owned 父子证据时不得按前缀推断。
- `cicd branch-follower` 对当前 PaC consumer 已退役，只保留 `status|events|logs` 与只读 `debug-step` 历史诊断。默认入口、任意 `--config` 和混合/未知 authority 都不能恢复 `apply|run-once|state-write` 等写能力，也不能猜测默认 node。
- k8s 运行面从拉取已构建镜像开始必须 0 Docker；CI 构建面可以使用 YAML 声明的原生构建工具，但不得把 Docker socket、Docker daemon 或 host Docker 带入运行面。
- 正式 CI/CD、publish、image build 和 rollout 必须走 Tekton Task/Pipeline/PipelineRun 承担 CI，并通过 GitOps/Argo 承担部署收敛；普通 Kubernetes Job 只允许用于 bounded helper、source sync、diagnostic、cleanup 或 bootstrap，不得作为正式发布、镜像构建或 rollout 入口。
- 未迁移的 legacy CI/CD 若仍保留人工入口，必须由单一受控命令完成 source sync、构建、发布、GitOps/Argo 收敛、runtime provenance 校验和 `/health` 端点验证。PaC migrated consumer 不得使用该 legacy 入口，只允许 `release plan` 后执行 `release trigger --confirm`。
- CI/CD 端到端 wall-clock 目标及预算只由 owning YAML 声明；PaC migrated consumer 从 CLI 手动 webhook 事件计时，legacy lane 从操作者触发受控命令计时，均到 runtime ready 且 `/health` 端点验证完成为止。
- CI/CD validation 阶段只能验证部署对象的 `/health` 端点和必要 provenance；禁止在 CI/CD gate 中运行 web-probe、Playwright、远程浏览器截图、用户路径 E2E 或等价重型业务探针。业务/用户入口验证只能作为发布后的独立 post-deploy validation 证据，不得阻塞 CI/CD 一键交付。
- 产品功能配置 schema 的 CI/CD 合同：
  - repo 内唯一约定路径固定为 `config/feature-config.schema.json`；
  - schema 固定使用 JSON Schema Draft 2020-12，并由 lockfile 锁定的完整结构化 validator 校验；禁止用正则、只检查顶层字段的浅层解析器或关闭整体 strict 代替；
  - schema 只描述产品功能配置，不得承载数据 authority、事件路径、投影实现或交付路径选择；
  - schema 的每个顶层 property 是一个规范产品配置键，值可以是对象，不强制使用大写 env 命名；
  - 每个顶层 property 必须声明唯一非空 `x-unidesk-feature`；同一功能只允许一个规范配置 property，禁止在 schema、renderer、Deployment env 或应用解析器中保留别名、反向变量或重复开关；
  - candidate snapshot 必须由正常 source-artifact 阶段从 owning YAML 或已渲染 workload 显式生成；禁止读取 runner `process.env` 作为产品配置 authority；
  - HWLAB、AgentRun 与 Sentinel consumer 必须复用同一 shared helper，并在正常 source-artifact/GitOps publish 路径执行，不得只挂到某个 consumer 的专属后处理；
  - CI/CD 必须检查 schema 语法、嵌套配置值匹配和功能到配置 property 的一对一关系，并输出有界 typed warning；输入快照缺失使用独立的 `feature-config-input-missing` warning，不得与 schema 非法混淆；
  - schema 缺失、非法、candidate 缺失、配置不匹配、重复 property、validator/依赖异常或 OTel 导出失败时，只允许记录 warning；embedded 命令必须以 `0` 退出，PipelineRun、artifact、GitOps promote、Argo reconcile、runtime rollout 和 `/health` closeout 必须继续；
  - schema 校验器只读，禁止写回配置、注入默认值、删除变量、关闭功能、切换架构路径或执行任何补救操作；运行时必须原样接收本次待发布配置；
  - schema warning 必须实际导出 CI/CD OTel span/event；endpoint、serviceName、sampling 和 exporter timeout 只读 `config/platform-infra/pipelines-as-code.yaml#observability` 与精确 repository params；零/多 repository 匹配或 exporter 配置漂移只增加 `blocking=false` warning，不得阻断 renderer 或滚动；
  - OTel exporter 自身失败继续输出 `blocking=false` warning；warning 同时进入 `status|history|debug-step` 的同构有界投影，但不得改变成功/失败终态。
- 任一 CI/CD 阶段或总耗时超过 owning YAML 预算时，不要继续死等或把超长等待视为正常；先输出阶段耗时分解，并优先从 env reuse、git mirror、BuildKit/cache、GitOps/Argo watch 和 runtime readiness 探测方向优化后再继续交付。
- 仅 legacy lane 的 node-scoped `trigger-current --wait` 可以把 source sync、pre/post flush、PipelineRun、GitOps/Argo、runtime readiness 和 `/health` closeout 放进同一端到端 YAML 预算；超预算时由 CLI 输出阶段分解、Argo target revision、runtime/public 状态和 TaskRun/Pod drill-down。PaC migrated consumer 禁止执行 `trigger-current`，也禁止手动串联状态、sync 或 flush 命令补齐交付。
- node-scoped `control-plane status` 可见性规则：
  - 必须立即输出 started/阶段，并按 owning YAML 输出 heartbeat；
  - 正常、总预算超时、中断和 worker 失败都要返回有界 closeout；
  - closeout 必须披露探针完成情况、进程组清理结果和脱敏的 worker 错误摘要；
  - 显式 `--json` 的 stdout 只允许一个合法 JSON 文档，progress 写入 stderr。
- 触发或验收 rollout 时必须绑定 lane、source commit、PipelineRun/GitOps revision、runtime ready 和 `/health` 端点验证结果；web-probe/Playwright 结果只能作为单独的 post-deploy 证据。
- CI/CD 状态、日志和事件查询必须减少 trans/SSH 传输：能在目标 NODE/k8s 内解析、聚合、裁剪的内容，必须在目标侧计算成短 JSON/table 摘要后再回传；禁止为了本地解析而把完整 ConfigMap、大对象、长日志或原始 API payload 透传回来。
- PaC history 范围必须显式且高效：
  - 未指定 `--consumer` 时汇总 target 全部 consumer，并按 namespace 复用 PipelineRun/TaskRun 读取；
  - 指定 `--consumer` 或可唯一归属的 `--id` 时只读取单 consumer 快路径；
  - 输出 `config.scope=target-summary|single-consumer`，不得静默退回默认 consumer。
- 退役 branch-follower 排障只允许使用 `state-read|controller-source|status-read|decide`、`status|events|logs` 等只读边界；`state-write`、gate、`run-once` 和自动 loop 不再是当前 PaC consumer 的修复或验收入口。
- 发布链单步测不通时，应在 Git-backed YAML、planner、controller 或源码中修复根因，并由修复 PR 合并后的新 plan 和手动 webhook/PaC 事件复测；不得用 branch-follower 写状态或补跑当前交付。
- CI/CD 排障中再次踩到已暴露的运行面坑、工具误用、镜像假设或状态可见性缺口时，必须先把长期规则写入本 skill/reference，再继续只读定位。
- CI/CD 运行面验收必须在目标 NODE/k8s 内计算短摘要；本机只用于源码阅读、编辑和静态合同测试，不能替代受控手动 webhook 产生的目标运行面证据。
- CI tools image 默认必须包含 `kubectl`：
  - `kubectl` 与其他构建工具统一由 owning YAML 的 tools image Dockerfile 声明并随镜像交付；
  - 镜像构建必须执行 `kubectl version --client` 自检；
  - 禁止在 PipelineRun、Pod 或 Job 启动后临时安装 `kubectl`；
  - 使用 tools image 的有界 CI helper、cleanup 或 bootstrap 可以直接调用 `kubectl`；
  - 产品业务镜像和长期 controller 不得仅因本规则新增对 `kubectl` 的运行时依赖。
- 一旦发现 CI/CD CLI 被误用且可能写入错误状态、产生伪证据或绕过目标运行面，必须立刻先把用法改成更符合直觉的公开入口并更新本 skill/reference，再继续验证或交付；不要只靠口头记忆、隐藏 flag、手动约定或后续小心来避免复发。内部 in-cluster 模式必须只由目标 k8s Job/Pod 调用，操作者从本机只能用公开入口提交目标侧 Job 或读取目标侧摘要。
- PaC migrated consumer 的旧手动 publish/debug 命令不得作为正式 closeout 引导；调查命令默认只能指向只读的 `platform-infra pipelines-as-code status|history`。`closeout` 仅保留只读兼容能力，不得作为主代理、子代理或操作者的 PR 合并后步骤。需要保留的旧 mutation 命令只能属于 YAML 明确的 legacy authority 或独立平台维护，不得标记或引导 manual recovery；单步确认的自动链缺陷必须回到 YAML/controller/源码修复。
- Secret 只通过 YAML sourceRef/targetKey 和受控 CLI 下发；输出只披露 presence/fingerprint。
- 平台 PostgreSQL Secret 状态判定：
  - YAML 声明的 Service 存在，且 EndpointSlice 或 ExternalName 路径有效时，连接桥即成立；
  - 同名 Endpoints 与 EndpointSlice 并存只能作为 `blocking=false` warning，禁止据此把已对齐的 Secret、OpenFGA 或 cloud-api 判为失败；
  - Secret、host、database 和 role 已对齐时不得继续输出 `ensure` 写入引导，动态 `next` 只保留必要的只读下钻。
- D601 独立 k3s 集群：
  - CI/CD、业务 renderer、PipelineRun 和 GitOps 不得写 k3s systemd unit，
    不得把 D601 注册为 NC01 agent，也不得创建跨地域 CNI 或共享 datastore。
  - D601 只走
    `platform-infra k3s-cluster plan|apply|status|smoke --target d601`；
    NC01 只走自己的 control-plane 入口，两者不得互相组合。
  - D601 server 的 YAML 摘要未变化且节点健康时禁止重装、重启或强写。
  - D601 默认是空集群。任何业务进入 D601 必须有独立 workload owning
    YAML 和显式 target，禁止继承 NC01 的 PaC、Tekton、Argo、GitOps、
    DaemonSet、namespace 或默认 placement。
  - D601 先通过 host proxy 让 server/containerd 出网，禁止公共 registry
    mirror。
  - 集群自有 artifact registry 的异地拉取是明确例外：
    - 内部 publish endpoint 保持唯一写入 authority；
    - 公网 HTTPS 只允许鉴权 `GET`/`HEAD`，不得成为 push、cache export 或删除入口；
    - D601 保持既有镜像引用，由集群 owning YAML 渲染 endpoint 与 SecretRef；
    - registry 大流量不得经过 Kubernetes 数据面，也不得使用 CDN 或公共镜像站；
    - bcrypt hash 必须以 Compose-safe 字面量写入 Secret source，且
      public-edge 用脱敏 material fingerprint 驱动凭据变更后的 recreate；
      候选校验不得用会保留引号的 `docker run --env-file` 改变 Secret 语义；
    - 验收统一走 `platform-infra k3s-cluster registry-smoke`，不手工 patch Caddy 或 containerd。
  - 跨地域 artifact 传输使用鉴权、只读的公网 HTTPS registry，不得通过
    Kubernetes Pod 网络、Service、DNS 或 VXLAN。
- 长命令用异步 job 或短轮询；不要长时间挂住 trans/ssh。
- Web 哨兵 YAML cadence 变更不新增发布 orchestrator：提交前用 `web-probe sentinel validate --local`；合并后用只读 `web-probe sentinel control-plane status --wait`。线上 desired schedule 必须来自 GitOps 清单，不能用操作者旧 worktree 的本地渲染值做阻塞门禁；收敛差异统一为非阻塞 warning。

## 何时读取 reference

- PR 自动合并、v0.2/v0.3 lane 差异：读 [references/pr-monitor.md](references/pr-monitor.md)。
- Legacy 手动触发、定点 PipelineRun/source commit、RBAC/Pipeline/Argo、node-scoped runtime lane：读 [references/control-plane.md](references/control-plane.md)。
- legacy git-mirror 退役核查：读 [references/git-mirror.md](references/git-mirror.md)。
- AgentRun/HWLAB env reuse、`IMAGE_STATUS=reused`、`ENV_REUSE=hit`、`skipped,skip=<n>` 或 PaC history/status 解释：读 [references/env-reuse.md](references/env-reuse.md)。
- JD01/NC01 Gitea+PaC 覆盖、旧 branch-follower/Gitea Actions POC 处置和只读观察顺序：读 [references/gitea-pac.md](references/gitea-pac.md)。
- Secret、observability、CI tools image、PipelineRun/PV 清理：读 [references/platform-ops.md](references/platform-ops.md)。
- AgentRun v0.1 或 YAML-only lane 部署：读 [references/agentrun.md](references/agentrun.md)。
- 退役 branch-follower 的 `status|events|logs|debug-step` 历史只读诊断：读 [references/branch-follower.md](references/branch-follower.md)。
- 生产事故、共同失败指纹、Tekton 大对象、Kine/SQLite 退化、快速恢复、回退决策或公共服务面边界：读 [references/incident-recovery.md](references/incident-recovery.md)。
