refactor: retire legacy todo note runtime

This commit is contained in:
Codex
2026-07-10 05:35:20 +02:00
parent 5ab59dd63a
commit 259abeb0c0
18 changed files with 21 additions and 197 deletions
-42
View File
@@ -24,11 +24,6 @@ import { k3sGuardShellLines } from "../k3s-target-guard";
import { composeRuntimeEnvValue } from "../runtime-env";
import type { ArtifactConsumerSpec, AuthHealthGate, RuntimeSecretRequirement } from "./types";
import { todoNoteSyntheticHealthDeployProof } from "./types";
export function todoNoteHealthProbeCommand(): string {
return "bun -e \"fetch('http://127.0.0.1:4211/api/health').then(async r=>{const text=await r.text(); let body; try{body=JSON.parse(text)}catch{body={ok:r.ok,raw:text}}; console.log(JSON.stringify(body)); process.exit(r.ok?0:1)}).catch(e=>{console.error(e); process.exit(1)})\"";
}
export const baiduNetdiskRuntimeSecretRequirements: RuntimeSecretRequirement[] = [
{ sourceEnvName: "UNIDESK_BAIDU_NETDISK_CLIENT_ID", containerEnvName: "BAIDU_NETDISK_CLIENT_ID" },
@@ -593,43 +588,6 @@ export const artifactConsumerSpecs: Record<string, ArtifactConsumerSpec> = {
},
},
},
"todo-note": {
serviceId: "todo-note",
environment: "prod",
kind: "compose",
registryRepository: "unidesk/todo-note",
sourceRepo: "https://gitee.com/Lyon1998/todo_note",
dockerfile: "Dockerfile",
prodLiveApply: "enabled",
targets: {
dev: {
targetImage: "todo-note",
targetCommitImage: (commit: string) => `todo-note:${commit}`,
deployRef: "deploy.json#environments.dev.services.todo-note",
compose: {
serviceName: "todo-note",
containerName: "todo-note-backend",
deployEnvPrefix: "UNIDESK_TODO_NOTE_DEPLOY",
healthProbeCommand: todoNoteHealthProbeCommand(),
requireHealthCommit: true,
syntheticHealthDeployProof: todoNoteSyntheticHealthDeployProof,
},
},
prod: {
targetImage: "todo-note",
targetCommitImage: (commit: string) => `todo-note:${commit}`,
deployRef: "deploy.json#environments.prod.services.todo-note",
compose: {
serviceName: "todo-note",
containerName: "todo-note-backend",
deployEnvPrefix: "UNIDESK_TODO_NOTE_DEPLOY",
healthProbeCommand: todoNoteHealthProbeCommand(),
requireHealthCommit: true,
syntheticHealthDeployProof: todoNoteSyntheticHealthDeployProof,
},
},
},
},
"dev:frontend": {
serviceId: "frontend",
environment: "dev",
-4
View File
@@ -99,8 +99,6 @@ export function localHelp(): Record<string, unknown> {
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service project-manager --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service oa-event-flow --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service code-queue-mgr --commit <full-sha> --dry-run [--target D601]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service todo-note --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service todo-note --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
@@ -127,7 +125,6 @@ export function localHelp(): Record<string, unknown> {
"bun scripts/cli.ts deploy apply --env prod --service project-manager",
"bun scripts/cli.ts deploy apply --env prod --service oa-event-flow",
"bun scripts/cli.ts deploy apply --env prod --service code-queue-mgr --dry-run",
"bun scripts/cli.ts deploy apply --env prod --service todo-note",
"bun scripts/cli.ts deploy apply --env prod --service findjob",
"bun scripts/cli.ts deploy apply --env prod --service pipeline",
"bun scripts/cli.ts deploy apply --env prod --service met-nonlinear --dry-run",
@@ -141,7 +138,6 @@ export function localHelp(): Record<string, unknown> {
"bun scripts/cli.ts deploy apply --env dev --service project-manager --dry-run",
"bun scripts/cli.ts deploy apply --env dev --service oa-event-flow --dry-run",
"bun scripts/cli.ts deploy apply --env dev --service code-queue-mgr --dry-run",
"bun scripts/cli.ts deploy apply --env dev --service todo-note",
"bun scripts/cli.ts deploy apply --env dev --service findjob --dry-run",
"bun scripts/cli.ts deploy apply --env dev --service pipeline --dry-run",
"bun scripts/cli.ts deploy apply --env dev --service met-nonlinear --dry-run",
-6
View File
@@ -178,7 +178,6 @@ export const supportedArtifactConsumerServices = [
"oa-event-flow",
"pipeline",
"project-manager",
"todo-note",
] as const;
export type SupportedArtifactConsumerService = typeof supportedArtifactConsumerServices[number];
@@ -292,8 +291,3 @@ export interface RuntimeSecretContract {
requirements: RuntimeSecretRequirementStatus[];
dryRunDisposition: "not-required" | "ready-for-live-apply" | "secret-source-blocked";
}
export const todoNoteSyntheticHealthDeployProof: SyntheticHealthDeployProof = {
kind: "compose-container-runtime-metadata",
description: "todo-note /api/health does not natively expose deploy metadata, so the artifact consumer synthesizes health.deploy from the recreated container's UNIDESK_DEPLOY_* env and verifies it against image/container labels.",
};
+1 -1
View File
@@ -72,7 +72,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 auth-broker/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.`);
throw new Error(`deploy apply --env dev currently supports auth-broker/backend-core/frontend/baidu-netdisk/decision-center/mdtodo/claudeqq/code-queue/project-manager/oa-event-flow/code-queue-mgr/findjob/pipeline/met-nonlinear artifact consumers; unsupported selected services: ${unsupported.join(", ")}. Todo Note uses NC01 PaC/Argo. Use ci run-dev-e2e for smoke verification.`);
}
const devArtifactServices = selectedDevArtifactServicesWithProdFallback(manifest, options.serviceId);
const devTargetServices = selectedDevTargetServices(manifest, options.serviceId);
+1 -1
View File
@@ -63,7 +63,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 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: "--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, findjob, pipeline, and met-nonlinear. Todo Note uses NC01 PaC/Argo. 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." },
-3
View File
@@ -495,9 +495,6 @@ export function artifactConsumerPlanValidation(service: UniDeskMicroserviceConfi
...base,
"recreates only the selected Compose service with --no-build --no-deps --force-recreate",
"verifies running image labels and private service health",
...(service.id === "todo-note" ? [
"todo-note runtime proof synthesizes health.deploy.commit/requestedCommit from Compose container env, container labels, and image labels; it does not infer commit from /root/todo_note or any source directory",
] : []),
];
}
return ["unsupported service remains blocked before source materialization or runtime mutation"];
+3 -3
View File
@@ -185,11 +185,11 @@ export const targetSideMaintenanceDeployAllowedServiceIds = new Set<string>(["k3
export const devApplySupportedServiceIds = new Set<string>();
export const devArtifactConsumerServiceIds = new Set<string>(["auth-broker", "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"]);
export const devArtifactConsumerServiceIds = new Set<string>(["auth-broker", "backend-core", "baidu-netdisk", "claudeqq", "code-queue", "code-queue-mgr", "decision-center", "findjob", "frontend", "mdtodo", "met-nonlinear", "oa-event-flow", "pipeline", "project-manager"]);
export const devArtifactConsumerProdDesiredFallbackServiceIds = new Set<string>(["code-queue-mgr", "oa-event-flow", "project-manager", "todo-note"]);
export const devArtifactConsumerProdDesiredFallbackServiceIds = new Set<string>(["code-queue-mgr", "oa-event-flow", "project-manager"]);
export const prodArtifactConsumerServiceIds = new Set<string>(["auth-broker", "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"]);
export const prodArtifactConsumerServiceIds = new Set<string>(["auth-broker", "backend-core", "baidu-netdisk", "claudeqq", "code-queue-mgr", "decision-center", "findjob", "frontend", "k3sctl-adapter", "mdtodo", "met-nonlinear", "oa-event-flow", "pipeline", "project-manager"]);
export const prodForbiddenTargetSideBuildServiceIds = new Set<string>(["backend-core", "baidu-netdisk", "claudeqq", "decision-center", "findjob", "frontend", "k3sctl-adapter", "mdtodo", "met-nonlinear", "pipeline"]);
+2 -16
View File
@@ -45,7 +45,7 @@ export interface DeprecatedHostComposeEntry {
references: string[];
}
const rebuildableServices = ["backend-core", "frontend", "dev-frontend-proxy", "provider-gateway", "todo-note", "project-manager", "baidu-netdisk", "oa-event-flow", "code-queue-mgr"] as const;
const rebuildableServices = ["backend-core", "frontend", "dev-frontend-proxy", "provider-gateway", "project-manager", "baidu-netdisk", "oa-event-flow", "code-queue-mgr"] as const;
const restartableServices = [...rebuildableServices, "pk01-postgres-relay"] as const;
export type RebuildableService = typeof rebuildableServices[number];
export type RestartableService = typeof restartableServices[number];
@@ -257,11 +257,6 @@ export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean):
UNIDESK_AUTH_BROKER_GITHUB_CONFIGURED: runtimeSecret("UNIDESK_AUTH_BROKER_GITHUB_CONFIGURED") || "false",
UNIDESK_AUTH_BROKER_GITHUB_CREDENTIAL_REF: runtimeSecret("UNIDESK_AUTH_BROKER_GITHUB_CREDENTIAL_REF") || "github:unidesk-dev",
UNIDESK_AUTH_BROKER_ALLOWED_REPOS: runtimeSecret("UNIDESK_AUTH_BROKER_ALLOWED_REPOS") || "pikasTech/unidesk",
UNIDESK_TODO_NOTE_DEPLOY_REF: runtimeSecret("UNIDESK_TODO_NOTE_DEPLOY_REF"),
UNIDESK_TODO_NOTE_DEPLOY_SERVICE_ID: runtimeSecret("UNIDESK_TODO_NOTE_DEPLOY_SERVICE_ID") || "todo-note",
UNIDESK_TODO_NOTE_DEPLOY_REPO: runtimeSecret("UNIDESK_TODO_NOTE_DEPLOY_REPO"),
UNIDESK_TODO_NOTE_DEPLOY_COMMIT: runtimeSecret("UNIDESK_TODO_NOTE_DEPLOY_COMMIT"),
UNIDESK_TODO_NOTE_DEPLOY_REQUESTED_COMMIT: runtimeSecret("UNIDESK_TODO_NOTE_DEPLOY_REQUESTED_COMMIT"),
UNIDESK_AUTH_USERNAME: config.auth.username,
UNIDESK_AUTH_PASSWORD: config.auth.password,
UNIDESK_SESSION_SECRET: config.auth.sessionSecret,
@@ -290,15 +285,6 @@ export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean):
UNIDESK_HOST_SSH_HOST: config.sshForwarding.host,
UNIDESK_HOST_SSH_PORT: String(config.sshForwarding.port),
UNIDESK_HOST_SSH_USER: config.sshForwarding.user,
UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_ENABLED: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_ENABLED") || "true",
UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_BASE_URL: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_BASE_URL") || "http://backend-core:8080/api/microservices/claudeqq/proxy",
UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_TARGET_TYPE: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_TARGET_TYPE") || "private",
UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_USER_ID: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_USER_ID") || "645275593",
UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_GROUP_ID: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_GROUP_ID"),
UNIDESK_TODO_NOTE_REMINDER_LEAD_MINUTES: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_LEAD_MINUTES") || "10",
UNIDESK_TODO_NOTE_REMINDER_SCAN_INTERVAL_MS: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_SCAN_INTERVAL_MS") || "30000",
UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_TIMEOUT_MS: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_TIMEOUT_MS") || "15000",
UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_SEND_ATTEMPTS: runtimeSecret("UNIDESK_TODO_NOTE_REMINDER_CLAUDEQQ_SEND_ATTEMPTS") || "3",
UNIDESK_CODE_QUEUE_MINIMAX_API_KEY: runtimeSecret("UNIDESK_CODE_QUEUE_MINIMAX_API_KEY") || runtimeSecret("MINIMAX_API_KEY"),
UNIDESK_CODE_QUEUE_MINIMAX_MODEL: runtimeSecret("UNIDESK_CODE_QUEUE_MINIMAX_MODEL") || runtimeSecret("MINIMAX_MODEL") || "MiniMax-M2.7",
UNIDESK_CODE_QUEUE_MINIMAX_M3_MODEL: runtimeSecret("UNIDESK_CODE_QUEUE_MINIMAX_M3_MODEL") || runtimeSecret("MINIMAX_M3_MODEL") || "MiniMax-M3",
@@ -814,7 +800,7 @@ export function stackLogs(config: UniDeskConfig, tailBytes: number): unknown {
const truncated = sizeBytes > tailBytes;
return { path, name: basename(path), sizeBytes, tailBytes, truncated, tail: tailFile(path, tailBytes) };
});
const containerNames = ["unidesk-database", "unidesk-backend-core", "unidesk-frontend", "unidesk-dev-frontend-proxy", "unidesk-provider-gateway-main", "unidesk-pk01-postgres-relay", "todo-note-backend", "project-manager-backend", "baidu-netdisk-backend", "oa-event-flow-backend"];
const containerNames = ["unidesk-database", "unidesk-backend-core", "unidesk-frontend", "unidesk-dev-frontend-proxy", "unidesk-provider-gateway-main", "unidesk-pk01-postgres-relay", "project-manager-backend", "baidu-netdisk-backend", "oa-event-flow-backend"];
const docker = containerNames.map((name) => {
const result = runCommand(["docker", "logs", "--tail", "40", name], repoRoot);
return {
+5 -6
View File
@@ -24,8 +24,8 @@ export function rootHelp(): unknown {
{ command: "server logs [--tail-bytes N]", description: "Return bounded tails from file logs and docker logs." },
{ command: "server cleanup plan [--min-age-hours N] [--limit N]", description: "Dry-run Docker image cleanup plan only: list active/protected images, stale candidates older than the default 24h threshold, risk, estimated reclaim, and manual review commands without deleting anything." },
{ command: "gc plan|run|db-trace|policy|remote [--confirm] [--logs-keep-days N] [--include-browser-cache]", description: "One-time main-server or remote provider disk relief and low-risk anti-bloat policy for logs, journald, allowlisted /tmp artifacts, scoped core dumps and explicit trace telemetry retention; plan is read-only and run requires --confirm." },
{ command: "server rebuild <backend-core|frontend|dev-frontend-proxy|provider-gateway|todo-note|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>", description: "Maintenance-only local Compose rebuild for reviewed main-server services; frontend standard release must use CI artifact plus deploy apply dev/prod artifact consumers." },
{ command: "server restart <backend-core|frontend|dev-frontend-proxy|provider-gateway|pk01-postgres-relay|todo-note|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>", description: "No-build single-service Compose restart for reviewed main-server maintenance recovery; returns an async job and validates the recreated container." },
{ command: "server rebuild <backend-core|frontend|dev-frontend-proxy|provider-gateway|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>", description: "Maintenance-only local Compose rebuild for reviewed main-server services; frontend standard release must use CI artifact plus deploy apply dev/prod artifact consumers." },
{ command: "server restart <backend-core|frontend|dev-frontend-proxy|provider-gateway|pk01-postgres-relay|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>", description: "No-build single-service Compose restart for reviewed main-server maintenance recovery; returns an async job and validates the recreated container." },
{ command: "provider attach <providerId> [--master-server URL] [--up] [--force] | provider triage <providerId> [--observed-error text] [--observed-scope scope] [--microservice id ...] [--full|--raw]", description: "Generate the minimal external provider-gateway env/compose bundle or run the low-noise read-only provider health triage contract." },
{ command: "trans <route> [operation args...] (alias of ssh <route> ...)", description: "Open a Host SSH / WSL SSH maintenance session; provider WebSocket carries control and host.ssh.tcp-pool carries stdin/stdout/stderr data." },
{ command: "trans gh:/owner/repo[/pr|/issue][/number[/1]] ls|cat|rg|apply-patch", description: "Treat GitHub PRs/issues as virtual text directories; `issue ls --search/--state` covers filtered reads, `cat|rg` reads first-floor body text, and `apply-patch` updates `body.md` through UniDesk gh plus apply-patch v2." },
@@ -127,8 +127,8 @@ export function serverHelp(action: string | undefined = undefined): unknown {
swap: "bun scripts/cli.ts server swap status|ensure [--path /swapfile] [--size 2GiB] [--dry-run]",
logs: "bun scripts/cli.ts server logs [--tail-bytes N]",
cleanup: "bun scripts/cli.ts server cleanup plan [--min-age-hours N] [--limit N]",
rebuild: "bun scripts/cli.ts server rebuild <backend-core|frontend|dev-frontend-proxy|provider-gateway|todo-note|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>",
restart: "bun scripts/cli.ts server restart <backend-core|frontend|dev-frontend-proxy|provider-gateway|pk01-postgres-relay|todo-note|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>",
rebuild: "bun scripts/cli.ts server rebuild <backend-core|frontend|dev-frontend-proxy|provider-gateway|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>",
restart: "bun scripts/cli.ts server restart <backend-core|frontend|dev-frontend-proxy|provider-gateway|pk01-postgres-relay|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>",
},
cleanupPlan: {
dryRunOnly: true,
@@ -613,7 +613,6 @@ function artifactRegistryHelp(): unknown {
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service project-manager --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service oa-event-flow --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service code-queue-mgr --commit <full-sha> --dry-run [--target <id>]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service todo-note --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
@@ -633,7 +632,7 @@ function artifactRegistryHelp(): unknown {
"service is host-managed by systemd + Docker Compose, not k3s-managed",
"install writes the rendered host unit/config and starts the registry",
"deploy-backend-core only pulls commit-pinned backend-core artifacts and does not build backend-core on the master server",
"deploy-service currently supports 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, and dev-only code-queue as standardized consumers",
"deploy-service currently supports backend-core, baidu-netdisk, prod/dev frontend, decision-center, mdtodo, claudeqq, project-manager, oa-event-flow, code-queue-mgr, findjob, pipeline, met-nonlinear, k3sctl-adapter, and dev-only code-queue as standardized consumers; Todo Note uses NC01 PaC/Argo",
"findjob and pipeline have D601 direct dev/prod Compose artifact consumers; met-nonlinear is runtime-verification blocked; k3sctl-adapter is supervisor-only",
"code-queue has no prod artifact deploy target; dev requests are dry-run evidence only unless a human operator or supervisor authorizes DEV apply outside Code Queue",
"status and health use provider-gateway Host SSH readonly checks",