fix: add dev backend-core artifact consumer

This commit is contained in:
Codex
2026-05-21 09:02:16 +00:00
parent 9977f00621
commit add3b8d3f2
14 changed files with 238 additions and 67 deletions
+6 -4
View File
@@ -59,6 +59,7 @@ bun scripts/cli.ts artifact-registry render
bun scripts/cli.ts artifact-registry install
bun scripts/cli.ts artifact-registry status
bun scripts/cli.ts artifact-registry health
bun scripts/cli.ts artifact-registry deploy-service --service backend-core --env dev --commit <full-sha>
bun scripts/cli.ts artifact-registry deploy-service --service baidu-netdisk --commit <full-sha>
bun scripts/cli.ts artifact-registry deploy-service --service frontend --env prod --commit <full-sha>
bun scripts/cli.ts artifact-registry deploy-service --service frontend --env dev --commit <full-sha>
@@ -82,12 +83,13 @@ bun scripts/cli.ts artifact-registry deploy-service --service code-queue --env d
真实 `install` 必须是幂等动作:创建远端目录,写入 CLI 渲染出的 config/compose/unit,执行 `systemctl daemon-reload`,启用并启动 `unidesk-artifact-registry.service`,然后运行与 `health` 相同的验收检查。若远端文件 hash 与期望不一致,install 可以覆盖由本 CLI 管理的 unit/config/compose,但不得删除 registry storage。
`deploy-backend-core` 是旧兼容入口,当前作为标准路径已禁用。Production backend-core CD 必须使用 `bun scripts/cli.ts deploy apply --env prod --service backend-core --commit <full-sha>`,由 deploy reconciler 先执行共同的 artifact-consumer guardrail,再调用通用 `deploy-service` consumer。旧入口只能返回 structured deprecated 结果,不得绕过 `deploy apply --env prod`
`deploy-backend-core` 是旧兼容入口,当前作为标准路径已禁用。Backend-core CD 必须使用 `bun scripts/cli.ts deploy apply --env dev --service backend-core --commit <full-sha>` `bun scripts/cli.ts deploy apply --env prod --service backend-core --commit <full-sha>`,由 deploy reconciler 先执行共同的 artifact-consumer guardrail,再调用通用 `deploy-service` consumer。旧入口只能返回 structured deprecated 结果,不得绕过 `deploy apply --env ...`
`deploy-service` 是标准化后的最小通用 artifact consumer。它目前支持 `backend-core``baidu-netdisk`、prod/dev `frontend``decision-center``mdtodo``claudeqq``project-manager``oa-event-flow``code-queue-mgr``todo-note``findjob``pipeline``met-nonlinear``k3sctl-adapter`,以及 dev-only `code-queue`。所有路径都必须先通过 D601 registry 的 commit-pinned manifest 校验,再执行拉取、导入/retag、部署和健康验证;`code-queue --env prod` 必须返回 structured unsupported,不能回退到生产 artifact deploy、rollout 或 manifest 变更;`code-queue-mgr` 的 prod live apply 仍需 supervisor 单独确认,`met-nonlinear``k3sctl-adapter` 当前只提供 plan/dry-run
`deploy-service` 是标准化后的最小通用 artifact consumer。它目前支持 dev/prod `backend-core``baidu-netdisk`、prod/dev `frontend``decision-center``mdtodo``claudeqq``project-manager``oa-event-flow``code-queue-mgr``todo-note``findjob``pipeline``met-nonlinear``k3sctl-adapter`,以及 dev-only `code-queue`。所有路径都必须先通过 D601 registry 的 commit-pinned manifest 校验,再执行拉取、导入/retag、部署和健康验证;`code-queue --env prod` 必须返回 structured unsupported,不能回退到生产 artifact deploy、rollout 或 manifest 变更;`code-queue-mgr` 的 prod live apply 仍需 supervisor 单独确认,`met-nonlinear``k3sctl-adapter` 当前只提供 plan/dry-run
```bash
bun scripts/cli.ts artifact-registry deploy-service --service baidu-netdisk --commit <full-sha> --run-now
bun scripts/cli.ts artifact-registry deploy-service --service backend-core --env dev --commit <full-sha> --run-now
bun scripts/cli.ts artifact-registry deploy-service --service frontend --env prod --commit <full-sha> --run-now
bun scripts/cli.ts artifact-registry deploy-service --service frontend --env dev --commit <full-sha> --run-now
bun scripts/cli.ts artifact-registry deploy-service --env dev --service decision-center --commit <full-sha> --run-now
@@ -106,7 +108,7 @@ bun scripts/cli.ts artifact-registry deploy-service --env dev --service code-que
`code-queue-mgr` 是主 server Compose sidecar,不是 D601 Code Queue scheduler/runner。`artifact-registry deploy-service --env prod --service code-queue-mgr --commit <full-sha> --dry-run` 必须显示 target 仅为 `composeService=code-queue-mgr` / `containerName=code-queue-mgr-backend`,并在 `excludedTargets` 中说明不会触碰 `code-queue` scheduler、runner、任务、interrupt 或 cancel 状态。真实 prod apply 仍受 supervisor-only gate 保护;未经单服务授权不得执行非 dry-run apply。
dry-run 输出会暴露 registry probe URL、required labels、目标 image、部署形态、目标 Deployment 列表回滚信息,但不得读取或打印运行时密钥`baidu-netdisk` 是 PGDATA 备份链路依赖服务;它的 Compose artifact 路径会通过 provider-gateway Host SSH 把 `unidesk/baidu-netdisk:<commit>` 流式拉到 master serverretag 为 `baidu-netdisk``baidu-netdisk:<commit>`,在 canonical UniDesk 根目录使用 `providerGateway.upgrade.composeEnvFile` 指向的受控 env 文件写入 `UNIDESK_BAIDU_NETDISK_DEPLOY_*`,只 recreate `baidu-netdisk` service,并验证容器 image label 与 `/health.deploy.commit`。live apply 在 recreate 前必须确认受控 env 文件中存在 `UNIDESK_BAIDU_NETDISK_CLIENT_ID``UNIDESK_BAIDU_NETDISK_CLIENT_SECRET``UNIDESK_BAIDU_NETDISK_TOKEN_KEY`,输出只能包含 present/length/booleanrecreate 后必须验收 `/health.auth.configured``clientIdConfigured``clientSecretConfigured``tokenKeyConfigured``loggedIn` 全部为 true,否则返回失败或 degraded,并提示先恢复 env、单服务 recreate、再验证 `microservice health baidu-netdisk``findjob``pipeline``met-nonlinear` 的 D601 direct Compose 路径在 D601 本机验证 registry manifest、pull image、retag stable image、写入 `UNIDESK_*_DEPLOY_*` labels/env,并用 `docker compose up -d --no-build --no-deps --force-recreate <service>` 重新拉起对应 compose service;其中 `met-nonlinear` 当前因为 registered Dockerfile 和 long-running service contract 不一致而 live deploy blocked。`k3sctl-adapter` 是基础设施控制桥,只做 plan/dry-run,真实生产部署需要 supervisor 单独确认。`frontend --env prod` 使用同一 Compose artifact consumer,流式拉取 `unidesk/frontend:<commit>`retag 为 `unidesk-frontend``unidesk-frontend:<commit>`,写入 `UNIDESK_FRONTEND_DEPLOY_*`,只 recreate `frontend` service,并验证 image label 与 `/health.deploy.commit``frontend --env dev``decision-center``mdtodo``claudeqq` 和 dev `code-queue` 的 k3s 路径会在 D601 上验证 commit image、导入 native k3s containerd、更新 Deployment image/env/annotations,并通过 Kubernetes API service proxy 验证 `/health` 中的 live commit 与 requested commitdev frontend 还会在 rollout 前把主 server `config.json.auth` 同步到 `unidesk-dev` Secret/ConfigMap。`decision-center --env dev` 落到 `unidesk-dev/decision-center-dev`prod 落到 `unidesk/decision-center``mdtodo``claudeqq` 使用同样的 dev 后 prod k3s consumer 结构。`code-queue --env dev` 只更新 `unidesk-dev` 中的 scheduler/read/write/provider-egress-proxy dev Deploymentsprod 没有 consumer target。D601 direct Compose consumer 与 k3s-managed consumer 的区别是:前者只接触 D601 Docker/Compose 项目和私有 backend health,不创建 Kubernetes 对象;后者只通过 native k3s Deployment/Service、containerd import 和 Kubernetes API service proxy 验证 live commit。回滚信息通过同一 artifact consumer 的 `rollback` 字段暴露,提示操作者重新对一个旧 commit 运行相同命令,而不是切回 legacy maintenance-channel 构建。
dry-run 输出会暴露 registry probe URL、required labels、目标 image、部署形态、目标 Deployment 列表回滚信息,以及结构化 `registry``source``build` 字段;`registry.digest` 在 dry-run 中为 `null``digestSource` 指明真实 digest 来自 live registry manifest HEAD`build.willCompile``build.willRunCargoBuild``build.willRunDockerBuild``build.willRunDockerComposeBuild` 必须为 false。dry-run 不得读取或打印运行时密钥。`backend-core --env dev` 使用 `ci publish-backend-core` 产出的 `127.0.0.1:5000/unidesk/backend-core:<commit>`,导入 D601 native k3s containerd,更新 `unidesk-dev/backend-core-dev` Deployment,设置 image/env/annotations,并通过 Kubernetes API service proxy 验证 `/health.deploy.commit``deploy.requestedCommit`;CD 阶段不得运行 Rust 编译或 Docker build`baidu-netdisk` 是 PGDATA 备份链路依赖服务;它的 Compose artifact 路径会通过 provider-gateway Host SSH 把 `unidesk/baidu-netdisk:<commit>` 流式拉到 master serverretag 为 `baidu-netdisk``baidu-netdisk:<commit>`,在 canonical UniDesk 根目录使用 `providerGateway.upgrade.composeEnvFile` 指向的受控 env 文件写入 `UNIDESK_BAIDU_NETDISK_DEPLOY_*`,只 recreate `baidu-netdisk` service,并验证容器 image label 与 `/health.deploy.commit`。live apply 在 recreate 前必须确认受控 env 文件中存在 `UNIDESK_BAIDU_NETDISK_CLIENT_ID``UNIDESK_BAIDU_NETDISK_CLIENT_SECRET``UNIDESK_BAIDU_NETDISK_TOKEN_KEY`,输出只能包含 present/length/booleanrecreate 后必须验收 `/health.auth.configured``clientIdConfigured``clientSecretConfigured``tokenKeyConfigured``loggedIn` 全部为 true,否则返回失败或 degraded,并提示先恢复 env、单服务 recreate、再验证 `microservice health baidu-netdisk``findjob``pipeline``met-nonlinear` 的 D601 direct Compose 路径在 D601 本机验证 registry manifest、pull image、retag stable image、写入 `UNIDESK_*_DEPLOY_*` labels/env,并用 `docker compose up -d --no-build --no-deps --force-recreate <service>` 重新拉起对应 compose service;其中 `met-nonlinear` 当前因为 registered Dockerfile 和 long-running service contract 不一致而 live deploy blocked。`k3sctl-adapter` 是基础设施控制桥,只做 plan/dry-run,真实生产部署需要 supervisor 单独确认。`frontend --env prod` 使用同一 Compose artifact consumer,流式拉取 `unidesk/frontend:<commit>`retag 为 `unidesk-frontend``unidesk-frontend:<commit>`,写入 `UNIDESK_FRONTEND_DEPLOY_*`,只 recreate `frontend` service,并验证 image label 与 `/health.deploy.commit``frontend --env dev``decision-center``mdtodo``claudeqq` 和 dev `code-queue` 的 k3s 路径会在 D601 上验证 commit image、导入 native k3s containerd、更新 Deployment image/env/annotations,并通过 Kubernetes API service proxy 验证 `/health` 中的 live commit 与 requested commitdev frontend 还会在 rollout 前把主 server `config.json.auth` 同步到 `unidesk-dev` Secret/ConfigMap。`decision-center --env dev` 落到 `unidesk-dev/decision-center-dev`prod 落到 `unidesk/decision-center``mdtodo``claudeqq` 使用同样的 dev 后 prod k3s consumer 结构。`code-queue --env dev` 只更新 `unidesk-dev` 中的 scheduler/read/write/provider-egress-proxy dev Deploymentsprod 没有 consumer target。D601 direct Compose consumer 与 k3s-managed consumer 的区别是:前者只接触 D601 Docker/Compose 项目和私有 backend health,不创建 Kubernetes 对象;后者只通过 native k3s Deployment/Service、containerd import 和 Kubernetes API service proxy 验证 live commit。回滚信息通过同一 artifact consumer 的 `rollback` 字段暴露,提示操作者重新对一个旧 commit 运行相同命令,而不是切回 legacy maintenance-channel 构建。
`status``health` 通过:
@@ -154,7 +156,7 @@ docker compose -p unidesk-artifact-registry -f /home/ubuntu/.unidesk/artifact-re
6. Compose runtime retag 为 Compose 使用的镜像名,并执行 `docker compose up -d --no-build --no-deps --force-recreate <service>`k3s runtime 设置 Deployment image/env/annotations 并等待 rollout。
7. 部署后通过 image label、runtime env、health payload 验证 live commit。
Baidu Netdisk is the first main-server direct user-service sample in this flow. Its dev validation command and prod CD command both consume `127.0.0.1:5000/unidesk/baidu-netdisk:<commit>` and must not build source on the master server. Frontend is the standard UniDesk UI artifact sample: CI publishes `127.0.0.1:5000/unidesk/frontend:<commit>`, production CD consumes that artifact into the master-server Compose `frontend` service, and dev CD consumes the same artifact into D601 native k3s `frontend-dev`. Project Manager, OA Event Flow and Todo Note use the same master-server Compose artifact-consumer shape as Baidu Netdisk, with `project-manager-backend`, `oa-event-flow-backend` and `todo-note-backend` as the runtime containers; Todo Note keeps its external source repository and requires a pre-existing `127.0.0.1:5000/unidesk/todo-note:<commit>` artifact. Its consumer injects `UNIDESK_TODO_NOTE_DEPLOY_*` runtime metadata and the container health probe combines `/api/health` with that metadata before enforcing `deploy.commit` / `deploy.requestedCommit`. Code Queue Manager is supported as an artifact consumer for validation, but prod live apply is supervisor-gated. Neither path may use `server rebuild frontend`, dirty source, mutable `latest`, or target-side frontend source builds as release truth. Decision Center, MDTODO and ClaudeQQ follow the same artifact-consumer pattern in both dev and prod, except the runtime target is native k3s on D601 instead of the master-server Compose stack. Dev `code-queue` is a deliberately narrower consumer: it validates only the `unidesk-dev` Code Queue execution slice and has no prod target. The k3s consumer must check the registry manifest, pull the commit-pinned image, import it into `/run/k3s/containerd/containerd.sock`, set the Deployment image to the commit tag, stamp `UNIDESK_DEPLOY_*` env/annotations, verify health through the Kubernetes API service proxy, and reject an old healthy revision if the live commit or requested commit does not match.
Baidu Netdisk is the first main-server direct user-service sample in this flow. Its dev validation command and prod CD command both consume `127.0.0.1:5000/unidesk/baidu-netdisk:<commit>` and must not build source on the master server. Backend-core is the Rust artifact sample: CI publishes `127.0.0.1:5000/unidesk/backend-core:<commit>`, dev CD consumes it into D601 native k3s `backend-core-dev`, and prod CD consumes it into the master-server Compose `backend-core` service. Frontend is the standard UniDesk UI artifact sample: CI publishes `127.0.0.1:5000/unidesk/frontend:<commit>`, production CD consumes that artifact into the master-server Compose `frontend` service, and dev CD consumes the same artifact into D601 native k3s `frontend-dev`. Project Manager, OA Event Flow and Todo Note use the same master-server Compose artifact-consumer shape as Baidu Netdisk, with `project-manager-backend`, `oa-event-flow-backend` and `todo-note-backend` as the runtime containers; Todo Note keeps its external source repository and requires a pre-existing `127.0.0.1:5000/unidesk/todo-note:<commit>` artifact. Its consumer injects `UNIDESK_TODO_NOTE_DEPLOY_*` runtime metadata and the container health probe combines `/api/health` with that metadata before enforcing `deploy.commit` / `deploy.requestedCommit`. Code Queue Manager is supported as an artifact consumer for validation, but prod live apply is supervisor-gated. Neither path may use `server rebuild frontend`, dirty source, mutable `latest`, or target-side frontend source builds as release truth. Decision Center, MDTODO and ClaudeQQ follow the same artifact-consumer pattern in both dev and prod, except the runtime target is native k3s on D601 instead of the master-server Compose stack. Dev `code-queue` is a deliberately narrower consumer: it validates only the `unidesk-dev` Code Queue execution slice and has no prod target. The k3s consumer must check the registry manifest, pull the commit-pinned image, import it into `/run/k3s/containerd/containerd.sock`, set the Deployment image to the commit tag, stamp `UNIDESK_DEPLOY_*` env/annotations, verify health through the Kubernetes API service proxy, and reject an old healthy revision if the live commit or requested commit does not match.
Main-server direct production dry-runs for the user-service matrix must be enough to review the blast radius before any live apply. `artifact-registry deploy-service --env prod --service <id> --commit <full-sha> --dry-run` is non-mutating and reports this fixed target shape:
+4 -4
View File
@@ -94,17 +94,17 @@ This means the CI service can read existing tasks, Trace summaries, Trace steps
## Backend-Core Artifact Publication
backend-core production image creation belongs to a manual D601-side artifact producer action, not to master server CD and not to a CI/CD bootstrap self-test. The purpose is to keep Rust compilation, Docker build cache, dependency downloads and image push on the higher-resource D601 side while leaving production deployment with a small pull/recreate/verify surface.
backend-core image creation belongs to a manual D601-side artifact producer action, not to master server CD, dev CD, or a CI/CD bootstrap self-test. The purpose is to keep Rust compilation, Docker build cache, dependency downloads and image push on the higher-resource D601 side while leaving dev/prod deployment with a small pull/import-or-recreate/verify surface.
The CI artifact task must follow these rules:
- Input revision comes from pushed Git and is resolved to a full 40-character commit. A dirty worktree or unpushed local tree must never be used as the image source.
- Source fetch for this artifact uses the existing D601 GitHub SSH deploy identity and the node-local provider-gateway WS egress proxy at `http://127.0.0.1:18789`. D601 prepares a commit-pinned source export under `/home/ubuntu/.unidesk/ci/backend-core-artifacts/<commit>` before creating the PipelineRun; Tekton consumes that prepared source through a read-only hostPath and must not clone GitHub itself, mount GitHub credentials, use an in-cluster Git mirror, or accept an operator-uploaded source tree.
- The source checkout, Rust build and Docker build run on D601 CI infrastructure. The master server must not run `cargo build`, `docker compose build backend-core` or `server rebuild backend-core` as part of production backend-core deployment.
- The source checkout, Rust build and Docker build run on D601 CI infrastructure. The master server and CD consumers must not run `cargo build`, `docker build`, `docker compose build backend-core` or `server rebuild backend-core` as part of backend-core deployment.
- The image is tagged with the source commit, for example `unidesk/backend-core:<commit>`, and pushed to the D601 artifact registry as `127.0.0.1:5000/unidesk/backend-core:<commit>`.
- The image must carry at least `unidesk.ai/service-id=backend-core`, `unidesk.ai/source-repo`, `unidesk.ai/source-commit` and `unidesk.ai/dockerfile=src/components/backend-core/Dockerfile`.
- Publication must fail if the D601 artifact registry is not healthy. It must not fall back to a third-party registry or a mutable `latest` tag.
- CI output must include the common `artifactSummary` fields defined above. `artifactSummary.imageRef` and `artifactSummary.digestRef` are deployment inputs for later CD, but CI must not restart production Compose services, call production `deploy apply`, mutate production namespaces, or change `deploy.json`.
- CI output must include the common `artifactSummary` fields defined above. `artifactSummary.imageRef` and `artifactSummary.digestRef` are deployment inputs for later CD, but CI must not restart dev/prod services, call `deploy apply`, mutate runtime namespaces, or change `deploy.json`.
The artifact registry contract and CD consumption path are defined in `docs/reference/artifact-registry.md`. CI is the producer of the backend-core image artifact; CD is only the consumer.
@@ -204,7 +204,7 @@ Publish a backend-core artifact for production CD:
bun scripts/cli.ts ci publish-backend-core --commit <full-sha> --wait-ms 1200000
```
This command creates the `unidesk-backend-core-artifact-publish` Tekton PipelineRun. It is a CI producer action only: it may build and push `127.0.0.1:5000/unidesk/backend-core:<commit>`, but it must not recreate the master server container. Production deployment is triggered separately with `deploy apply --env prod --service backend-core --commit <full-sha>`.
This command creates the `unidesk-backend-core-artifact-publish` Tekton PipelineRun. It is a CI producer action only: it may build and push `127.0.0.1:5000/unidesk/backend-core:<commit>`, but it must not recreate dev or prod runtime containers. Dev deployment is triggered separately with `deploy apply --env dev --service backend-core --commit <full-sha>`; production deployment is triggered separately with `deploy apply --env prod --service backend-core --commit <full-sha>`.
Publish a user-service artifact:
+8 -8
View File
@@ -135,9 +135,9 @@ This table freezes the boundary between standard artifact services, upstream ima
| `server rebuild filebrowser*`, `database`, `code-queue`, `k3sctl-adapter`, unknown services | `allowed-remove-later` for silent fallback only | Historically the CLI threw a generic usage error; no valid main-server Compose rebuild exists for these objects. | Structured `unsupported-server-rebuild` result; no job creation, no source build, no Compose mutation. | Operators must use documented upstream digest, k3s artifact, bridge repair, or manual-risk path instead. | Generic errors can lead operators to invent hand-built fallback commands. | Silent/generic fallback is removed; do not delete the real upstream/bootstrap runtime paths. |
| `deploy apply --env prod` unsupported services | `needs-manual` | Environment-ref prod apply reads `origin/master:deploy.json`; services without reviewed prod artifact consumers return structured unsupported. | Add service-specific CI producer, D601 registry artifact, prod consumer, and live commit/digest verification before enabling. | Silent target-side builds would bypass registry, dirty-worktree, and live verification guardrails. | Not removable as a class; enable per service only after review. |
| Local-manifest `deploy apply --file ...` for reviewed prod artifact consumers | `allowed-remove-later` | CLI blocks reviewed prod artifact consumers before source materialization and points to `deploy apply --env prod --service <id>`. | Environment-ref deploy and artifact consumer only for standard production. | Confirm no recovery runbook requires local-manifest prod apply; provide rollback via registry. | Dirty local `deploy.json` or target-side source build can become production truth. | Allow removing or further degrading after recovery runbooks move to env-ref artifacts. |
| D601 target-side build path for dev `backend-core` | `bootstrap-keep` | `deploy apply --env dev --service backend-core` builds on D601 and rolls out only `unidesk-dev`. | Keep as controlled dev/Rust boundary until backend-core dev artifact consumer replaces it. | D601 CI artifact publication, dev consumer, Rust check/build parity, and rollback evidence. | Removing it can block Rust validation on the resource-appropriate host. | Keep; not removable next stage. |
| D601 target-side build path for dev `backend-core` | `allowed-remove-later` | Replaced by `deploy apply --env dev --service backend-core` artifact consumer, which imports `127.0.0.1:5000/unidesk/backend-core:<commit>` into `unidesk-dev/backend-core-dev` without compiling. | Keep only structured no-build artifact consumer; remove stale target-side callers/docs. | D601 CI artifact publication, dev consumer, Rust check/build parity, and rollback evidence. | Any fallback rebuild could bypass the CI artifact and hide Rust build failures. | Legacy path is no longer the standard dev route. |
| D601 maintenance-channel direct deploy for non-bridge services | `allowed-remove-later` | Direct provider `host.ssh` build/apply is blocked for normal D601 services; `codex deploy` is disabled. | Only artifact consumers or reviewed native bootstrap may mutate D601 services. | Confirm no supported runbook still calls the disabled path; keep structured unsupported output. | A second deploy control plane can bypass registry artifacts and k3s verification. | Remove stale callers/docs after no references remain. |
| `artifact-registry deploy-backend-core` | `allowed-remove-later` | Compatibility name returns a structured deprecated result; replacement is `deploy apply --env prod --service backend-core`. | Use only deploy reconciler entry for backend-core prod CD. | All callers and docs stop using the compatibility action. | Bypasses common deploy guardrails if re-enabled casually. | Remove compatibility after callers are migrated. |
| `artifact-registry deploy-backend-core` | `allowed-remove-later` | Compatibility name returns a structured deprecated result; replacement is `deploy apply --env dev|prod --service backend-core`. | Use only deploy reconciler entry for backend-core CD. | All callers and docs stop using the compatibility action. | Bypasses common deploy guardrails if re-enabled casually. | Remove compatibility after callers are migrated. |
| `k3sctl-adapter` | `bootstrap-keep` | D601 direct Compose control bridge outside k3s; artifact consumer is plan/dry-run only and live prod apply needs supervisor confirmation. | Keep outside the k3s fault domain; optionally publish artifact for controlled upgrade, but retain bridge repair. | Supervisor-approved live upgrade path, adapter health/control-plane validation, and rollback without losing Kubernetes access. | Removing or moving it into k3s can remove the bridge needed to repair k3s. | Keep; not removable next stage. |
| Maintenance SSH / manual Docker / manual k3s commands | `needs-manual` | Available through provider-gateway Host SSH, WSL SSH, manual Docker, and native k3s commands for repair and investigation. | Explicit maintenance-only runbooks with bounded commands, no silent source builds, no dirty worktree release truth, and no default CD fallback. | For each manual entry, document owner, trigger, rollback, volume/scope safety, and replacement artifact path. | Manual state can become undocumented production truth or destroy bootstrap access if over-cleaned. | Do not delete globally; constrain and document per path. |
| Dirty worktree, mutable `latest` tag, hand-mutated container state | `allowed-remove-later` as release truth | These may exist as local operator state or Docker cache, but they are not valid deployment evidence. | Standard releases use `deploy.json` commit, commit-tagged or digest-pinned images, image labels, and live commit/digest verification. | Runtime label checks, digest pins, env-ref deploy, and runbooks that reject `latest` and dirty worktree inputs. | Reproducibility and rollback are lost; a healthy old or hand-built container may be accepted accidentally. | Remove as accepted release evidence; keep only as diagnostic observations. |
@@ -148,12 +148,12 @@ This table freezes the boundary between standard artifact services, upstream ima
| --- | --- | --- | --- |
| `deploy apply --env prod` for services without a reviewed artifact consumer | Must stay disabled/degraded | returns structured unsupported and refuses maintenance-channel fallback | enable only after each service has a documented artifact producer, dev consumer, prod consumer and live verification |
| Local-manifest `deploy apply` for prod artifact consumers (`backend-core`, `frontend`, `baidu-netdisk`, `decision-center`) | Must stay disabled/degraded as a standard prod path | blocked before source build; operator is pointed to `deploy apply --env prod` | remove only after all production deploys use env-ref artifact consumers and no recovery runbook depends on local manifests |
| `artifact-registry deploy-backend-core` | Legacy compatibility entry | returns structured deprecated result; replacement is `deploy apply --env prod --service backend-core` | remove after callers and docs use only `deploy apply --env prod` |
| `artifact-registry deploy-backend-core` | Legacy compatibility entry | returns structured deprecated result; replacement is `deploy apply --env dev|prod --service backend-core` | remove after callers and docs use only `deploy apply --env dev|prod` |
| `server rebuild frontend` and `server rebuild baidu-netdisk` | Maintenance / non-standard | docs classify as maintenance-only; standard release requires CI artifact plus dev/prod artifact consumer | keep until recovery runbooks have equivalent pull-only repair commands |
| `server rebuild backend-core` | Diagnostic/recovery only; not Rust iteration or prod CD | docs forbid Rust iteration and prod backend-core artifact CD through this command | keep for bootstrap/recovery until backend-core artifact CD and rollback are proven under outage conditions |
| `server rebuild dev-frontend-proxy`, `code-queue-mgr`, `project-manager`, `oa-event-flow`, `todo-note`, `provider-gateway` on main-server Compose | Bootstrap / recovery / diagnostic | still serialized through Compose lock and post-up validation | reassess service by service after artifact consumers exist |
| `provider.upgrade mode=schedule` for provider-gateway | Must be retained | protected upgrade path with validation; Host SSH self-rebuild remains forbidden | do not delete; it is the provider-gateway recovery path |
| D601 direct `docker build`, `kubectl apply`, `docker compose up --build` used by deploy executor for allowed dev/backend bootstrap and native k3s setup | Bootstrap / recovery / controlled dev | limited to allowed target-side executor, native k3s initialization, and dev backend-core; Code Queue prod is not enabled | convert only after artifact consumers or native bootstrap replacements exist |
| D601 direct `docker build`, `kubectl apply`, `docker compose up --build` used by deploy executor for native k3s setup or approved recovery | Bootstrap / recovery | limited to native k3s initialization or documented recovery; dev backend-core CD is now artifact-only; Code Queue prod is not enabled | convert only after artifact consumers or native bootstrap replacements exist |
| D601 direct Code Queue / old `codex deploy` | Must stay disabled/degraded | compatibility command throws; docs classify direct deployment as forbidden | wait for controlled Code Queue dev/prod CD worker |
| File Browser `docker run` image-only path | Needs later worker | now cataloged as upstream-image consumer; no CI Dockerfile build allowed | implement digest-resolved pull-only/mirror CD before treating it as standard deployment |
@@ -176,13 +176,13 @@ This table freezes the boundary between standard artifact services, upstream ima
| `unsupported-server-rebuild` | `bun scripts/cli.ts server rebuild filebrowser` and `bun scripts/cli.ts server rebuild database` return `ok=false`, `error=unsupported-server-rebuild`, classification, replacement path and allowed services | accidental source-build/Compose fallback for upstream images, database, k3s/control bridges and unknown services | keep; it removes only silent/generic fallback, not bootstrap or maintenance runtime paths |
| backend-core/code-queue prod boundary | docs and deploy support matrix allow backend-core and D601 Code Queue only in dev validation for this phase | accidental prod validation entrypoints for backend-core or Code Queue | do not add executable prod test/deploy validation in this precheck |
The guarded-but-not-deletable paths are: `server rebuild backend-core`, `server rebuild frontend`, `server rebuild baidu-netdisk`, provider-gateway protected upgrade, native k3s bootstrap, k3sctl-adapter bridge repair, File Browser provider-local docker-run repair, and D601 dev/backend target-side rollout. They remain because they are bootstrap, recovery, diagnostic, or controlled dev paths; deleting them requires replacement runbooks or reviewed artifact consumers.
The guarded-but-not-deletable paths are: `server rebuild backend-core`, `server rebuild frontend`, `server rebuild baidu-netdisk`, provider-gateway protected upgrade, native k3s bootstrap, k3sctl-adapter bridge repair, and File Browser provider-local docker-run repair. Dev backend-core target-side rollout is no longer a standard guarded path; its replacement is the D601 registry artifact consumer, and stale target-side callers/docs should be removed once no runbook references remain.
## Safety Boundary
CI may build images, push to the D601 loopback registry and report immutable digests. CI must not run production CD, call `deploy apply` for production, mutate production namespaces, recreate production Compose services or update `deploy.json`.
backend-core and D601 `code-queue` remain restricted to dev image validation in this phase. Any future production rollout for them must be implemented as an explicit CD consumer change, not as a CI producer side effect.
backend-core now has explicit dev/prod artifact consumers; CI still only produces the image and must not deploy it as a side effect. D601 `code-queue` remains restricted to dev image validation in this phase. Any future production rollout for Code Queue must be implemented as an explicit CD consumer change, not as a CI producer side effect.
### Code Queue Dry-Run Delivery Boundary
@@ -207,7 +207,7 @@ The test checks that dev targets only `unidesk-dev`, prod exposes no runtime dep
## Validation Boundary
This precheck uses lightweight parsing and dry-run evidence only. It intentionally does not run full `check`, e2e, Playwright, or other broad browser/runtime test suites on the master server because those are outside the precheck scope and may exceed master-server resource limits. `backend-core` and D601 `code-queue` production validation are also out of scope; backend-core dev rollout can be attempted only through the existing D601 dev path, and a provider-offline result is an infrastructure blocker rather than permission to validate production.
This precheck uses lightweight parsing and dry-run evidence only. It intentionally does not run full `check`, e2e, Playwright, or other broad browser/runtime test suites on the master server because those are outside the precheck scope and may exceed master-server resource limits. D601 `code-queue` production validation is out of scope. backend-core dev rollout must use the artifact consumer path, and a provider-offline result is an infrastructure blocker rather than permission to validate production.
The structured read-only preflight entrypoints are `artifact-registry status|health` and `ci publish-user-service --dry-run`. Remote runners may call them through the frontend passthrough path, and the result must classify missing backend-core, database, provider or registry channels as `runnerDisposition=infra-blocked`. The detailed probe list remains in `missingChannels`; the stable runner-facing domain list is `missingControlChannels` with only `backend-core`, `database`, `provider` and `registry`. Those cases are infrastructure blockers, not business failures and not a license to retry a real publish. A non-dry-run publish may be attempted only where `controlledPublish` points: D601 CI, namespace `unidesk-ci`, PipelineRun `unidesk-user-service-artifact-publish`.
@@ -217,7 +217,7 @@ This matrix describes the next promotion stage after dry-run coverage is in plac
| Service class | Target branch | CI current state | CD current state | DEV acceptance | PROD acceptance | Blockers | Suggested model |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `backend-core` | `master` | source-build supported | dev target-side rollout only | Rust build + dev rollout proof on D601; no prod gate in this phase | not authorized | keep Rust iteration on D601 dev path; no prod validation | `GPT-5.5` |
| `backend-core` | `master` | source-build supported through `ci publish-backend-core` | dev + prod artifact consumer | dev artifact rollout to `unidesk-dev/backend-core-dev` with no CD compile | prod artifact recreate with live commit proof | CI resource, registry artifact, and runtime health evidence | `GPT-5.5` |
| `code-queue` | `master` | source-build supported, dev-only | dev-only k3s consumer | dev artifact validation for `unidesk-dev` scheduler/read/write/provider-egress-proxy | not implemented; must remain unsupported | production boundary, hostPath/source contract, scheduler/egress dependency health | `GPT-5.5` |
| `frontend` | `master` | source-build supported | dev + prod artifact consumer | commit-pinned dev rollout and `/health.deploy.commit` | commit-pinned prod recreate and UI route verification | none beyond standard artifact/CD checks | `GPT-5.5` |
| `baidu-netdisk` | `master` | source-build supported | dev + prod artifact consumer | pull-only dev validation plus auth and proxy checks | pull-only prod recreate plus live commit and proxy checks | secret presence and `/health.auth` gate | `GPT-5.5` |
+4 -4
View File
@@ -25,7 +25,7 @@ CLI 可以从 `master` 快速演进,但必须兼容 `deploy.json` 固定的 CI
- `microservice list/status/health/diagnostics/tunnel-self-test/proxy` 通过 backend-core 内网 API 管理挂载在计算节点 Docker 或 k3s 控制面中的用户服务(底层命令名仍为 microservice);`health``diagnostics``tunnel-self-test``proxy` 会走真实 backend-core -> provider-gateway 或 k3sctl-adapter -> 节点服务链路,`proxy` 支持受控 JSON 请求体并对超大响应 body 默认输出有界预览,规则见 `docs/reference/microservices.md`
- `decision upload/list/show/health` 通过 backend-core 用户服务代理访问 D601 k3s Decision Center,用于上传会议记录/决议 Markdown、列出权威记录、查看详情和健康检查;`decision list` 默认只返回摘要并省略完整 Markdown body,需要排查大正文时显式加 `--include-body`。正式文书字段通过 records 模型一等字段返回和查询:`--doc-no DC-...``--doc-type DCSN|GOAL|PLAN|RPRT|ACTN|ISSU|RETR|RQST|RESP|MINS``--doc-priority P0|P1|P2|P3``--year YYYY``--signer``--issued-at``--effective-scope``--supersedes``--superseded-by``show``requirement update` 可使用 `id``docNo``decision requirement list/create/upsert/update/show` 在同一 records 模型上管理 `goal|decision|blocker|debt|experiment` 需求记录,`docNo` 唯一,未传 `--doc-no` 但提供 `--doc-type/--doc-priority/--year` 时由服务分配下一个序号。它们不得直连 D601 Service、NodePort 或 provider-gateway 业务 HTTP。
- `decision diary import <markdown-file>` 将带 `# YYYY年M月D日``# YYYY-MM-DD``# YYYY/M/D` 标题的工作日志拆成每天一篇 Markdown 日记,按 `YYYY-MM/YYYY-MM-DD.md` 虚拟路径写入 Decision Center PostgreSQL`decision diary list/history` 默认只返回摘要,需要完整 Markdown 时显式加 `--include-body``decision diary show <YYYY-MM-DD|id> [--source-file path]` 查看单日正文,`--source-file` 用于同一天存在多个导入来源时精确选择;`decision diary edit|upsert <YYYY-MM-DD|id> --body-file <path> [--title text] [--source-file path] [--tag tag]` 通过 `PUT /api/diary/entries/:idOrDate` 创建当天或历史条目并编辑既有条目。
- `deploy check/plan/apply` 默认从根目录 `deploy.json` 读取服务 repo 与 commit 期望状态,join `config.json` 和现有 manifest 后使用 target-side build 单一路径校验更新已支持目标;`deploy plan --env dev|prod` 只从 `origin/master:deploy.json#environments.<env>` 读取 manifest 并输出 dry-run 环境计划,不使用本地 dirty worktree;当前 `deploy apply --env dev` 支持 D601 `backend-core` target-side rollout,以及 `frontend`/`baidu-netdisk`/`decision-center` artifact consumers`findjob`/`pipeline`/`met-nonlinear` 为 D601 direct Compose artifact consumers`k3sctl-adapter` 只提供 plan/dry-rundev desired-state smoke 使用 `ci run-dev-e2e`;规则见 `docs/reference/deploy.md``docs/reference/dev-environment.md``docs/reference/dev-ci-runner.md``deploy apply --env prod` 同时覆盖 `findjob``pipeline` 的 pull-only Compose CD,但 `met-nonlinear` 仍然只允许 dry-run/plan`k3sctl-adapter` 只允许 plan/dry-run。
- `deploy check/plan/apply` 默认从根目录 `deploy.json` 读取服务 repo 与 commit 期望状态,join `config.json` 和现有 manifest 后使用 target-side build 或 reviewed artifact consumer 校验/更新已支持目标;`deploy plan --env dev|prod` 只从 `origin/master:deploy.json#environments.<env>` 读取 manifest 并输出 dry-run 环境计划,不使用本地 dirty worktree;当前 `deploy apply --env dev` 支持 `backend-core``frontend``baidu-netdisk``decision-center``mdtodo``claudeqq` 和 dev-only `code-queue` artifact consumers`findjob`/`pipeline`/`met-nonlinear` 为 D601 direct Compose artifact consumers`k3sctl-adapter` 只提供 plan/dry-rundev desired-state smoke 使用 `ci run-dev-e2e`;规则见 `docs/reference/deploy.md``docs/reference/dev-environment.md``docs/reference/dev-ci-runner.md``deploy apply --env prod` 同时覆盖 `findjob``pipeline` 的 pull-only Compose CD,但 `met-nonlinear` 仍然只允许 dry-run/plan`k3sctl-adapter` 只允许 plan/dry-run。
- `dev-env validate [--manifest path] [--kubectl-dry-run]` 离线校验 D601 `unidesk-dev` namespace、dev PostgreSQL 底座和 dev workload manifest。默认检查 `src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-foundation.k8s.yaml`;也可显式校验 `src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-core.k8s.yaml``src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-code-queue.k8s.yaml`。所有 namespaced 对象必须只落到 `unidesk-dev`foundation manifest 必须包含 `postgres-dev` StatefulSet/Service、dev secret/config、迁移 Job 和 DB URL guardcore manifest 必须包含 `backend-core-dev`/`frontend-dev` Deployment/ServiceCode Queue dev manifest 必须包含 `code-queue-scheduler-dev``code-queue-read-dev``code-queue-write-dev`、dev provider egress proxy,以及只读挂载宿主 `/home/ubuntu/.agents/skills` 到容器 `/root/.agents/skills``skills-dir` volume。加 `--kubectl-dry-run` 时额外执行 `kubectl apply --dry-run=client --validate=false -f <manifest>`,仍不 apply 资源。
- `dev-env prewarm-images [--image image] [--provider-id D601] [--no-pull] [--proxy-url URL] [--pull-timeout-ms N] [--dry-run]` 创建异步 job,通过 UniDesk SSH 维护桥在 D601 上把开发底座依赖镜像从 Docker 缓存导入原生 k3s containerd。默认镜像是 `postgres:16-alpine``rancher/mirrored-library-busybox:1.36.1`,用于避免 `postgres-dev` 与 local-path helper pod 卡在外部 registry 拉取。该命令固定验证 `/etc/rancher/k3s/k3s.yaml` 指向的 native k3s 上下文,并输出 `dev_env_containerd_image_ready=...` 作为成功判据;它不 apply manifest、不修改生产 `unidesk` namespace。
- `artifact-registry plan|render|status|health|install|deploy-backend-core|deploy-service` 管理 D601 host-managed CNCF Distribution registry 的声明、安装、只读检查和 pull-only artifact CD。该 registry 固定为 D601 loopback `127.0.0.1:5000`,由 systemd + Docker Compose 管理,位于 native k3s 故障域外;`deploy-service` 只拉取 CI 已发布的 commit-pinned 镜像、retag/recreate 或导入 native k3s,并做 live commit 验证,不构建 runtime source。`deploy-backend-core` 是 deprecated 兼容名,标准 backend-core prod CD 入口是 `deploy apply --env prod --service backend-core`。长期规则见 `docs/reference/artifact-registry.md`
@@ -42,7 +42,7 @@ CLI 可以从 `master` 快速演进,但必须兼容 `deploy.json` 固定的 CI
- `ci install|status|run|publish-backend-core|publish-user-service|run-dev-e2e|logs` 管理 D601 原生 k3s 上的 Tekton CI。`run` 手动创建每 commit 检查和 Code Queue 只读性能门禁;`publish-backend-core``publish-user-service` 从 pushed Git commit 构建并发布 `127.0.0.1:5000/unidesk/<service>:<commit>` commit-pinned artifacts,输出 `artifactSummary`(含 `serviceId``sourceCommit``sourceRepo``dockerfile``imageRef``tag``digest``digestRef`),但不部署生产;`run-dev-e2e` 的 Git 控制 runner、短 launcher、host fetch 边界、临时 smoke namespace 和 no-CD 规则只在 `docs/reference/dev-ci-runner.md` 定义;Tekton CI 通用规则见 `docs/reference/ci.md`
- `schedule list|get|runs|run|retry-run|delete|upsert-pgdata-backup` 管理 backend-core 定时任务和运行历史。`schedule list``schedule get``schedule runs --limit N``schedule runs <scheduleId> --limit N` 是只读观察入口;`schedule run``schedule retry-run``schedule delete``schedule upsert-pgdata-backup` 会触发运行或写入配置,生产恢复时必须有明确授权。`schedule runs --limit N` 是全局历史视图,返回 `scope=global``scheduleId=null``schedule runs <scheduleId> --limit N` 是指定 schedule 历史视图,返回 `scope=schedule` 和对应 `scheduleId`。CLI 必须拒绝 `schedule runs 50` 这类纯数字位置参数,并提示使用 `schedule runs --limit 50`,避免把空数组误判成“没有历史 run”。`schedule run <id> --wait-ms N` 触发同一 schedule,并且即使 wait 超时也必须返回 `newRunId``observeCommand``schedule retry-run <failedRunId>` 只接受 failed run,从原 run 反查 `scheduleId` 后重触发同一 schedule,并输出 `originalRunId``scheduleId``newRunId``observeCommand`。当 backend-core 目标容器缺失或只观察到 verify-only 容器时,schedule/microservice 命令必须以非零退出并返回 `failureKind=target-stack-not-running``runnerDisposition=infra-blocked``readOnlyCommands``authorizationRequiredForRecovery`,不得把 Docker 的 `No such container` 当成成功的空历史。
- `codex deploy <commitId>` 是旧 Code Queue 兼容部署入口,已禁用以防止维护通道直连 D601 部署 Code Queue;当前 dev 自动化只做 `ci run-dev-e2e` smoke,不提供 Code Queue CD,详细规则见 `docs/reference/codex-deploy.md`
- `codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue queueId] [--provider-id id] [--cwd path] [--model model] [--reasoning-effort effort] [--execution-mode mode] [--max-attempts N] [--reference-task-id id] [--dry-run]` 通过 backend-core 私有代理向稳定 `code-queue` 用户服务路径提交任务;prompt 必须且只能来自位置参数、文件或 stdin 之一,`--dry-run` 只返回结构化请求且不实际入队。dry-run 会额外输出 `routingRecommendation`,包含推荐 route、runner、model、风险信号、prompt 自包含/issue 非唯一来源/prod-secret-DB 禁止/证据要求等 guard 状态;该建议只用于指挥官 preflight,不会改写 payload,也不假设生产 MiniMax 可用。提交确认和 dry-run 必须返回完整 prompt、字符数和 `truncated=false`,不能套用任务详情的预览截断策略,否则长任务 prompt 无法被人工验收。真实提交会经过本机本地串行化保护和短节流,避免同一指挥端并发 submit 把低内存主机或 `code-queue-mgr` 控制面打抖;返回值会附带 `submitConcurrencyGuard` 说明本次提交的锁与等待信息。backend-core 默认把提交、队列 CRUD、已读状态、历史摘要和轻量 Trace 读取分流到主 server `code-queue-mgr`,由它写入主 PostgreSQLD601 scheduler 只轮询并执行已入库任务。
- `codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue queueId] [--provider-id id] [--cwd path] [--model model] [--reasoning-effort effort] [--execution-mode mode] [--max-attempts N] [--reference-task-id id] [--dry-run]` 通过 backend-core 私有代理向稳定 `code-queue` 用户服务路径提交任务;prompt 必须且只能来自位置参数、文件或 stdin 之一,`--dry-run` 只返回结构化请求且不实际入队。dry-run 会额外输出 `routingRecommendation`,包含推荐 route、runner、model、风险信号、prompt 自包含/issue 非唯一来源/prod-secret-DB 禁止/运行态或 release 禁止/证据要求/中等复杂度候选等 guard 状态;同时输出 `policyContract`,固定暴露 GPT-5.5、DeepSeek、MiniMax 的风险分层、并发上限和外部 provider 429 退避处置。该建议只用于指挥官 preflight,不会改写 payload不改变 runtime admission也不假设生产 MiniMax 或 DeepSeek 可用。提交确认和 dry-run 必须返回完整 prompt、字符数和 `truncated=false`,不能套用任务详情的预览截断策略,否则长任务 prompt 无法被人工验收。真实提交会经过本机本地串行化保护和短节流,避免同一指挥端并发 submit 把低内存主机或 `code-queue-mgr` 控制面打抖;返回值会附带 `submitConcurrencyGuard` 说明本次提交的锁与等待信息。backend-core 默认把提交、队列 CRUD、已读状态、历史摘要和轻量 Trace 读取分流到主 server `code-queue-mgr`,由它写入主 PostgreSQLD601 scheduler 只轮询并执行已入库任务。
- `codex pr-preflight [--remote] [--push-dry-run --push-dry-run-ref refs/heads/probe/<name>] [--pr-create-dry-run --pr-create-dry-run-head <head>] [--issue N] [--full]` 通过稳定 `code-queue` proxy 请求 D601 scheduler `/api/runtime-preflight`,用于 PR 型派单 admission。输出会压缩展示 scheduler/runner 的 token 覆盖、工具、agent port、Git worktree、GitHub egress、repo/issue/PR 只读探测、可选 push dry-run,以及可选 PR body/create dry-run guard;只报告 `GH_TOKEN`/`GITHUB_TOKEN` 是否存在和来源 key,不打印值。缺少 env token 时顶层 `ok=false``runnerDisposition=infra-blocked``tokenCoverage.missing` 同时列出 `GH_TOKEN``GITHUB_TOKEN``preflight.prCapabilityContract` 是 runner-facing 合同摘要,必须包含目标分支、token 来源 key、`systemGhBinaryRequiredForWrites=false`、UniDesk REST `bun scripts/cli.ts gh` 可用性、push dry-run/PR create dry-run 的 `writesRemote=false`、expected PR handoff 和 `gh pr merge``unsupported-command` 边界。`--pr-create-dry-run` 不 POST GitHub,只证明 runner 内 PR body 生成、`scripts/cli.ts gh pr create --dry-run` 和 branch 参数形态可用;服务端创建权限仍以 token auth、repo/issue/PR read、push dry-run 和最终授权后的真实 PR 创建结果为准。
- `codex task <taskId>` 通过 Code Queue 私有代理按任务 ID 查询结构化审阅摘要;默认只返回任务身份、执行 Provider、工作目录、attempt 计数、原始 prompt、最终 response、最后错误和渐进披露命令,适合指挥官审阅完成未读任务且避免上下文爆炸。需要旧式详细摘要时显式加 `--detail`;需要完整 prompt/response 文本时加 `--full`;需要工具调用、judge、attempt 全量摘要时使用 `--detail --full --tool-limit N`。该摘要读取默认由主 server `code-queue-mgr` 从 PostgreSQL 返回,不依赖 D601 `code-queue-read` Service 可用。
- `codex tasks [--view supervisor|full] [--queue id] [--status succeeded|running|queued|failed|canceled|judging|retry_wait[,..]] [--unread|--unread-only] [--limit N] [--before-id id]` 通过同一私有代理输出渐进式披露视图。默认 `supervisor` 只返回 `running``completedUnread``recentCompleted``queued``executionDiagnostics` 摘要,不嵌入完整 Trace、final response 或全量 overview;每个条目都带 `commands.show``commands.trace``commands.output``commands.read``commands.full``--unread``--unread-only` 的别名,必须只保留未读终态;`--status` 必须真实过滤支持的状态,未知参数或未知状态必须结构化失败,不能静默忽略。需要完整当前页任务简表时显式使用 `--view full``--full`,仍受 `--limit``--before-id` 分页约束。
@@ -64,9 +64,9 @@ CLI 可以从 `master` 快速演进,但必须兼容 `deploy.json` 固定的 CI
长时操作采用 Fire-and-Forget 模式:CLI 创建 `.state/jobs/{jobId}.json`,后台进程执行真实命令,并将 stdout、stderr 分别写入 `.state/jobs/{jobId}.stdout.log``.state/jobs/{jobId}.stderr.log`。调用者通过 `bun scripts/cli.ts job status <jobId>` 查询进度和尾部输出。
`server rebuild``server start``server stop` 一样必须通过返回的 job id 确认结果;不要把连续 `server rebuild` 命令理解成“前一个重建已完成”,因为两个命令只是在快速创建异步 job。重建 frontend 只保留为维护/非标准路径;标准 frontend 发布必须先运行 `ci publish-user-service --service frontend --commit <full-sha>`,再运行 `deploy apply --env dev --service frontend``deploy apply --env prod --service frontend`,并验证 `/health.deploy.commit`。重建 dev 入口薄代理使用 `bun scripts/cli.ts server rebuild dev-frontend-proxy`,随后验证 `server status``urls.devFrontend``http://127.0.0.1:18083/health`;重建 Todo Note 后端使用 `bun scripts/cli.ts server rebuild todo-note`,随后用 `microservice health todo-note``microservice proxy todo-note /api/instances` 验证;重建 Code Queue Manager 使用 `bun scripts/cli.ts server rebuild code-queue-mgr`,随后用 `microservice health code-queue-mgr``microservice health code-queue``codex submit --dry-run` 验证主 server 控制面路径;重建 Project Manager 后端使用 `bun scripts/cli.ts server rebuild project-manager`,随后用 `microservice health project-manager``microservice proxy project-manager /api/projects` 验证;重建 Baidu Netdisk 后端使用 `bun scripts/cli.ts server rebuild baidu-netdisk`,随后用 `microservice health baidu-netdisk``microservice proxy baidu-netdisk /api/transfers` 验证,但该命令只保留为维护/非标准路径;重建 OA Event Flow 后端使用 `bun scripts/cli.ts server rebuild oa-event-flow`,随后用 `microservice health oa-event-flow``microservice proxy oa-event-flow /api/diagnostics` 验证。D601 Code Queue 执行面和 Decision Center 后端由 D601 k3s/k8s 控制面代管;persistent dev backend-core 走 target-side dev rolloutpersistent dev frontend 和 Decision Center 走 artifact consumer,当前 Code Queue 仍不得通过维护通道直连 D601 做部署。不得把 `docker rm` 手工兜底当成正式交付步骤。
`server rebuild``server start``server stop` 一样必须通过返回的 job id 确认结果;不要把连续 `server rebuild` 命令理解成“前一个重建已完成”,因为两个命令只是在快速创建异步 job。重建 frontend 只保留为维护/非标准路径;标准 frontend 发布必须先运行 `ci publish-user-service --service frontend --commit <full-sha>`,再运行 `deploy apply --env dev --service frontend``deploy apply --env prod --service frontend`,并验证 `/health.deploy.commit`。重建 dev 入口薄代理使用 `bun scripts/cli.ts server rebuild dev-frontend-proxy`,随后验证 `server status``urls.devFrontend``http://127.0.0.1:18083/health`;重建 Todo Note 后端使用 `bun scripts/cli.ts server rebuild todo-note`,随后用 `microservice health todo-note``microservice proxy todo-note /api/instances` 验证;重建 Code Queue Manager 使用 `bun scripts/cli.ts server rebuild code-queue-mgr`,随后用 `microservice health code-queue-mgr``microservice health code-queue``codex submit --dry-run` 验证主 server 控制面路径;重建 Project Manager 后端使用 `bun scripts/cli.ts server rebuild project-manager`,随后用 `microservice health project-manager``microservice proxy project-manager /api/projects` 验证;重建 Baidu Netdisk 后端使用 `bun scripts/cli.ts server rebuild baidu-netdisk`,随后用 `microservice health baidu-netdisk``microservice proxy baidu-netdisk /api/transfers` 验证,但该命令只保留为维护/非标准路径;重建 OA Event Flow 后端使用 `bun scripts/cli.ts server rebuild oa-event-flow`,随后用 `microservice health oa-event-flow``microservice proxy oa-event-flow /api/diagnostics` 验证。D601 Code Queue 执行面和 Decision Center 后端由 D601 k3s/k8s 控制面代管;persistent dev backend-corefrontend 和 Decision Center 走 artifact consumer,当前 Code Queue 仍不得通过维护通道直连 D601 做部署。不得把 `docker rm` 手工兜底当成正式交付步骤。
新部署入口优先使用 `deploy apply``deploy apply --env dev --service backend-core` 是 D601 target-side dev 路径`deploy apply --env dev|prod --service frontend``deploy apply --env dev|prod --service baidu-netdisk``deploy apply --env dev|prod --service decision-center` 是 artifact-consumer 样板;旧的 `codex deploy` 已禁用;后续 Code Queue 等 D601 服务部署应另行收敛到同一类受控 CD 路径,部署后用 live commit 校验证明不是旧服务。
新部署入口优先使用 `deploy apply``deploy apply --env dev --service backend-core` 是 D601 k3s artifact consumer,消费 `ci publish-backend-core` 产出的成品镜像`deploy apply --env dev|prod --service frontend``deploy apply --env dev|prod --service baidu-netdisk``deploy apply --env dev|prod --service decision-center` 是 artifact-consumer 样板;旧的 `codex deploy` 已禁用;后续 Code Queue 等 D601 服务部署应另行收敛到同一类受控 CD 路径,部署后用 live commit 校验证明不是旧服务。
## Output Contract
+10 -9
View File
@@ -40,9 +40,9 @@ The root `deploy.json` is the single desired-state source for both prod and dev.
The optional non-service execution declaration under `environments.dev` is intentionally not specified here. The only currently allowed declaration is `ci`, and its authoritative `repo`, `scriptPath`, `timeoutMs`, short launcher, host fetch boundary and no-CD rules are defined only in `docs/reference/dev-ci-runner.md`.
Environment mode never reads the local dirty working tree manifest. `deploy check --env ...`, `deploy plan --env ...` and `deploy apply --env ...` fetch `origin/master`, read `origin/master:deploy.json`, select `environments.<env>`, and report the manifest commit/blob, service commit IDs, target namespace, database fingerprint and Provider identity. `deploy apply --env dev` is currently enabled for persistent D601 dev `backend-core` target-side rollout and for reviewed artifact consumers `frontend`, `baidu-netdisk`, `decision-center`, `mdtodo`, `claudeqq`, dev-only `code-queue`, `project-manager`, `oa-event-flow`, `code-queue-mgr`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear`. `deploy apply --env prod` exposes reviewed registry artifact consumers (`backend-core`, `frontend`, `baidu-netdisk`, `decision-center`, `mdtodo`, `claudeqq`, `project-manager`, `oa-event-flow`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear`), while `code-queue` must report unsupported, `code-queue-mgr` remains supervisor-gated and `k3sctl-adapter` is plan/dry-run only. Production backend-core artifact CD is a separate executor because its build target is D601 CI while its runtime target is the master server. The default user-service delivery policy, including CI build, registry publication, dev validation, production CD and manual acceptance, is documented in `docs/reference/user-service-delivery.md`.
Environment mode never reads the local dirty working tree manifest. `deploy check --env ...`, `deploy plan --env ...` and `deploy apply --env ...` fetch `origin/master`, read `origin/master:deploy.json`, select `environments.<env>`, and report the manifest commit/blob, service commit IDs, target namespace, database fingerprint and Provider identity. `deploy apply --env dev` is currently enabled for reviewed artifact consumers `backend-core`, `frontend`, `baidu-netdisk`, `decision-center`, `mdtodo`, `claudeqq`, dev-only `code-queue`, `project-manager`, `oa-event-flow`, `code-queue-mgr`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear`. `deploy apply --env prod` exposes reviewed registry artifact consumers (`backend-core`, `frontend`, `baidu-netdisk`, `decision-center`, `mdtodo`, `claudeqq`, `project-manager`, `oa-event-flow`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear`), while `code-queue` must report unsupported, `code-queue-mgr` remains supervisor-gated and `k3sctl-adapter` is plan/dry-run only. Backend-core artifact CD is a pull-only consumer in both dev and prod; the build target is D601 CI, while dev runtime target is D601 native k3s and prod runtime target is the master server Compose stack. The default user-service delivery policy, including CI build, registry publication, dev validation, production CD and manual acceptance, is documented in `docs/reference/user-service-delivery.md`.
`--commit <full-sha>` is allowed only with `--env dev|prod --service <id>` for reviewed artifact consumers. It overrides the selected service commit for that one artifact consumer while still using the Git-backed environment manifest for target, namespace, repo, deploy ref and guardrails. It is the supported temporary shape for release-line frontend validation and rollback when the artifact was produced from a pushed `release/v1` commit but `origin/master:deploy.json#environments.<env>.services.frontend.commitId` has not been repinned. It must not be used for local-manifest mode, multi-service apply, or target-side source-build services such as dev `backend-core`.
`--commit <full-sha>` is allowed only with `--env dev|prod --service <id>` for reviewed artifact consumers. It overrides the selected service commit for that one artifact consumer while still using the Git-backed environment manifest for target, namespace, repo, deploy ref and guardrails. It is the supported temporary shape for release-line frontend/backend-core validation and rollback when the artifact was produced from a pushed `release/v1` commit but `origin/master:deploy.json#environments.<env>.services.<id>.commitId` has not been repinned. It must not be used for local-manifest mode, multi-service apply, or target-side source-build services.
For services with reviewed production artifact consumers, local-manifest `deploy apply --file ...` is not a production fallback. The CLI blocks `backend-core`, `frontend`, `baidu-netdisk`, `decision-center`, `mdtodo`, `claudeqq` and other reviewed pull-only consumers before source materialization or Docker build and directs operators to `deploy apply --env prod --service <id> --commit <full-sha>`. This prevents a dirty worktree, local manifest or target-side source build from bypassing the pull-only artifact CD guardrails. The broader precheck and legacy-path classification live in `docs/reference/cicd-standardization.md`.
@@ -87,7 +87,7 @@ Phase 3 introduces the dev backend/frontend manifest at `src/components/microser
`backend-core-dev` must use `unidesk-dev-runtime-config` and `unidesk-dev-runtime-secrets`, connect to `postgres-dev.../unidesk_dev`, expose HTTP on 8080 and provider ingress on 8081, and write logs under `/var/log/unidesk-dev`. `frontend-dev` must set `CORE_INTERNAL_URL=http://backend-core-dev.unidesk-dev.svc.cluster.local:8080` and must not proxy to production backend-core.
The manifest keeps placeholder image tags and deploy commit values in source control. The controlled `deploy apply --env dev --service backend-core` path fetches `origin/master:deploy.json`, materializes the requested source commit on D601, narrows the dev core control manifest to the selected Service/Deployment pair, replaces placeholders with the requested commit and dev image tag, builds on D601, imports the image into native k3s containerd, applies only the `unidesk-dev` objects and stamps the Deployment. `deploy apply --env dev --service frontend` uses the same selected dev manifest objects but consumes the existing D601 registry artifact `127.0.0.1:5000/unidesk/frontend:<commit>` instead of building frontend source on the target. Decision Center, MDTODO and ClaudeQQ use the same dev namespace but follow the D601 registry artifact consumer path instead of a source build: each verifies the commit-pinned image in D601 registry, imports it into native k3s containerd, applies its dev manifest, stamps the Deployment and verifies live commit/requestedCommit through the Kubernetes API service proxy. `project-manager`, `oa-event-flow`, `code-queue-mgr`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear` consume existing D601 registry artifacts for direct Docker/Compose validation rather than separate parallel k3s dev instances; `code-queue-mgr` live prod apply remains supervisor-gated. Client dry-run and static validation remain useful checks before controlled apply:
The manifest keeps placeholder image tags and deploy commit values in source control. The controlled `deploy apply --env dev --service backend-core` path consumes the existing D601 registry artifact `127.0.0.1:5000/unidesk/backend-core:<commit>` produced by `ci publish-backend-core`; it does not compile Rust or build a Docker image during CD. Backend-core and frontend use the same selected dev core manifest objects: CD verifies the commit-pinned registry image and labels, imports the artifact into native k3s containerd, applies only the selected `unidesk-dev` objects, stamps the Deployment, and verifies live commit/requestedCommit through the Kubernetes API service proxy. Decision Center, MDTODO and ClaudeQQ use the same dev namespace and D601 registry artifact consumer path. `project-manager`, `oa-event-flow`, `code-queue-mgr`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear` consume existing D601 registry artifacts for direct Docker/Compose validation rather than separate parallel k3s dev instances; `code-queue-mgr` live prod apply remains supervisor-gated. Client dry-run and static validation remain useful checks before controlled apply:
- `bun scripts/cli.ts dev-env validate --manifest src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-core.k8s.yaml`
- `KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl apply --dry-run=client --validate=false -f src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-core.k8s.yaml`
@@ -112,11 +112,11 @@ Production `code-queue-mgr` is a separate main-server Compose sidecar artifact c
`bun scripts/cli.ts deploy plan --env dev [--service <id>]` reads `origin/master:deploy.json#environments.dev` and prints a dry-run environment plan without checking or mutating live runtime resources. `deploy check --env dev` uses the same dry-run environment plan. `--env prod` is available for parity as a dry-run planning path; it reads `origin/master:deploy.json#environments.prod` and must not use a dirty local `deploy.json`.
Environment plan output must be sufficient to review the artifact matrix without running a live apply. Each service item includes `deploymentPath`, `artifactConsumer.consumerKind`, `artifactConsumer.registryImage`, `artifactConsumer.noRuntimeSourceBuild`, `artifactConsumer.dryRunOnly`, `target`, `validation` and `liveApply` where relevant. `consumerKind=d601-direct-compose` means the reviewed consumer touches only the D601 Docker/Compose service and private health path; `consumerKind=d601-k3s-managed` means the reviewed consumer imports the artifact into native k3s/containerd and verifies through the Kubernetes API service proxy; `consumerKind=main-server-compose` means the reviewed consumer streams or loads the D601 artifact into the main-server Compose service; `consumerKind=d601-dev-target-side-build` is reserved for the controlled dev backend-core source-build exception. Artifact consumer plan items must explicitly report `noRuntimeSourceBuild=true` and list forbidden build/public exposure actions. Blocked or gated services must keep structured `dryRunOnly` / `blockedReason` output, for example `met-nonlinear` `runtime-verification-blocked` and `k3sctl-adapter` supervisor-only production apply.
Environment plan output must be sufficient to review the artifact matrix without running a live apply. Each service item includes `deploymentPath`, `artifactConsumer.consumerKind`, `artifactConsumer.registryImage`, `artifactConsumer.registry`, `artifactConsumer.source`, `artifactConsumer.build`, `artifactConsumer.noRuntimeSourceBuild`, `artifactConsumer.dryRunOnly`, `target`, `validation` and `liveApply` where relevant. `consumerKind=d601-direct-compose` means the reviewed consumer touches only the D601 Docker/Compose service and private health path; `consumerKind=d601-k3s-managed` means the reviewed consumer imports the artifact into native k3s/containerd and verifies through the Kubernetes API service proxy; `consumerKind=main-server-compose` means the reviewed consumer streams or loads the D601 artifact into the main-server Compose service; `consumerKind=d601-dev-target-side-build` is retained only as a legacy classification and should not appear for backend-core. Artifact consumer plan items must explicitly report `noRuntimeSourceBuild=true`, expose registry/source/build boundaries including digest provenance, and list forbidden build/public exposure actions. Blocked or gated services must keep structured `dryRunOnly` / `blockedReason` output, for example `met-nonlinear` `runtime-verification-blocked` and `k3sctl-adapter` supervisor-only production apply.
For `--env dev --service code-queue`, the environment plan must also expose a `boundary` block that separates the CI producer from the dev CD consumer. CI is allowed to publish only `127.0.0.1:5000/unidesk/code-queue:<commit>` plus digest/label evidence. DEV CD may consume that artifact only for `unidesk-dev` Code Queue scheduler/read/write/provider-egress-proxy objects after an operator reviews the dry-run. For `--env prod --service code-queue`, the service item must remain `deploymentPath=unsupported`, `artifactConsumer.consumerKind=unsupported`, `target.deployCommandShape=none` and `liveApply.allowed=false`; it must not expose production k3s as an executable target. The prod boundary must state that production Code Queue CD needs a future supervisor-approved design and that this runner cannot self-deploy, mutate the production namespace, restart scheduler/runner, or interrupt/cancel tasks.
`bun scripts/cli.ts deploy apply [--file deploy.json | --env dev|prod] [--service <id>] [--commit <full-sha>] [--dry-run] [--force]` starts an asynchronous job only for supported targets. Use `bun scripts/cli.ts job status <jobId> --tail-bytes 30000` to observe progress. `--dry-run` resolves the same plan but does not build or replace runtime objects. `--force` rebuilds even when the live commit matches. Environment apply is not the dev e2e trigger; use `bun scripts/cli.ts ci run-dev-e2e` for the Git-controlled temporary namespace smoke flow. `--env dev` apply is enabled for persistent D601 `backend-core` target-side rollout and for `frontend`/`baidu-netdisk`/`decision-center`/`mdtodo`/`claudeqq`/dev-only `code-queue`/`project-manager`/`oa-event-flow`/`code-queue-mgr`/`todo-note`/`findjob`/`pipeline`/`met-nonlinear` artifact consumers. `--env prod` apply exposes the D601 registry artifact consumer for `backend-core`, `frontend`, `baidu-netdisk`, `decision-center`, `mdtodo`, `claudeqq`, `project-manager`, `oa-event-flow`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear`; `code-queue-mgr` prod live apply is supervisor-gated and `k3sctl-adapter` is plan/dry-run only. `--commit` may override one selected reviewed artifact consumer in either dev or prod, for example `deploy apply --env dev --service frontend --commit <release-v1-full-sha>`, and the image must already exist as `127.0.0.1:5000/unidesk/<service-id>:<commit>`. Unsupported prod services, especially `code-queue`, return a structured `unsupported` payload instead of silently falling back to a maintenance-channel source build.
`bun scripts/cli.ts deploy apply [--file deploy.json | --env dev|prod] [--service <id>] [--commit <full-sha>] [--dry-run] [--force]` starts an asynchronous job only for supported targets. Use `bun scripts/cli.ts job status <jobId> --tail-bytes 30000` to observe progress. `--dry-run` resolves the same plan but does not build or replace runtime objects. `--force` redeploys even when the live commit matches. Environment apply is not the dev e2e trigger; use `bun scripts/cli.ts ci run-dev-e2e` for the Git-controlled temporary namespace smoke flow. `--env dev` apply is enabled for `backend-core`/`frontend`/`baidu-netdisk`/`decision-center`/`mdtodo`/`claudeqq`/dev-only `code-queue`/`project-manager`/`oa-event-flow`/`code-queue-mgr`/`todo-note`/`findjob`/`pipeline`/`met-nonlinear` artifact consumers. `--env prod` apply exposes the D601 registry artifact consumer for `backend-core`, `frontend`, `baidu-netdisk`, `decision-center`, `mdtodo`, `claudeqq`, `project-manager`, `oa-event-flow`, `todo-note`, `findjob`, `pipeline` and `met-nonlinear`; `code-queue-mgr` prod live apply is supervisor-gated and `k3sctl-adapter` is plan/dry-run only. `--commit` may override one selected reviewed artifact consumer in either dev or prod, for example `deploy apply --env dev --service backend-core --commit <full-sha>` or `deploy apply --env dev --service frontend --commit <release-v1-full-sha>`, and the image must already exist as `127.0.0.1:5000/unidesk/<service-id>:<commit>`. Unsupported prod services, especially `code-queue`, return a structured `unsupported` payload instead of silently falling back to a maintenance-channel source build.
All deploy commands output JSON. Long operations must use `.state/jobs/` and bounded log tails; no deploy path may succeed with missing progress output.
@@ -131,16 +131,17 @@ Target-side build is the standard deployment mode. The controller may run on the
The reconciler distributes only repository URL, commit ID, Dockerfile path, build context and the existing deployment manifest/compose declaration. It must not distribute large Docker images between hosts as the default path, and it must not accept `docker commit` images, dirty worktrees or hand-mutated runtime containers as deployment truth.
Each target fetches the remote repository, resolves the requested commit to a full 40 character SHA and exports tracked files with `git archive`. Build contexts are created from that archive, not from the operator's current working tree. Environment applies such as `deploy apply --env dev` must not upload Kubernetes manifests or source files from the master server worktree; the target-side materialized commit is the source for Dockerfile, build context and k3s control manifests. The master server side may only do lightweight CLI orchestration, environment ref reading and remote command dispatch.
Target-side source-build services fetch the remote repository, resolve the requested commit to a full 40 character SHA and export tracked files with `git archive`. Build contexts are created from that archive, not from the operator's current working tree. Artifact consumers such as dev/prod backend-core do not materialize source during CD; they use the Git-backed environment manifest only for commit intent, target selection and deploy ref metadata. The master server side may only do lightweight CLI orchestration, environment ref reading and remote command dispatch.
## Artifact Consumer Exception
Production backend-core and reviewed user-service samples are explicit exceptions to standard target-side build. The runtime target can be the master server Compose stack, but the build target is D601 CI; CD then consumes only commit-pinned images from the D601 artifact registry.
Backend-core and reviewed user-service samples are explicit exceptions to standard target-side build. The runtime target can be the master server Compose stack or D601 native k3s dev namespace, but the build target is D601 CI; CD then consumes only commit-pinned images from the D601 artifact registry.
The exception is narrow:
- CI on D601 builds `src/components/backend-core/Dockerfile` from a pushed commit, stamps image labels and publishes `127.0.0.1:5000/unidesk/backend-core:<commit>` to the D601 artifact registry.
- CD on the master server pulls that existing image through the controlled artifact-registry relay, retags it for the Compose service, recreates only `backend-core` with `--no-build --no-deps --force-recreate`, and verifies the running commit.
- Dev CD on D601 imports that existing image into native k3s containerd, sets `backend-core-dev` to the commit image, stamps deploy metadata, and verifies `/health.deploy.commit` and `deploy.requestedCommit`.
- Prod CD on the master server pulls that existing image through the controlled artifact-registry relay, retags it for the Compose service, recreates only `backend-core` with `--no-build --no-deps --force-recreate`, and verifies the running commit.
- CD must not run Rust compilation, Docker build, Compose build or `server rebuild backend-core`.
- The legacy `artifact-registry deploy-backend-core` compatibility entry is deprecated and disabled as a standard entrypoint; use `deploy apply --env prod --service backend-core --commit <full-sha>` so the common artifact-consumer guardrails execute first.
- The pushed Git commit remains the version source of truth. The image registry is a content cache and transfer boundary, not a replacement for `deploy.json` or Git.
@@ -191,7 +192,7 @@ The reconciler selects the executor from `config.json`:
- `deployment.mode=internal-sidecar` on `main-server`: use the same main-server target-side source export, Docker build, image label stamping, fixed Compose project replacement and live commit verification as direct Compose services. This class is for private sidecars such as `code-queue-mgr`; it is still versioned by `deploy.json.commitId`, not by the operator's current worktree, and prod live apply remains supervisor-gated.
- `deployment.mode=unidesk-direct` on a provider: this executor is disabled for D601 service deployment. The historical behavior dispatched `host.ssh` to the provider, built on the provider, then used the service's provider-local compose file and project; that shape must not remain a second deployment control plane.
- Control bridges that UniDesk needs in order to inspect or repair an orchestrator must stay in this direct class. In particular, `k3sctl-adapter` is a UniDesk-managed bridge to native k3s and must remain outside k3s; Docker packaging on Docker Desktop/WSL must create an explicit host-local bridge, currently an adapter-container SSH local tunnel, to reach `/etc/rancher/k3s/k3s.yaml` and WSL `127.0.0.1:6443`.
- `deployment.mode=k3sctl-managed`: the target behavior is to build on the active control target unless the service has a reviewed artifact-consumer exception, verify native k3s on the host OS/WSL distro, import the image into native k3s/containerd, apply the existing Kubernetes manifest, stamp the Deployment and wait for rollout. On D601, persistent dev apply is currently allowed for `backend-core` target-side build plus `frontend`, `decision-center`, `mdtodo`, `claudeqq` and dev-only `code-queue` artifact consumption in `unidesk-dev`; production artifact consumers are limited to reviewed services and exclude Code Queue. Normal production services still cannot use a maintenance-channel direct rollout. The executor must use the native kubeconfig and containerd socket, for example `/etc/rancher/k3s/k3s.yaml` and `/run/k3s/containerd/containerd.sock`; running k3s itself in Docker is forbidden for both control-plane and worker nodes. A `rancher/k3s` image or legacy container may only be used as a temporary artifact source during migration, and any active containerized k3s control plane must be stopped before verification succeeds. The executor must preload a valid `rancher/mirrored-pause:3.6` sandbox image into native k3s containerd through the provider-gateway one-shot egress path, verify its entrypoint is `/pause`, and reject fake or sleep-based replacement images. k3s-managed deploys must use ClusterIP Services and Kubernetes API service proxy health checks; they must not add NodePort, hostPort, public business ports or provider-gateway direct business backends.
- `deployment.mode=k3sctl-managed`: the target behavior is to build on the active control target unless the service has a reviewed artifact-consumer exception, verify native k3s on the host OS/WSL distro, import the image into native k3s/containerd, apply the existing Kubernetes manifest, stamp the Deployment and wait for rollout. On D601, persistent dev apply uses artifact consumption for `backend-core`, `frontend`, `decision-center`, `mdtodo`, `claudeqq` and dev-only `code-queue` in `unidesk-dev`; production artifact consumers are limited to reviewed services and exclude Code Queue. Normal production services still cannot use a maintenance-channel direct rollout. The executor must use the native kubeconfig and containerd socket, for example `/etc/rancher/k3s/k3s.yaml` and `/run/k3s/containerd/containerd.sock`; running k3s itself in Docker is forbidden for both control-plane and worker nodes. A `rancher/k3s` image or legacy container may only be used as a temporary artifact source during migration, and any active containerized k3s control plane must be stopped before verification succeeds. The executor must preload a valid `rancher/mirrored-pause:3.6` sandbox image into native k3s containerd through the provider-gateway one-shot egress path, verify its entrypoint is `/pause`, and reject fake or sleep-based replacement images. k3s-managed deploys must use ClusterIP Services and Kubernetes API service proxy health checks; they must not add NodePort, hostPort, public business ports or provider-gateway direct business backends.
D601 Docker local images are not the source of truth for k3s runtime availability. For Code Queue, the deploy gate must verify `unidesk-code-queue:d601` exists in native k3s containerd after import with `ctr --address /run/k3s/containerd/containerd.sock -n k8s.io images ls`, and it must fail before rollout if the tag is missing. The same gate must verify every production Code Queue Deployment that uses the image (`code-queue`, `code-queue-read`, `code-queue-write`, `d601-provider-egress-proxy`, `d601-tcp-egress-gateway`) still references exactly `unidesk-code-queue:d601`; otherwise kubelet may attempt an external registry pull and leave base gateways in `ImagePullBackOff`.
+2 -2
View File
@@ -30,7 +30,7 @@ CLI 会优先使用 `docker compose` v2 plugin;当 v2 plugin 不存在时才
Compose v2 安装后仍然必须遵守 UniDesk 的服务控制入口:全栈生命周期用 `server start` / `server stop`,单服务重建用 `server rebuild <service>`。不要因为 v2 可用就直接在生产栈上手工执行未纳入 CLI 的 `up --build``down -v` 或跨项目清理命令;所有会影响容器的动作都应保持 job 可观测、Compose project 固定、database named volume 保留。主 server Compose 命令必须从 `providerGateway.upgrade.hostProjectRoot` 指定的 canonical UniDesk 根目录运行,临时 worktree、Code Queue 导出目录或实验分支不得复用生产 `-p unidesk` 和固定 `container_name` 去替换生产容器。
版本化用户服务部署优先使用 `bun scripts/cli.ts deploy apply` 已支持的受控路径;D601 persistent dev apply 当前支持 `backend-core` target-side rollout、`frontend`/`baidu-netdisk`/`decision-center`/`mdtodo`/`claudeqq` artifact consumer、dev-only `code-queue` artifact consumer,以及 `project-manager``oa-event-flow``code-queue-mgr``todo-note``findjob``pipeline``met-nonlinear` 的 artifact consumer validationdev desired-state smoke 使用 `ci run-dev-e2e``deploy.json` 只声明服务 `id``repo``commitId`;目标节点、Dockerfile、Compose、Kubernetes manifest、健康检查和代理路径继续来自 `config.json` 与现有 manifest。主 server 直管微服务和内部 sidecar,例如 `code-queue-mgr`,也必须支持这一路径:`deploy apply --service code-queue-mgr``deploy.json` 指定 commit 导出源码、构建镜像、替换固定 Compose service 并验证运行中镜像/健康信息的 commit,但 prod live apply 仍需 supervisor 确认。部署默认遵循 target-side build:服务部署到哪台 target,就在哪台 target 从 remote commit 导出源码、一次性代理构建镜像并部署;不得把中心构建镜像作为默认分发路径,也不得用 `docker commit` 或脏 worktree 作为部署输入。production backend-core 是明确例外;`frontend` 是用户服务 UI / 前端镜像化样板,`baidu-netdisk` 是主 server 直管微服务的镜像化样板,`decision-center``mdtodo``claudeqq` 是 k3s-managed artifact consumer 样板,`findjob``pipeline` 是 D601 direct Docker/Compose pull-only 样板:D601 CI 构建并推送 commit-pinned 镜像到 D601 artifact registryCD 只拉取、retag 或导入、recreate/rollout 和验证,不在 master server 或 runtime target 执行 Compose build。`met-nonlinear` 当前只允许 dry-run/plan`k3sctl-adapter` 只允许 plan/dry-run 且真实 prod 部署需要 supervisor 确认。`code-queue` 只允许 dev artifact consumerprod artifact deploy/rollout/manifest mutation 必须 unsupported。完整规则见 `docs/reference/deploy.md`D601 dev/Rust 边界见 `docs/reference/dev-environment.md`artifact registry 见 `docs/reference/artifact-registry.md`
版本化用户服务部署优先使用 `bun scripts/cli.ts deploy apply` 已支持的受控路径;D601 persistent dev apply 当前支持 `backend-core`/`frontend`/`baidu-netdisk`/`decision-center`/`mdtodo`/`claudeqq` artifact consumer、dev-only `code-queue` artifact consumer,以及 `project-manager``oa-event-flow``code-queue-mgr``todo-note``findjob``pipeline``met-nonlinear` 的 artifact consumer validationdev desired-state smoke 使用 `ci run-dev-e2e``deploy.json` 只声明服务 `id``repo``commitId`;目标节点、Dockerfile、Compose、Kubernetes manifest、健康检查和代理路径继续来自 `config.json` 与现有 manifest。主 server 直管微服务和内部 sidecar,例如 `code-queue-mgr`,也必须支持这一路径:`deploy apply --service code-queue-mgr``deploy.json` 指定 commit 导出源码、构建镜像、替换固定 Compose service 并验证运行中镜像/健康信息的 commit,但 prod live apply 仍需 supervisor 确认。部署默认遵循 target-side build:服务部署到哪台 target,就在哪台 target 从 remote commit 导出源码、一次性代理构建镜像并部署;不得把中心构建镜像作为默认分发路径,也不得用 `docker commit` 或脏 worktree 作为部署输入。backend-core 是明确例外;`frontend` 是用户服务 UI / 前端镜像化样板,`baidu-netdisk` 是主 server 直管微服务的镜像化样板,`decision-center``mdtodo``claudeqq` 是 k3s-managed artifact consumer 样板,`findjob``pipeline` 是 D601 direct Docker/Compose pull-only 样板:D601 CI 构建并推送 commit-pinned 镜像到 D601 artifact registryCD 只拉取、retag 或导入、recreate/rollout 和验证,不在 master server 或 runtime target 执行 Compose build。Dev backend-core consumes `127.0.0.1:5000/unidesk/backend-core:<commit>` into `unidesk-dev/backend-core-dev` and must not compile Rust during CD. `met-nonlinear` 当前只允许 dry-run/plan`k3sctl-adapter` 只允许 plan/dry-run 且真实 prod 部署需要 supervisor 确认。`code-queue` 只允许 dev artifact consumerprod artifact deploy/rollout/manifest mutation 必须 unsupported。完整规则见 `docs/reference/deploy.md`D601 dev/Rust 边界见 `docs/reference/dev-environment.md`artifact registry 见 `docs/reference/artifact-registry.md`
## Main Server Swap
@@ -46,7 +46,7 @@ swap 管理不能被强塞进所有热路径。`server start/status` 可以暴
## Single Service Rebuild
前端、本机 provider-gateway、dev-frontend-proxy 或主 server 承载的 Todo Note/Code Queue Manager/Project Manager/Baidu Netdisk/OA Event Flow 用户服务需要非版本化本地重建时,统一使用 `bun scripts/cli.ts server rebuild <service>`,其中 `<service>` 只能是 `backend-core``frontend``dev-frontend-proxy``provider-gateway``todo-note``code-queue-mgr``project-manager``baidu-netdisk``oa-event-flow`。对 `database``filebrowser``filebrowser-d601``code-queue``k3sctl-adapter` 或未知对象,CLI 必须返回结构化 `unsupported-server-rebuild`,不得创建 job、不得执行 Compose mutation,也不得把对象强行转成源码构建服务。需要按 commit 上线或恢复到 desired-state 时必须改用 `bun scripts/cli.ts deploy apply --service <id>`、backend-core artifact CD、`deploy apply --env dev|prod --service frontend|baidu-netdisk|decision-center|mdtodo|claudeqq` artifact consumer,或 dev-only `deploy apply --env dev --service code-queue` artifact consumer;直管微服务也不能把脏工作树或手工重建作为部署真相。`server rebuild frontend``server rebuild baidu-netdisk``server rebuild project-manager``server rebuild oa-event-flow``server rebuild todo-note``server rebuild code-queue-mgr` 都只作为维护/非标准路径保留,不得作为标准发布完成证据。Rust backend-core 迭代不得在 master server 用 `server rebuild backend-core` 编译,生产 backend-core 也不得用该命令完成 Rust 构建,必须走 D601 dev deploy/CI 或 D601 artifact registry CD。D601 Code Queue 执行面、File Browser、FindJob、Pipeline、MET Nonlinear 和 ClaudeQQ 部署在计算节点,不属于主 server Compose 可重建服务;其中 D601 Code Queue 执行面不得再通过 `codex deploy` 或维护通道直连 D601 部署,且本阶段 prod artifact deploy/rollout/manifest mutation 仍 unsupported。特例冻结清单和下一阶段删除判断见 `docs/reference/cicd-standardization.md`
前端、本机 provider-gateway、dev-frontend-proxy 或主 server 承载的 Todo Note/Code Queue Manager/Project Manager/Baidu Netdisk/OA Event Flow 用户服务需要非版本化本地重建时,统一使用 `bun scripts/cli.ts server rebuild <service>`,其中 `<service>` 只能是 `backend-core``frontend``dev-frontend-proxy``provider-gateway``todo-note``code-queue-mgr``project-manager``baidu-netdisk``oa-event-flow`。对 `database``filebrowser``filebrowser-d601``code-queue``k3sctl-adapter` 或未知对象,CLI 必须返回结构化 `unsupported-server-rebuild`,不得创建 job、不得执行 Compose mutation,也不得把对象强行转成源码构建服务。需要按 commit 上线或恢复到 desired-state 时必须改用 `bun scripts/cli.ts deploy apply --service <id>`、backend-core artifact CD、`deploy apply --env dev|prod --service frontend|baidu-netdisk|decision-center|mdtodo|claudeqq` artifact consumer,或 dev-only `deploy apply --env dev --service code-queue` artifact consumer;直管微服务也不能把脏工作树或手工重建作为部署真相。`server rebuild frontend``server rebuild baidu-netdisk``server rebuild project-manager``server rebuild oa-event-flow``server rebuild todo-note``server rebuild code-queue-mgr` 都只作为维护/非标准路径保留,不得作为标准发布完成证据。Rust backend-core 迭代不得在 master server 用 `server rebuild backend-core` 编译,dev/prod backend-core CD 也不得用该命令完成 Rust 构建,必须走 D601 CI `ci publish-backend-core`,再用 dev/prod artifact consumer 拉取成品镜像。D601 Code Queue 执行面、File Browser、FindJob、Pipeline、MET Nonlinear 和 ClaudeQQ 部署在计算节点,不属于主 server Compose 可重建服务;其中 D601 Code Queue 执行面不得再通过 `codex deploy` 或维护通道直连 D601 部署,且本阶段 prod artifact deploy/rollout/manifest mutation 仍 unsupported。特例冻结清单和下一阶段删除判断见 `docs/reference/cicd-standardization.md`
frontend 改动必须明确上线到公网:修改 `src/components/frontend/src/``src/components/frontend/public/style.css`、frontend 使用的共享 TSX/TS 模块或 WebUI 导航后,标准发布顺序是先把 pushed commit 交给 `bun scripts/cli.ts ci publish-user-service --service frontend --commit <full-sha>`,再用 `bun scripts/cli.ts deploy apply --env dev --service frontend``bun scripts/cli.ts deploy apply --env prod --service frontend` 消费同一个 commit-pinned artifact。公网 WebUI 的 `/app.js``unidesk-frontend` 镜像内运行时 bundle;只改工作区文件、只跑 `bun run check`、只跑 `Bun.build`、只刷新浏览器或只 `server rebuild frontend` 都不能作为标准版本发布证据。
+21 -22
View File
@@ -9,8 +9,8 @@ The dev environment lets users experience the next UniDesk version without inter
- Production stays on the normal public frontend at `http://74.48.78.17:18081/`.
- Dev is exposed through a separate main-server public port at `http://74.48.78.17:18083/`.
- Dev backend/frontend workloads run in D601 native k3s namespace `unidesk-dev`, not in the main-server Compose stack.
- Dev backend-core build and frontend artifact rollout use pushed Git commits from `origin/master:deploy.json#environments.dev`, not dirty local worktrees.
- Rust backend-core check/build must run on D601 through CI or dev deploy; the master server must not compile Rust for this iteration path.
- Dev backend-core and frontend rollout use pushed Git commits from `origin/master:deploy.json#environments.dev`, not dirty local worktrees.
- Rust backend-core check/build must run on D601 CI through `ci publish-backend-core`; dev CD consumes the published image and must not compile Rust.
## Public Dev Frontend Port
@@ -40,8 +40,7 @@ During a `release/v1` stabilization window, this same implemented `environments.
The persistent dev rollout currently supports:
- `backend-core` as a D601 target-side build.
- `frontend`, `decision-center`, `mdtodo`, `claudeqq` and `code-queue` as D601 registry artifact consumers in `unidesk-dev`.
- `backend-core`, `frontend`, `decision-center`, `mdtodo`, `claudeqq` and `code-queue` as D601 registry artifact consumers in `unidesk-dev`.
- `baidu-netdisk` as the main-server direct user-service artifact validation sample.
`deploy apply --env dev --service baidu-netdisk` consumes the D601 registry artifact and validates the main-server Compose service; it is not a persistent D601 k3s dev workload. `deploy apply --env dev --service code-queue` is intentionally dev-only and may mutate only `unidesk-dev` Code Queue scheduler/read/write/provider-egress-proxy objects. `deploy apply --env prod --service code-queue` must remain unsupported. The `environments.dev.ci` declaration and short launcher runner are owned by `docs/reference/dev-ci-runner.md`.
@@ -66,24 +65,23 @@ Not allowed on the master server for this path:
- `bun scripts/cli.ts server rebuild backend-core` as a way to iterate Rust backend-core, because it would build the Rust image in the main-server Docker daemon.
- Ad-hoc `docker build` of `src/components/backend-core/Dockerfile` on the master server.
Rust checking is enabled only when the process is already running inside the D601 CI/dev execution boundary: `UNIDESK_D601_RUST_CHECK=1 bun scripts/cli.ts check --full --rust`. `check --rust` deliberately fails outside that guard with an explicit explanation instead of silently compiling on the wrong host.
Rust checking is enabled only when the process is already running inside the D601 CI execution boundary: `UNIDESK_D601_RUST_CHECK=1 bun scripts/cli.ts check --full --rust`. `check --rust` deliberately fails outside that guard with an explicit explanation instead of silently compiling on the wrong host.
## Dev Deploy Path
`deploy apply --env dev --service backend-core|frontend|decision-center|mdtodo|claudeqq|code-queue` is the controlled persistent dev rollout path for D601 dev workloads. The controller runs on the master server, but the heavy work runs on D601. `backend-core` still uses the constrained dev target-side build path; the other listed services consume CI-published commit-pinned artifacts from the D601 registry.
`deploy apply --env dev --service backend-core|frontend|decision-center|mdtodo|claudeqq|code-queue` is the controlled persistent dev rollout path for D601 dev workloads. The controller runs on the master server, but dev CD is a pull-only artifact consumer. All listed services consume CI-published commit-pinned artifacts from the D601 registry.
1. Fetch `origin/master:deploy.json#environments.dev` and resolve the requested service commit to a full SHA.
2. Dispatch to D601 through the existing provider-gateway/Host SSH maintenance capability.
3. On D601, fetch/export the requested Git commit through the node-local provider-gateway egress proxy `http://127.0.0.1:18789`.
4. For backend-core, use the target-side commit as the source for Dockerfile, build context and dev k3s manifest, then build the service image on D601 Docker.
5. For artifact consumers, require the existing registry image `127.0.0.1:5000/unidesk/<service-id>:<commit>` produced by `ci publish-user-service --service <service-id>`; do not build that service source in the dev target.
6. Import the backend-core build output or registry artifact into native k3s containerd at `/run/k3s/containerd/containerd.sock`.
7. Apply only the selected `unidesk-dev` Service/Deployment objects from the dev manifest.
8. For `frontend`, sync auth/session settings from main-server `config.json.auth` into the dev runtime Secret/ConfigMap before rollout.
9. Stamp the Deployment with `UNIDESK_DEPLOY_*` env and `unidesk.ai/deploy-*` annotations.
10. Verify health through the Kubernetes API service proxy and require the live commit to match the requested commit.
3. Require the existing registry image `127.0.0.1:5000/unidesk/<service-id>:<commit>` produced by `ci publish-backend-core` for backend-core or `ci publish-user-service --service <service-id>` for user services.
4. Verify the registry manifest and image labels for service id, source commit and Dockerfile. The dry-run plan exposes the registry image, planned digest source, target, source commit and `build.willCompile=false`.
5. Import the registry artifact into native k3s containerd at `/run/k3s/containerd/containerd.sock`.
6. Apply only the selected `unidesk-dev` Service/Deployment objects from the dev manifest.
7. For `frontend`, sync auth/session settings from main-server `config.json.auth` into the dev runtime Secret/ConfigMap before rollout.
8. Stamp the Deployment with `UNIDESK_DEPLOY_*` env and `unidesk.ai/deploy-*` annotations.
9. Verify health through the Kubernetes API service proxy and require the live commit to match the requested commit.
The dev path is not a fallback system. If GitHub fetch, provider-gateway egress, Docker build for backend-core, artifact lookup, native k3s, containerd import, kubectl apply or live health verification fails, the job fails with logs. It must not fall back to building artifact-consumer source on the dev target, building on the master server, using a dirty worktree, direct D601 public ports, NodePort, hostPort, provider-gateway business HTTP, or another deployment command. k3s-managed health verification must use the Kubernetes API service proxy.
The dev path is not a fallback system. If artifact lookup, label verification, native k3s, containerd import, kubectl apply or live health verification fails, the job fails with logs. It must not fall back to `cargo build`, `docker build`, building on the master server, building source on the dev target, using a dirty worktree, direct D601 public ports, NodePort, hostPort, provider-gateway business HTTP, or another deployment command. k3s-managed health verification must use the Kubernetes API service proxy.
## DevOps Hygiene
@@ -97,13 +95,14 @@ Use this sequence for backend-core Rust and frontend dev work:
2. Run local non-Rust checks on the master server, for example `bun scripts/cli.ts check --files --scripts-typecheck --compose --logs`.
3. Commit and push the code to `origin master`; `deploy apply --env dev` cannot deploy unpushed local changes.
4. Update `deploy.json` `environments.dev.services` so `backend-core` and `frontend` point at the pushed commit, then commit and push that manifest update.
5. For artifact-consumer changes, publish the artifact first: `bun scripts/cli.ts ci publish-user-service --service <frontend|decision-center|mdtodo|claudeqq|code-queue> --commit <full-sha> --wait-ms 1200000`.
6. Run `bun scripts/cli.ts deploy apply --env dev --service backend-core` and observe the returned job with `bun scripts/cli.ts job status <jobId> --tail-bytes 30000`.
7. Run `bun scripts/cli.ts deploy apply --env dev --service <frontend|decision-center|mdtodo|claudeqq|code-queue>` and observe the job the same way; this must consume the registry artifact and verify live deploy metadata through the service health path.
8. If the dev service catalog changes, deploy the pushed `k3sctl-adapter` commit through the controlled local manifest exception, then verify `/api/control-plane` lists `k3s/dev/unidesk-dev-core.k3s.json`.
9. Rebuild or verify `dev-frontend-proxy` on the main server with `bun scripts/cli.ts server rebuild dev-frontend-proxy` when the proxy config or port changes.
10. Manually test `http://74.48.78.17:18083/` and the dev health endpoints.
11. Run D601 CI for the commit and the dev smoke runner: `bun scripts/cli.ts ci run --revision <commit> --wait-ms <ms>` and `bun scripts/cli.ts ci run-dev-e2e --wait-ms <ms>`. When Code Queue behavior changes, update the `code-queue` entry in `environments.dev.services` to the pushed commit before running dev artifact validation or the temporary dev smoke.
5. Publish the artifact first: `bun scripts/cli.ts ci publish-backend-core --commit <full-sha> --wait-ms 1200000` for backend-core, or `bun scripts/cli.ts ci publish-user-service --service <frontend|decision-center|mdtodo|claudeqq|code-queue> --commit <full-sha> --wait-ms 1200000` for user services.
6. Run `bun scripts/cli.ts deploy apply --env dev --service backend-core --dry-run` and confirm `artifactConsumer.noRuntimeSourceBuild=true`, `build.willCompile=false`, the registry image is `127.0.0.1:5000/unidesk/backend-core:<commit>`, and the target is `unidesk-dev/backend-core-dev`.
7. Run `bun scripts/cli.ts deploy apply --env dev --service backend-core` and observe the returned job with `bun scripts/cli.ts job status <jobId> --tail-bytes 30000`.
8. Run `bun scripts/cli.ts deploy apply --env dev --service <frontend|decision-center|mdtodo|claudeqq|code-queue>` and observe the job the same way; this must consume the registry artifact and verify live deploy metadata through the service health path.
9. If the dev service catalog changes, deploy the pushed `k3sctl-adapter` commit through the controlled local manifest exception, then verify `/api/control-plane` lists `k3s/dev/unidesk-dev-core.k3s.json`.
10. Rebuild or verify `dev-frontend-proxy` on the main server with `bun scripts/cli.ts server rebuild dev-frontend-proxy` when the proxy config or port changes.
11. Manually test `http://74.48.78.17:18083/` and the dev health endpoints.
12. Run D601 CI for the commit and the dev smoke runner: `bun scripts/cli.ts ci run --revision <commit> --wait-ms <ms>` and `bun scripts/cli.ts ci run-dev-e2e --wait-ms <ms>`. When Code Queue behavior changes, update the `code-queue` entry in `environments.dev.services` to the pushed commit before running dev artifact validation or the temporary dev smoke.
## Validation Commands
+1 -1
View File
@@ -22,7 +22,7 @@ The following practices are not acceptable as the long-term or hidden source of
- Rebuilding backend-core, frontend, k3sctl-adapter or other managed services from a dirty worktree on the master server, D601 or an operator machine.
- Copying large local shell scripts, generated manifests, Docker images or application source to D601 as the main deployment mechanism.
- Fixing dev or production reachability by adding direct D601 public ports, NodePorts or backend-core hardcoded service entries instead of updating the proper catalog/control bridge.
- Treating `server rebuild backend-core` as a Rust backend-core iteration path; Rust build/check belongs to D601 dev deploy or D601 CI only.
- Treating `server rebuild backend-core` as a Rust backend-core iteration path; Rust build/check belongs to D601 CI and CD must consume the published artifact.
- Using local-manifest production deploy for services that already have artifact consumers. `backend-core`, `frontend`, `baidu-netdisk` and `decision-center` production deploys must enter through `deploy apply --env prod` so CD consumes a commit-pinned registry artifact instead of silently falling back to target-side source build.
- Treating upstream images as UniDesk source-build services. `filebrowser` and `filebrowser-d601` are upstream-image consumers; they require digest pin or digest-verified mirror governance and must not be added to Dockerfile CI artifacts.
- Considering manual curl, kubectl or Docker checks sufficient when live commit metadata, deploy plan, health checks and CI/e2e disagree.
+2 -2
View File
@@ -172,7 +172,7 @@ Baidu Netdisk 在 UniDesk 语境中按纯后端服务管理:不得暴露百度
D601 开发环境底座只允许创建 `unidesk-dev` namespace 与 dev 专用对象,manifest 固定为 `src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-foundation.k8s.yaml`。该 manifest 包含 `postgres-dev` 独立 PostgreSQL StatefulSet/Service/PVC、dev-only secret/config 模板、dev DB 初始化 SQL 和迁移 Job、ResourceQuota/LimitRange,以及 `unidesk-dev-db-guard`。它不得修改生产 `unidesk` namespace、生产 PostgreSQL、生产 PVC、生产 Deployment/Service/Secret 或主 server Docker Compose。
`postgres-dev` 是 dev backend-core 与 dev Code Queue 状态的默认唯一数据库。dev 运行时必须使用 `postgres-dev.unidesk-dev.svc.cluster.local:5432/unidesk_dev` 和 dev Provider 身份 `D601-dev`;不得共享生产 `d601-tcp-egress-gateway.../unidesk`。Persistent dev backend-core target-side rollout, frontend/Decision Center/MDTODO/ClaudeQQ artifact rollout, dev-only Code Queue artifact rollout, public dev frontend port and Rust build boundary are defined in `docs/reference/dev-environment.md`.
`postgres-dev` 是 dev backend-core 与 dev Code Queue 状态的默认唯一数据库。dev 运行时必须使用 `postgres-dev.unidesk-dev.svc.cluster.local:5432/unidesk_dev` 和 dev Provider 身份 `D601-dev`;不得共享生产 `d601-tcp-egress-gateway.../unidesk`。Persistent dev backend-core/frontend/Decision Center/MDTODO/ClaudeQQ artifact rollout, dev-only Code Queue artifact rollout, public dev frontend port and Rust CI artifact boundary are defined in `docs/reference/dev-environment.md`.
验收入口:先运行 `bun scripts/cli.ts dev-env validate` 做静态资源与 DB URL 护栏检查;具备 D601 kubeconfig 时运行 `bun scripts/cli.ts dev-env validate --kubectl-dry-run` 做 Kubernetes client dry-run。首次或镜像缓存不确定时,先运行 `bun scripts/cli.ts dev-env prewarm-images`,把 `postgres:16-alpine` 和 local-path helper 所需的 `rancher/mirrored-library-busybox:1.36.1` 导入 D601 原生 k3s containerd;否则 D601 的 Docker 代理/缓存正常也不能保证 k3s/containerd 能实时拉到外部镜像。若实际 apply,只能 apply 到 `unidesk-dev`,随后用 `kubectl -n unidesk-dev get pods,svc,pvc` 验证 dev DB ready,并对比 apply 前后的 `kubectl -n unidesk get deploy,sts,svc,secret,pvc -o name` 证明生产 workload 未变化。
@@ -184,7 +184,7 @@ D601 上必须显式使用原生 k3s kubeconfig`KUBECONFIG=/etc/rancher/k3s/k
`backend-core-dev` 必须从 `unidesk-dev-runtime-config``unidesk-dev-runtime-secrets` 注入 dev-only 配置,使用 `postgres-dev.../unidesk_dev`、dev Provider token、dev log path 和 `UNIDESK_DEPLOY_REF=origin/master:deploy.json#environments.dev``frontend-dev` 必须把 `CORE_INTERNAL_URL` 指向 `backend-core-dev.unidesk-dev.svc.cluster.local:8080`,页面在 dev identity 下显示 DEV 标记,`/health` 返回 dev namespace、database、service id、deploy ref 和 commit metadata。生产环境未设置 dev identity 时,backend-core 和 frontend health payload 保持生产兼容形状。
`unidesk-dev-core.k8s.yaml` 当前使用 placeholder image/commit;正式 rollout 需要 `deploy apply --env dev` executor`origin/master:deploy.json#environments.dev` 替换 commit 并构建镜像。当前验收只做静态校验和 Kubernetes client dry-run,不能把 placeholder manifest 当成已上线。
`unidesk-dev-core.k8s.yaml` 当前使用 placeholder image/commit;正式 rollout 需要先由 CI 发布 commit-pinned artifact,再由 `deploy apply --env dev --service backend-core|frontend``origin/master:deploy.json#environments.dev` 读取 commit、拉取或导入成品镜像并更新 Deployment。当前验收只做静态校验和 Kubernetes client dry-run,不能把 placeholder manifest 当成已上线。
`unidesk-dev-mdtodo.k8s.yaml``unidesk-dev-claudeqq.k8s.yaml``unidesk-dev-code-queue.k8s.yaml` 是 D601 registry artifact consumer 的 dev manifests。它们只能创建 `unidesk-dev` 内的 ClusterIP Service/Deployment 对象,不得修改生产 `unidesk` namespace、主 server Compose 或新增 NodePort/hostPort。受控 rollout 必须使用 commit-pinned registry artifact、stamp `UNIDESK_DEPLOY_*` metadata,并通过 Kubernetes API service proxy 检查服务健康。
@@ -90,6 +90,16 @@ const ciCatalog = asRecord(JSON.parse(readFileSync(rootPath("CI.json"), "utf8"))
const artifacts = asArray(ciCatalog.artifacts, "CI.json.artifacts").map((item, index) => asRecord(item, `CI.json.artifacts[${index}]`));
const artifactByService = new Map(artifacts.map((item) => [String(item.serviceId), item]));
const backendCoreArtifact = asRecord(artifactByService.get("backend-core"), "CI.json artifact backend-core");
const backendCoreSource = asRecord(backendCoreArtifact.source, "CI.json artifact backend-core.source");
const backendCoreImage = asRecord(backendCoreArtifact.image, "CI.json artifact backend-core.image");
assertCondition(backendCoreArtifact.kind === "source-build", "backend-core producer must be source-build", backendCoreArtifact);
assertCondition(backendCoreArtifact.status === "supported", "backend-core producer must be supported", backendCoreArtifact);
assertCondition(backendCoreArtifact.producer === "ci publish-backend-core", "backend-core producer command must be publish-backend-core", backendCoreArtifact);
assertCondition(backendCoreSource.repo === "https://github.com/pikasTech/unidesk", "backend-core producer source repo mismatch", backendCoreSource);
assertCondition(backendCoreSource.dockerfile === "src/components/backend-core/Dockerfile", "backend-core producer dockerfile mismatch", backendCoreSource);
assertCondition(backendCoreImage.repository === "unidesk/backend-core", "backend-core registry repository mismatch", backendCoreImage);
for (const item of serviceCases) {
const artifact = asRecord(artifactByService.get(item.serviceId), `CI.json artifact ${item.serviceId}`);
const source = asRecord(artifact.source, `CI.json artifact ${item.serviceId}.source`);
@@ -158,9 +168,72 @@ for (const item of serviceCases) {
});
}
const backendCoreDevPlan = asRecord(await runArtifactRegistryCommand([
"deploy-service",
"--env",
"dev",
"--service",
"backend-core",
"--commit",
commit,
"--dry-run",
]), "backend-core dev dry-run plan");
const backendCoreDevTarget = asRecord(backendCoreDevPlan.target, "backend-core dev dry-run target");
const backendCoreDevLabels = asRecord(backendCoreDevPlan.requiredLabels, "backend-core dev dry-run labels");
const backendCoreDevRegistry = asRecord(backendCoreDevPlan.registry, "backend-core dev dry-run registry");
const backendCoreDevBuild = asRecord(backendCoreDevPlan.build, "backend-core dev dry-run build");
const backendCoreDevSource = asRecord(backendCoreDevPlan.source, "backend-core dev dry-run source");
const backendCoreDevValidation = asArray(backendCoreDevPlan.validation, "backend-core dev dry-run validation").map(String);
assertCondition(backendCoreDevPlan.ok === true, "backend-core dev dry-run must be ok", backendCoreDevPlan);
assertCondition(backendCoreDevPlan.dryRun === true && backendCoreDevPlan.mutation === false, "backend-core dev dry-run must be non-mutating", backendCoreDevPlan);
assertCondition(backendCoreDevPlan.environment === "dev", "backend-core dev dry-run must target dev", backendCoreDevPlan);
assertCondition(backendCoreDevPlan.serviceId === "backend-core", "backend-core dev service id mismatch", backendCoreDevPlan);
assertCondition(backendCoreDevPlan.sourceImage === `127.0.0.1:5000/unidesk/backend-core:${commit}`, "backend-core dev source image mismatch", backendCoreDevPlan);
assertCondition(backendCoreDevRegistry.imageRef === backendCoreDevPlan.sourceImage, "backend-core dev registry imageRef mismatch", backendCoreDevRegistry);
assertCondition(backendCoreDevRegistry.digest === null, "backend-core dev dry-run must not fake a digest", backendCoreDevRegistry);
assertCondition(String(backendCoreDevRegistry.digestSource ?? "").includes("manifest HEAD"), "backend-core dev digest source should name manifest HEAD", backendCoreDevRegistry);
assertCondition(backendCoreDevSource.repo === "https://github.com/pikasTech/unidesk", "backend-core dev source repo mismatch", backendCoreDevSource);
assertCondition(backendCoreDevSource.commit === commit, "backend-core dev source commit mismatch", backendCoreDevSource);
assertCondition(backendCoreDevSource.dockerfile === "src/components/backend-core/Dockerfile", "backend-core dev source dockerfile mismatch", backendCoreDevSource);
assertCondition(backendCoreDevBuild.willCompile === false, "backend-core dev CD dry-run must not compile", backendCoreDevBuild);
assertCondition(backendCoreDevBuild.willRunCargoBuild === false, "backend-core dev CD dry-run must not run cargo build", backendCoreDevBuild);
assertCondition(backendCoreDevBuild.willRunDockerBuild === false, "backend-core dev CD dry-run must not run docker build", backendCoreDevBuild);
assertCondition(backendCoreDevBuild.willRunDockerComposeBuild === false, "backend-core dev CD dry-run must not run docker compose build", backendCoreDevBuild);
assertCondition(backendCoreDevBuild.producerBoundary === "ci publish-backend-core", "backend-core dev producer boundary mismatch", backendCoreDevBuild);
assertCondition(backendCoreDevLabels["unidesk.ai/service-id"] === "backend-core", "backend-core dev required service label missing", backendCoreDevLabels);
assertCondition(backendCoreDevLabels["unidesk.ai/source-commit"] === commit, "backend-core dev required commit label missing", backendCoreDevLabels);
assertCondition(backendCoreDevLabels["unidesk.ai/dockerfile"] === "src/components/backend-core/Dockerfile", "backend-core dev required dockerfile label missing", backendCoreDevLabels);
assertCondition(backendCoreDevTarget.kind === "d601-k3s", "backend-core dev target must be D601 k3s", backendCoreDevTarget);
assertCondition(backendCoreDevTarget.namespace === "unidesk-dev", "backend-core dev namespace mismatch", backendCoreDevTarget);
assertCondition(backendCoreDevTarget.deployment === "backend-core-dev", "backend-core dev deployment mismatch", backendCoreDevTarget);
assertCondition(backendCoreDevTarget.service === "backend-core-dev", "backend-core dev service mismatch", backendCoreDevTarget);
assertCondition(backendCoreDevTarget.stableImage === "unidesk-backend-core:dev", "backend-core dev stable image mismatch", backendCoreDevTarget);
assertCondition(backendCoreDevTarget.runtimeImage === `unidesk-backend-core:${commit}`, "backend-core dev runtime image mismatch", backendCoreDevTarget);
assertCondition(backendCoreDevTarget.manifestRepoPath === "src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-core.k8s.yaml", "backend-core dev manifest mismatch", backendCoreDevTarget);
assertCondition(backendCoreDevValidation.some((line) => line.includes("registry /v2 manifest")), "backend-core dev must plan registry manifest validation", backendCoreDevValidation);
assertCondition(backendCoreDevValidation.some((line) => line.includes("native k3s containerd")), "backend-core dev must plan containerd import validation", backendCoreDevValidation);
assertCondition(backendCoreDevValidation.some((line) => line.includes("deploy.commit") && line.includes("deploy.requestedCommit")), "backend-core dev must plan health commit validation", backendCoreDevValidation);
assertCondition(!JSON.stringify(backendCoreDevPlan).includes("cargo build"), "backend-core dev dry-run must not include cargo build", backendCoreDevPlan);
assertCondition(!JSON.stringify(backendCoreDevPlan).includes("docker build"), "backend-core dev dry-run must not include docker build", backendCoreDevPlan);
assertCondition(!JSON.stringify(backendCoreDevPlan).includes("docker compose build"), "backend-core dev dry-run must not include compose build", backendCoreDevPlan);
assertCondition(!JSON.stringify(backendCoreDevPlan).includes("server rebuild"), "backend-core dev dry-run must not include server rebuild", backendCoreDevPlan);
plans.push({
serviceId: "backend-core",
environment: "dev",
sourceImage: backendCoreDevPlan.sourceImage,
deployment: backendCoreDevTarget.deployment,
service: backendCoreDevTarget.service,
deployCommandShape: backendCoreDevTarget.deployCommandShape,
});
process.stdout.write(`${JSON.stringify({
ok: true,
checks: [
"CI.json producer catalog covers backend-core publish-backend-core",
"dev backend-core dry-run is a non-mutating D601 k3s artifact consumer",
"dev backend-core dry-run exposes registry/source/build boundaries and does not compile",
"CI.json producer catalog covers the main-server direct artifact services",
"prod dry-run plans are non-mutating and commit-pinned",
"dry-run targets only the matching main-server Compose service with --no-build --no-deps --force-recreate",
@@ -41,6 +41,31 @@ assertCondition(findjobTarget.runtimeHost === "D601", "findjob target should be
assertCondition(findjobTarget.composeService === "server", "findjob compose service should be server", findjobTarget);
assertCondition(listIncludes(findjobTarget.forbiddenActions, "docker compose build"), "findjob plan should forbid Compose build", findjobTarget);
const backendCoreDev = runDeployPlan("dev", "backend-core");
const backendCoreArtifact = asRecord(backendCoreDev.artifactConsumer, "backend-core dev artifactConsumer");
const backendCoreTarget = asRecord(backendCoreDev.target, "backend-core dev target");
const backendCoreRegistry = asRecord(backendCoreArtifact.registry, "backend-core dev registry");
const backendCoreSource = asRecord(backendCoreArtifact.source, "backend-core dev source");
const backendCoreBuild = asRecord(backendCoreArtifact.build, "backend-core dev build");
assertCondition(backendCoreDev.deploymentPath === "d601-registry-artifact-consumer", "backend-core dev deployment path must be artifact consumer", backendCoreDev);
assertCondition(backendCoreArtifact.consumerKind === "d601-k3s-managed", "backend-core dev must be a D601 k3s-managed artifact consumer", backendCoreArtifact);
assertCondition(backendCoreArtifact.noRuntimeSourceBuild === true, "backend-core dev plan must declare no runtime source build", backendCoreArtifact);
assertCondition(String(backendCoreArtifact.registryImage ?? "").includes("127.0.0.1:5000/unidesk/backend-core:"), "backend-core dev registry image missing", backendCoreArtifact);
assertCondition(backendCoreRegistry.repository === "unidesk/backend-core", "backend-core dev registry repository mismatch", backendCoreRegistry);
assertCondition(backendCoreRegistry.digest === null, "backend-core dev plan must not fake digest", backendCoreRegistry);
assertCondition(String(backendCoreRegistry.digestSource ?? "").includes("manifest HEAD"), "backend-core dev digest source should name manifest HEAD", backendCoreRegistry);
assertCondition(backendCoreSource.repo === "https://github.com/pikasTech/unidesk", "backend-core dev source repo mismatch", backendCoreSource);
assertCondition(backendCoreBuild.willCompile === false, "backend-core dev plan must not compile in CD", backendCoreBuild);
assertCondition(backendCoreBuild.willRunCargoBuild === false, "backend-core dev plan must not run cargo build in CD", backendCoreBuild);
assertCondition(backendCoreBuild.willRunDockerBuild === false, "backend-core dev plan must not run docker build in CD", backendCoreBuild);
assertCondition(backendCoreBuild.producerBoundary === "ci publish-backend-core", "backend-core dev producer boundary mismatch", backendCoreBuild);
assertCondition(backendCoreTarget.namespace === "unidesk-dev", "backend-core dev target namespace should be unidesk-dev", backendCoreTarget);
assertCondition(backendCoreTarget.deployment === "backend-core-dev", "backend-core dev deployment should be backend-core-dev", backendCoreTarget);
assertCondition(backendCoreTarget.service === "backend-core-dev", "backend-core dev service should be backend-core-dev", backendCoreTarget);
assertCondition(backendCoreTarget.targetImage === "unidesk-backend-core:dev", "backend-core dev target image mismatch", backendCoreTarget);
assertCondition(listIncludes(backendCoreTarget.forbiddenActions, "docker build"), "backend-core dev plan should forbid docker build", backendCoreTarget);
assertCondition(listIncludes(backendCoreTarget.forbiddenActions, "docker compose build"), "backend-core dev plan should forbid compose build", backendCoreTarget);
const mdtodo = runDeployPlan("prod", "mdtodo");
const mdtodoArtifact = asRecord(mdtodo.artifactConsumer, "mdtodo artifactConsumer");
const mdtodoTarget = asRecord(mdtodo.target, "mdtodo target");
@@ -66,6 +91,8 @@ assertCondition(k3sctlTarget.composeService === "k3sctl-adapter", "k3sctl target
process.stdout.write(`${JSON.stringify({
ok: true,
checks: [
"deploy plan models dev backend-core as a no-build D601 k3s artifact consumer",
"dev backend-core plan exposes registry/source/build boundaries and target metadata",
"deploy plan distinguishes D601 direct Compose from D601 k3s-managed artifact consumers",
"deploy plan exposes no-runtime-source-build and forbidden build/public-port actions",
"met-nonlinear remains runtime-verification-blocked",
+50 -1
View File
@@ -207,6 +207,32 @@ const artifactConsumerSpecs: Record<string, ArtifactConsumerSpec> = {
},
},
},
"dev:backend-core": {
serviceId: "backend-core",
environment: "dev",
kind: "d601-k3s",
registryRepository: "unidesk/backend-core",
dockerfile: "src/components/backend-core/Dockerfile",
prodLiveApply: "enabled",
targets: {
dev: {
targetImage: "unidesk-backend-core:dev",
targetCommitImage: (commit: string) => `unidesk-backend-core:${commit}`,
deployRef: "origin/master:deploy.json#environments.dev.services.backend-core",
k3s: {
namespace: "unidesk-dev",
manifestRepoPath: "src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-core.k8s.yaml",
deploymentName: "backend-core-dev",
serviceName: "backend-core-dev",
servicePort: 8080,
containerName: "backend-core",
healthPath: "/health",
applySelector: "app.kubernetes.io/name=backend-core",
podLabelSelector: "app.kubernetes.io/name=backend-core,app.kubernetes.io/component=core,unidesk.ai/environment=dev",
},
},
},
},
"baidu-netdisk": {
serviceId: "baidu-netdisk",
environment: "prod",
@@ -2038,6 +2064,7 @@ function dryRunArtifactConsumerPlan(options: ArtifactRegistryOptions, spec: Arti
const verificationBlocked = spec.runtimeVerification === "blocked";
const livePolicy = environment === "prod" ? spec.prodLiveApply : "enabled";
const sourceImage = artifactImageRef(options, spec, commit);
const registryEndpoint = `http://127.0.0.1:${options.port}`;
const k3sDeployments = target.k3s === undefined
? []
: [
@@ -2059,6 +2086,27 @@ function dryRunArtifactConsumerPlan(options: ArtifactRegistryOptions, spec: Arti
sourceRepo: sourceRepoFor(options, spec),
deployRef: deployRefFor(options, spec),
sourceImage,
source: {
repo: sourceRepoFor(options, spec),
commit,
dockerfile: spec.dockerfile,
},
registry: {
endpoint: registryEndpoint,
repository: spec.registryRepository,
tag: commit,
imageRef: sourceImage,
digest: null,
digestHeader: "Docker-Content-Digest",
digestSource: "planned registry manifest HEAD; live apply must read this digest before mutation",
},
build: {
willCompile: false,
willRunCargoBuild: false,
willRunDockerBuild: false,
willRunDockerComposeBuild: false,
producerBoundary: spec.serviceId === "backend-core" ? "ci publish-backend-core" : "ci publish-user-service",
},
requiredLabels: {
"unidesk.ai/service-id": spec.serviceId,
"unidesk.ai/source-commit": commit,
@@ -2066,7 +2114,8 @@ function dryRunArtifactConsumerPlan(options: ArtifactRegistryOptions, spec: Arti
},
registryProbe: {
method: "HEAD",
url: `http://127.0.0.1:${options.port}/v2/${spec.registryRepository}/manifests/${commit}`,
url: `${registryEndpoint}/v2/${spec.registryRepository}/manifests/${commit}`,
digestHeader: "Docker-Content-Digest",
},
boundary: `${environment} CD is artifact-consumer only: verify commit-pinned registry image, pull/import, deploy, then verify live commit/image/health; it never builds source on the runtime target`,
liveApply: {
+1 -1
View File
@@ -367,7 +367,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
if (options.rust) {
items.push(rustCheckItem());
} else {
items.push(skippedItem("rust:backend-core", "Rust check/build must run on D601 dev deploy or CI, not on the master server", "--rust inside D601 CI with UNIDESK_D601_RUST_CHECK=1"));
items.push(skippedItem("rust:backend-core", "Rust check/build must run through D601 CI artifact publication, not on the master server or CD runtime target", "--rust inside D601 CI with UNIDESK_D601_RUST_CHECK=1"));
}
return { ok: items.every((item) => item.ok), mode: options.full ? "full" : "basic", options, items };
}
+29 -9
View File
@@ -139,9 +139,9 @@ const nativeK3sInstallVersion = "v1.34.1+k3s1";
const nativeK3sImage = "rancher/k3s:v1.34.1-k3s1";
const nativeK3sCtrAddress = "/run/k3s/containerd/containerd.sock";
const unideskRepoUrl = "https://github.com/pikasTech/unidesk";
const d601MaintenanceDeployAllowedServiceIds = new Set<string>(["backend-core", "k3sctl-adapter"]);
const devApplySupportedServiceIds = new Set<string>(["backend-core"]);
const devArtifactConsumerServiceIds = new Set<string>(["baidu-netdisk", "claudeqq", "code-queue", "code-queue-mgr", "decision-center", "findjob", "frontend", "mdtodo", "met-nonlinear", "oa-event-flow", "pipeline", "project-manager", "todo-note"]);
const d601MaintenanceDeployAllowedServiceIds = new Set<string>(["k3sctl-adapter"]);
const devApplySupportedServiceIds = new Set<string>();
const devArtifactConsumerServiceIds = new Set<string>(["backend-core", "baidu-netdisk", "claudeqq", "code-queue", "code-queue-mgr", "decision-center", "findjob", "frontend", "mdtodo", "met-nonlinear", "oa-event-flow", "pipeline", "project-manager", "todo-note"]);
const devArtifactConsumerProdDesiredFallbackServiceIds = new Set<string>(["code-queue-mgr", "oa-event-flow", "project-manager", "todo-note"]);
const prodArtifactConsumerServiceIds = new Set<string>(["backend-core", "baidu-netdisk", "claudeqq", "code-queue-mgr", "decision-center", "findjob", "frontend", "k3sctl-adapter", "mdtodo", "met-nonlinear", "oa-event-flow", "pipeline", "project-manager", "todo-note"]);
const prodForbiddenTargetSideBuildServiceIds = new Set<string>(["backend-core", "baidu-netdisk", "claudeqq", "decision-center", "findjob", "frontend", "k3sctl-adapter", "mdtodo", "met-nonlinear", "pipeline"]);
@@ -212,7 +212,7 @@ export function deployHelp(action: string | undefined = undefined): Record<strin
actions: {
check: "Validate desired repo+commit state against live service health and commit markers.",
plan: "Show desired/live drift, or with --env show the environment-ref dry-run plan without touching runtime resources.",
apply: "Start an async target-side reconcile job unless --run-now is explicitly present.",
apply: "Start an async deploy/reconcile job unless --run-now is explicitly present.",
guard: "Run local deployment guards without mutating runtime resources.",
},
releaseV1Frontend: {
@@ -223,7 +223,7 @@ export function deployHelp(action: string | undefined = undefined): Record<strin
},
options: [
{ name: "--file <path>", default: defaultDeployFile, description: "Desired-state manifest path relative to the repo root. JSON and ESM JS manifests are supported, for example deploy.json or develop.js. Local D601 maintenance apply is limited to approved direct exceptions; Code Queue direct rollout is disabled." },
{ name: "--env <dev|prod>", description: "Read the named environment from origin/master:deploy.json. Dev apply supports backend-core target-side rollout plus reviewed artifact consumers for frontend, baidu-netdisk, decision-center, mdtodo, claudeqq, dev-only code-queue, project-manager, oa-event-flow, code-queue-mgr, todo-note, findjob, pipeline, and met-nonlinear. Prod apply uses reviewed D601 registry artifact consumers; code-queue has no prod target and gated/incomplete services return structured unsupported or dry-run-only output." },
{ name: "--env <dev|prod>", description: "Read the named environment from origin/master:deploy.json. Dev apply supports reviewed artifact consumers for backend-core, frontend, baidu-netdisk, decision-center, mdtodo, claudeqq, dev-only code-queue, project-manager, oa-event-flow, code-queue-mgr, todo-note, findjob, pipeline, and met-nonlinear. Prod apply uses reviewed D601 registry artifact consumers; code-queue has no prod target and gated/incomplete services return structured unsupported or dry-run-only output." },
{ name: "--service <id>", description: "Limit reconcile to one service from the manifest." },
{ name: "--commit <full-sha>", description: "Artifact consumer override for one selected --env dev|prod service; the commit-pinned image must already exist in the D601 registry. This is the supported release/v1 frontend validation and rollback shape without editing a local manifest." },
{ name: "--dry-run", description: "Prepare and validate without mutating the target service." },
@@ -2773,7 +2773,7 @@ async function applyOneService(config: UniDeskConfig, service: UniDeskMicroservi
ok: false,
serviceId: service.id,
skipped: true,
reason: `D601 target-side deployment is allowed only for k3sctl-adapter and dev backend-core; artifact consumers must use registry CD. ${service.id} is not enabled. Use ci run-dev-e2e for smoke verification.`,
reason: `D601 target-side deployment is allowed only for k3sctl-adapter as a control-bridge maintenance path; artifact consumers must use registry CD. ${service.id} is not enabled. Use ci run-dev-e2e for smoke verification.`,
steps,
};
}
@@ -2969,6 +2969,26 @@ function environmentDryRunPlan(
} : {
consumerKind: unsupported ? "unsupported" : planKind,
registryImage: unsupported ? null : `127.0.0.1:5000/unidesk/${service.id}:${service.commitId}`,
registry: unsupported ? null : {
endpoint: "http://127.0.0.1:5000",
repository: `unidesk/${service.id}`,
tag: service.commitId,
imageRef: `127.0.0.1:5000/unidesk/${service.id}:${service.commitId}`,
digest: null,
digestSource: "planned registry manifest HEAD; live apply records Docker-Content-Digest before mutation",
},
source: unsupported ? null : {
repo: service.repo,
commit: service.commitId,
deployRef: `${source.ref}:deploy.json#environments.${environment}.services.${service.id}`,
},
build: unsupported ? null : {
willCompile: planKind === "d601-dev-target-side-build",
willRunCargoBuild: false,
willRunDockerBuild: planKind === "d601-dev-target-side-build",
willRunDockerComposeBuild: false,
producerBoundary: service.id === "backend-core" ? "ci publish-backend-core" : "ci publish-user-service",
},
noRuntimeSourceBuild: unsupported || planKind !== "d601-dev-target-side-build",
dryRunOnly: unsupported || (environment === "prod" && prodArtifactLiveApplyBlockedServiceIds.has(service.id)) || dryRunBlockedReason !== null,
blockedReason: unsupportedReason ?? dryRunBlockedReason ?? (environment === "prod" ? prodArtifactLiveApplyBlockedServiceIds.get(service.id) ?? null : null),
@@ -3029,7 +3049,7 @@ function blockedD601MaintenanceDeployServices(config: UniDeskConfig, manifest: D
}
function d601MaintenanceDeployBlockMessage(blocked: string[]): string {
return `D601 target-side deployment is enabled only for k3sctl-adapter and dev backend-core; artifact consumers must use registry CD. Blocked services: ${blocked.join(", ")}. Code Queue is dev-only through artifact-registry/deploy --env dev and has no production direct rollout path.`;
return `D601 target-side deployment is enabled only for k3sctl-adapter as a control-bridge maintenance path; artifact consumers must use registry CD. Blocked services: ${blocked.join(", ")}. Code Queue is dev-only through artifact-registry/deploy --env dev and has no production direct rollout path.`;
}
function selectedDevArtifactServices(manifest: DeployManifest, serviceId: string | null): DeployManifestService[] {
@@ -3088,7 +3108,7 @@ function commitOverrideArtifactConsumerError(options: DeployOptions): string | n
if (options.commitOverride === null) return null;
if (options.environment === "dev") {
if (options.serviceId !== null && devArtifactConsumerServiceIds.has(options.serviceId)) return null;
return `deploy --commit is supported for --env dev only on reviewed artifact consumers (${Array.from(devArtifactConsumerServiceIds).sort().join(", ")}); it must not switch dev target-side source builds such as backend-core away from deploy.json`;
return `deploy --commit is supported for --env dev only on reviewed artifact consumers (${Array.from(devArtifactConsumerServiceIds).sort().join(", ")})`;
}
if (options.environment === "prod") {
if (options.serviceId !== null && prodArtifactConsumerServiceIds.has(options.serviceId)) return null;
@@ -3300,7 +3320,7 @@ export async function runDeployCommand(config: UniDeskConfig | null, args: strin
}
const unsupported = unsupportedDevApplyServices(manifest, options.serviceId);
if (unsupported.length > 0) {
throw new Error(`deploy apply --env dev currently supports backend-core target-side rollout plus frontend/baidu-netdisk/decision-center/mdtodo/claudeqq/code-queue/project-manager/oa-event-flow/code-queue-mgr/todo-note/findjob/pipeline/met-nonlinear artifact consumers; unsupported selected services: ${unsupported.join(", ")}. Use ci run-dev-e2e for smoke verification.`);
throw new Error(`deploy apply --env dev currently supports backend-core/frontend/baidu-netdisk/decision-center/mdtodo/claudeqq/code-queue/project-manager/oa-event-flow/code-queue-mgr/todo-note/findjob/pipeline/met-nonlinear artifact consumers; unsupported selected services: ${unsupported.join(", ")}. Use ci run-dev-e2e for smoke verification.`);
}
const devArtifactServices = selectedDevArtifactServicesWithProdFallback(manifest, options.serviceId);
const devTargetServices = selectedDevTargetServices(manifest, options.serviceId);