From 5b01dad112b8d11ce95c623990f47fcf2f66850d Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 29 May 2026 02:36:29 +0000 Subject: [PATCH] fix: remove stale code queue execution gate --- AGENTS.md | 2 +- docs/reference/code-queue-supervision.md | 2 +- ...ode-queue-execution-plane-contract-test.ts | 205 ------------------ scripts/src/check.ts | 4 - scripts/src/code-queue-execution-plane.ts | 180 +-------------- scripts/src/help.ts | 4 +- 6 files changed, 6 insertions(+), 391 deletions(-) delete mode 100644 scripts/code-queue-execution-plane-contract-test.ts diff --git a/AGENTS.md b/AGENTS.md index fc92d764..5ad195ef 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -165,7 +165,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - `bun scripts/cli.ts hwlab cd audit --env dev` / `status|preflight|apply --dry-run`:旧 D601 HWLAB DEV CD 指挥侧 wrapper,仅用于显式 legacy 诊断和迁移对照;当前 HWLAB DEV/PROD source/runtime truth 已迁到 G14 `/root/hwlab` 与 G14 k3s/GitOps,规则见 `docs/reference/hwlab.md`。 - `bun scripts/cli.ts ci install/status/run/publish-backend-core/publish-user-service/run-dev-e2e/logs`:在 D601 原生 k3s 上安装和运行 Tekton CI,支持每 commit 检查、Code Queue 只读性能门禁、`CI.json` catalog 驱动的 backend-core 与 user-service commit-pinned 镜像发布和手动触发的 `origin/master:deploy.json#environments.dev` 临时 namespace e2e;catalog/producer/consumer 分工见 `docs/reference/cicd-standardization.md`,`run-dev-e2e` 的 Git 控制 runner、短 launcher 和 no-CD 边界见 `docs/reference/dev-ci-runner.md`,Tekton 规则见 `docs/reference/ci.md`。 - `bun scripts/cli.ts codex deploy `:旧 Code Queue 兼容部署入口已禁用,原因是它会绕过受控部署边界直连 D601 部署 Code Queue;规则见 `docs/reference/codex-deploy.md`。 -- `bun scripts/cli.ts codex prompt-lint [prompt|--prompt-file path|--prompt-stdin]` / `codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue ]` / `codex execution-plane [--full|--raw]` / `codex pr-preflight [--remote]`:`prompt-lint` 在派发/steer 前 dry-run 检查 runner prompt 的 DEV 测试授权分级(`read-only`/`live-read`/`live-mutating`)且不回显 prompt;`submit --dry-run` 同时给出 MiniMax/GPT/人工路由建议、该 lint 结果和 requested/effective execution mode;真实提交成功只返回写入确认、task id、服务级 runnerPermissions 和后续查看命令,不回显 prompt;`execution-plane` 通过 `tran D601:k3s` 只读比较 D601 原生 k3s 正式 Code Queue 执行面、旧 Compose 残留、commit/digest/worktree/probe drift;`pr-preflight` 只读检查 D601 scheduler/runner 的 GitHub token、egress 和 PR 能力,PR 型派单前必须使用,规则见 `docs/reference/cli.md` 和 `docs/reference/code-queue-supervision.md`。 +- `bun scripts/cli.ts codex prompt-lint [prompt|--prompt-file path|--prompt-stdin]` / `codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue ]` / `codex execution-plane [--full|--raw]` / `codex pr-preflight [--remote]`:`prompt-lint` 在派发/steer 前 dry-run 检查 runner prompt 的 DEV 测试授权分级(`read-only`/`live-read`/`live-mutating`)且不回显 prompt;`submit --dry-run` 同时给出 MiniMax/GPT/人工路由建议、该 lint 结果和 requested/effective execution mode;真实提交成功只返回写入确认、task id、服务级 runnerPermissions 和后续查看命令,不回显 prompt;`execution-plane` 通过 `tran D601:k3s` 只读观察 D601 原生 k3s 正式 Code Queue 执行面、旧 Compose 残留、commit/digest/worktree drift;`pr-preflight` 只读检查 D601 scheduler/runner 的 GitHub token、egress 和 PR 能力,PR 型派单前必须使用,规则见 `docs/reference/cli.md` 和 `docs/reference/code-queue-supervision.md`。 - `bun scripts/cli.ts codex task `:按 Code Queue 任务 ID 查询默认审阅摘要,只返回原始 prompt、最终 response、最后错误和渐进披露命令;`codex tasks --view commander` 是 host commander 推荐轮询入口,默认有界显示 active runner 精确计数、queued/retry_wait、terminal-unread、active 风险、分类和 drill-down 命令;`--view supervisor|full`、`codex output` 和大 `--limit` 仍默认有界,完整内容需显式 `--full`/`--full-text`/分页展开;`codex queues [--full] [--limit N] [--page N|--offset N]` 默认分页低噪声输出队列摘要,完整 upstream 只通过 raw command 显式获取。 - `bun scripts/cli.ts codex unread [--repo owner/name] [--issue N] [--limit N]`:只读汇总完成未读积压并给出 repo/issue/status/queue 计数和 drill-down/read 命令;批量已读必须显式 `codex unread mark-read ... --confirm`,规则见 `docs/reference/cli.md`。 - `bun scripts/cli.ts codex judge --attempt [--dry-run]`:按指定 task/attempt 用与队列 worker 相同的上下文构建和 MiniMax judge 调用路径单步复现完成判定;`--dry-run` 只输出 prompt/payload 诊断。 diff --git a/docs/reference/code-queue-supervision.md b/docs/reference/code-queue-supervision.md index 87af618e..3f2bca45 100644 --- a/docs/reference/code-queue-supervision.md +++ b/docs/reference/code-queue-supervision.md @@ -280,7 +280,7 @@ replacement runner 只用于方向明显错误、质量不可接受、原 task - `bun scripts/cli.ts codex tasks --view commander --limit N`:host commander 轮询的推荐入口。输出是有界 action map,必须直接显示 `activeRunners.count`、计数来源、split-brain/heartbeat 处置、queued/retry_wait 精确计数、terminal-unread 总数和已省略行数、active 风险数、stale/heartbeat/trace gap、`finalResponse` 已出现但仍非终态的 awaiting terminal/judge、blocker-like final response、HWLAB#7/#99/#116/#164/#317 与 UniDesk#20/#118 命中、任务分类和下一步 drill-down 命令。默认不得输出完整 prompt、完整 final response、raw output、完整 trace 或 raw overview;需要详情只能按 task id 使用 `codex task`、`codex task --trace`、`codex output`、`codex read` 或 `rawOverview` 命令渐进展开。 - `bun scripts/cli.ts codex tasks --view supervisor --limit N`:查看默认低噪声监督视图,包括 `activeRunning`、running、完成未读、少量最近完成、queued/runnable、activity、commanderConcurrency、execution diagnostics、任务分类和下一步 drill-down 命令。默认行只保留 task id、队列、短 prompt/body 预览和原始字符数;`--limit` 是扫描/分页预算,不是返回几十条肥行的开关,CLI effective limit 安全上限为 100,输出必须用 `filters.requestedLimit`、`filters.effectiveLimit`、`filters.limitCapped`、`source.requestedLimit` 和 `source.effectiveLimit` 区分用户请求、CLI cap 和 overview 源拉取预算;例如 `--limit 260` 应明确显示 requested=260、effective=100、source=200,`running.returned` 只是低噪声返回行数。`show/detail/trace/output/full/read` 放在 section template 中,避免每条任务重复刷屏,需要更多内容再按 taskId 展开。刚执行 `codex submit` 后也可以先读 submit 返回的 `submitted.taskStates[]`、`queue.countContext`、`queue.activity.effectiveActiveTaskCount` 和 `queue.stateDisclosure`;若某个 id preview 有 `idsUnavailable=true`,不要把它当成空队列,按 `queue.listPreviewPolicy.rawCommand` 或本 supervisor 命令继续查。 - `bun scripts/cli.ts codex queues`:默认是 commander-first 队列态势摘要,`--commander` 是显式同义开关。输出前部固定使用 `.data.queues.commander`,先给出 `activeRunnerCount`、`source`、`target=15`、`slotDeficit`、`queuedCount`、`runningTasks`、`heartbeat.fresh`、`heartbeat.risk`、`heartbeat.staleRecoveryCandidates`、active/runnable queue 小页和 drill-down 命令;历史 queue item 列表保留在 `.data.queues.items[]`,但只是分页的次要行。需要完整队列行视图时加 `--full`,但 `--full` 仍默认分页,继续用 `--limit N`、`--page N` 或 `--offset N` 渐进展开。summary 和 full 都使用稳定 JSON path `.data.queues.items[]` 读取队列行,并从 `.data.queues.commander`、`.data.queues.commanderConcurrency`、`.data.queues.activity`、`.data.queues.counts` 与 `.data.queues.executionDiagnostics` 读取全局活跃计数和执行诊断;完整 upstream 只通过输出中的 raw command 显式获取。若 `/api/queues` 没有返回 task row,`runningTasks.items[].name` 会是 `null` 且 `nameSource=not-returned-by-api-queues`,此时按返回的 `codex task ` 或 supervisor 命令展开,不要假设任务没有名称。 -- `bun scripts/cli.ts codex execution-plane [--full|--raw]`:只读巡检 D601 原生 k3s `unidesk` namespace 下的正式执行面。该命令的 live collector 必须通过 UniDesk `tran`/`ssh` 维护桥访问 `D601:k3s` 和 `D601:/home/ubuntu/cq-deploy`,不得在 master server 本地调用 `kubectl`、读取本地 worktree 或把 master server 的工具缺失误报成 D601 阻塞。该命令强制使用 `KUBECONFIG=/etc/rancher/k3s/k3s.yaml` 并确认 node `d601`,默认低噪声返回 `summary.formalExecutionPlane`、`summary.deploymentDrift`、`summary.deprecatedComposeResidual`、`executionPlane.deployments[]`、`drift.status`、`residual.status` 和 `judgeProbe.behaviorVersion`。它比较三类 Deployment:`code-queue` 必须是 scheduler,`code-queue-read` 必须是 read,`code-queue-write` 必须是 write;同时比较 deployment env/annotation commit、Pod `imageID` digest、宿主 `/home/ubuntu/cq-deploy` HEAD、以及 `/api/judge/probe` 的 `behaviorVersion=code-queue-judge-probe:v1`。任何 commit/digest/worktree/probe 不一致或缺少可比 marker 都必须输出 `deployment-drift`,不能写成 healthy。检测到 D601 上旧 Docker Compose `code-queue-backend` 或旧 `127.0.0.1:4222` 监听时必须输出 `deprecated-compose-residual`。默认不打印完整 Kubernetes Deployment JSON、环境变量全集、SecretRef 值、judge probe 原始结果或命令 stdout;需要逐项展开时使用 `--full`,需要安全裁剪后的原始观察对象时使用 `--raw`。 +- `bun scripts/cli.ts codex execution-plane [--full|--raw]`:只读巡检 D601 原生 k3s `unidesk` namespace 下的正式执行面。该命令的 live collector 必须通过 UniDesk `tran`/`ssh` 维护桥访问 `D601:k3s` 和 `D601:/home/ubuntu/cq-deploy`,不得在 master server 本地调用 `kubectl`、读取本地 worktree 或把 master server 的工具缺失误报成 D601 阻塞。该命令强制使用 `KUBECONFIG=/etc/rancher/k3s/k3s.yaml` 并确认 node `d601`,默认低噪声返回 `summary.formalExecutionPlane`、`summary.deploymentDrift`、`summary.deprecatedComposeResidual`、`executionPlane.deployments[]`、`drift.status` 和 `residual.status`。它比较三类 Deployment:`code-queue` 必须是 scheduler,`code-queue-read` 必须是 read,`code-queue-write` 必须是 write;同时比较 deployment env/annotation commit、Pod `imageID` digest 和宿主 `/home/ubuntu/cq-deploy` HEAD。任何 commit/digest/worktree 不一致或缺少可比 marker 都必须输出 `deployment-drift`,不能写成 healthy。检测到 D601 上旧 Docker Compose `code-queue-backend` 或旧 `127.0.0.1:4222` 监听时必须输出 `deprecated-compose-residual`。该命令不再把 `/api/judge/probe` 或 behaviorVersion 作为门禁;Code Queue runner 能力必须用真实 `codex submit`/任务审阅和人工交互命令在目标运行面闭环验收。默认不打印完整 Kubernetes Deployment JSON、环境变量全集、SecretRef 值或命令 stdout;需要逐项展开时使用 `--full`,需要安全裁剪后的原始观察对象时使用 `--raw`。 - `bun scripts/cli.ts codex unread --limit N`:查看完成未读审阅积压的默认 triage,按 repo、issue、status 和 queue 汇总,并给出有界最新任务紧凑行;默认行只包含 task id、状态、queue、issues、updatedAt/finishedAt 和一条 `nextStep`,不重复每任务 `show/detail/trace/output/read` 命令,也不输出 raw prompt、final response、trace 或 output。完整 per-task 命令必须显式使用 `codex unread --full`、`codex unread --view full`、`codex unread list` 或单任务 `codex task `/`codex read ` 展开;默认输出必须保留一次性的模板命令和分页命令。 - `bun scripts/cli.ts codex unread mark-read --repo owner/name --issue N --limit N --confirm`:批量已读入口,必须显式 `mark-read` 和 `--confirm`,否则结构化失败且不 POST `/read`。 - `bun scripts/cli.ts codex tasks --unread --limit N`:兼容查看完成未读审阅积压;`--unread` 与 `--unread-only` 等价,不能被静默忽略。 diff --git a/scripts/code-queue-execution-plane-contract-test.ts b/scripts/code-queue-execution-plane-contract-test.ts deleted file mode 100644 index 7818a399..00000000 --- a/scripts/code-queue-execution-plane-contract-test.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { - expectedJudgeProbeBehaviorVersion, - runCodeQueueExecutionPlaneForTest, - type CodeQueueExecutionPlaneObservation, -} from "./src/code-queue-execution-plane"; -import { readFileSync } from "node:fs"; - -type JsonRecord = Record; - -function assertCondition(condition: unknown, message: string, detail: JsonRecord = {}): void { - if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`); -} - -const commit = "62c613eefc84292fe1874a837685b073ac6c7295"; -const otherCommit = "0c3cdb4ee06a23361ed511a2da033d67b53d16f4"; -const digest = `sha256:${"1".repeat(64)}`; -const otherDigest = `sha256:${"2".repeat(64)}`; - -function deployment(name: string, role: "scheduler" | "read" | "write", schedulerEnabled: "true" | "false", overrides: Partial = {}): CodeQueueExecutionPlaneObservation["deployments"][number] { - return { - name, - namespace: "unidesk", - observed: true, - expectedRole: role, - expectedSchedulerEnabled: schedulerEnabled, - labels: { - app: "code-queue", - component: role === "scheduler" ? null : role, - deploymentMode: "k3sctl-managed", - instanceId: role === "scheduler" ? "D601" : `D601-${role}`, - }, - annotations: { - deployRef: "origin/master:deploy.json#environments.prod.services.code-queue", - deployCommit: commit, - deployRequestedCommit: commit, - imageSource: "deploy-env-commit", - }, - replicas: { - desired: role === "read" ? 2 : 1, - ready: role === "read" ? 2 : 1, - available: role === "read" ? 2 : 1, - updated: role === "read" ? 2 : 1, - }, - nodeSelector: "D601", - image: "unidesk-code-queue:d601", - env: { - serviceRole: role, - schedulerEnabled, - unideskDeployCommit: commit, - unideskDeployRequestedCommit: commit, - codeQueueDeployCommit: commit, - codeQueueDeployRequestedCommit: commit, - }, - repoHostPath: "/home/ubuntu/cq-deploy", - error: null, - ...overrides, - }; -} - -function healthyObservation(overrides: Partial = {}): CodeQueueExecutionPlaneObservation { - const base: CodeQueueExecutionPlaneObservation = { - checkedAt: "2026-05-24T00:00:00.000Z", - namespace: "unidesk", - kubeconfig: "/etc/rancher/k3s/k3s.yaml", - worktreePath: "/home/ubuntu/cq-deploy", - guard: { - status: "pass", - refusal: false, - refusalSignals: [], - kubeconfig: "/etc/rancher/k3s/k3s.yaml", - expectedKubeconfig: "/etc/rancher/k3s/k3s.yaml", - currentContext: "default", - apiServer: "https://127.0.0.1:6443", - nodeNames: ["d601"], - nodeCount: 1, - requiredNodeName: "d601", - requiredNodePresent: true, - commandsOk: true, - summary: "D601 native k3s guard passed with explicit KUBECONFIG.", - }, - deployments: [ - deployment("code-queue", "scheduler", "true"), - deployment("code-queue-read", "read", "false"), - deployment("code-queue-write", "write", "false"), - ], - pods: [ - { name: "code-queue-aaa", instanceId: "D601", component: null, nodeName: "d601", phase: "Running", ready: true, imageID: `registry/unidesk-code-queue@${digest}`, digest }, - { name: "code-queue-read-aaa", instanceId: "D601-read", component: "read", nodeName: "d601", phase: "Running", ready: true, imageID: `registry/unidesk-code-queue@${digest}`, digest }, - { name: "code-queue-write-aaa", instanceId: "D601-write", component: "write", nodeName: "d601", phase: "Running", ready: true, imageID: `registry/unidesk-code-queue@${digest}`, digest }, - ], - services: [ - { name: "code-queue", observed: true, type: "ClusterIP", clusterIP: "10.43.0.1", ports: ["http:4222->http"], selector: { app: "code-queue", component: null, instanceId: "D601" }, error: null }, - { name: "code-queue-read", observed: true, type: "ClusterIP", clusterIP: "10.43.0.2", ports: ["http:4222->http"], selector: { app: "code-queue", component: "read", instanceId: null }, error: null }, - { name: "code-queue-write", observed: true, type: "ClusterIP", clusterIP: "10.43.0.3", ports: ["http:4222->http"], selector: { app: "code-queue", component: "write", instanceId: null }, error: null }, - ], - worktree: { - path: "/home/ubuntu/cq-deploy", - ok: true, - head: commit, - error: null, - }, - residual: { - composeBackend: { ok: true, present: false, containers: [], error: null }, - loopbackPort4222: { ok: true, present: false, listeners: [], error: null }, - }, - judgeProbe: { - ok: true, - attempted: true, - behaviorVersion: expectedJudgeProbeBehaviorVersion, - expectedBehaviorVersion: expectedJudgeProbeBehaviorVersion, - configured: true, - model: "minimax-m2.7", - hits: 8, - total: 8, - hitRate: 1, - serviceProxyPath: "/api/v1/namespaces/unidesk/services/code-queue/proxy/api/judge/probe", - error: null, - raw: { ok: true, behaviorVersion: expectedJudgeProbeBehaviorVersion, results: [{ id: "bounded" }] }, - }, - commandDiagnostics: {}, - }; - return { ...base, ...overrides }; -} - -async function checkHealthyNoDrift(): Promise { - const result = await runCodeQueueExecutionPlaneForTest([], healthyObservation()); - assertCondition(result.ok === true, "healthy fixture should pass", result); - assertCondition((result.summary as JsonRecord).deploymentDrift === false, "healthy fixture should not report deployment drift", result); - assertCondition((result.summary as JsonRecord).deprecatedComposeResidual === false, "healthy fixture should not report residual compose", result); -} - -async function checkDeploymentDrift(): Promise { - const obs = healthyObservation({ - deployments: [ - deployment("code-queue", "scheduler", "true", { env: { ...deployment("code-queue", "scheduler", "true").env, codeQueueDeployCommit: otherCommit } }), - deployment("code-queue-read", "read", "false"), - deployment("code-queue-write", "write", "false"), - ], - pods: [ - { name: "code-queue-aaa", instanceId: "D601", component: null, nodeName: "d601", phase: "Running", ready: true, imageID: `registry/unidesk-code-queue@${digest}`, digest }, - { name: "code-queue-read-aaa", instanceId: "D601-read", component: "read", nodeName: "d601", phase: "Running", ready: true, imageID: `registry/unidesk-code-queue@${otherDigest}`, digest: otherDigest }, - ], - judgeProbe: { - ...healthyObservation().judgeProbe, - behaviorVersion: "legacy", - }, - }); - const result = await runCodeQueueExecutionPlaneForTest([], obs); - const drift = result.drift as JsonRecord; - assertCondition(result.ok === false, "drift fixture should fail", result); - assertCondition(drift.status === "deployment-drift", "drift status should be deployment-drift", result); - assertCondition(JSON.stringify(drift).includes("deployment-drift"), "drift signal code should be visible", result); -} - -async function checkDeprecatedComposeResidual(): Promise { - const result = await runCodeQueueExecutionPlaneForTest([], healthyObservation({ - residual: { - composeBackend: { ok: true, present: true, containers: [{ name: "code-queue-backend", status: "Up 3 days", image: "unidesk-code-queue:old" }], error: null }, - loopbackPort4222: { ok: true, present: true, listeners: [{ localAddress: "127.0.0.1:4222", process: "users:((\"bun\",pid=1,fd=12))", line: "LISTEN 0 128 127.0.0.1:4222 0.0.0.0:* users:((\"bun\",pid=1,fd=12))" }], error: null }, - }, - })); - const residual = result.residual as JsonRecord; - assertCondition(result.ok === false, "residual fixture should fail", result); - assertCondition(residual.status === "deprecated-compose-residual", "residual status should be explicit", result); - assertCondition(JSON.stringify(result.blockers).includes("deprecated-compose-residual"), "residual blocker code should be visible", result); -} - -async function checkProgressiveDisclosure(): Promise { - const compact = await runCodeQueueExecutionPlaneForTest([], healthyObservation()); - assertCondition(!("details" in compact), "default output should omit details", compact); - assertCondition(!("rawObservation" in compact), "default output should omit raw observation", compact); - const full = await runCodeQueueExecutionPlaneForTest(["--full"], healthyObservation()); - assertCondition("details" in full, "--full should include details", full); - assertCondition(!("rawObservation" in full), "--full should still omit raw observation", full); - const raw = await runCodeQueueExecutionPlaneForTest(["--raw"], healthyObservation()); - assertCondition("details" in raw && "rawObservation" in raw, "--raw should include details and raw observation", raw); -} - -async function checkLiveCollectorUsesD601TranTransport(): Promise { - const source = readFileSync(new URL("./src/code-queue-execution-plane.ts", import.meta.url), "utf8"); - assertCondition(source.includes('["D601:k3s", "kubectl", ...args]'), "live collector should observe k3s through D601 tran route, not local kubectl"); - assertCondition(source.includes('`D601:${options.worktreePath}`'), "worktree observation should run on D601 workspace route"); - assertCondition(!source.includes('runCommand(["kubectl", ...args]'), "live collector must not call local kubectl directly"); - assertCondition(!source.includes('runCommand(["git", "-C", options.worktreePath'), "worktree observation must not read local filesystem"); -} - -async function main(): Promise { - const checks = [ - ["code-queue:execution-plane-healthy-no-drift", checkHealthyNoDrift], - ["code-queue:execution-plane-deployment-drift", checkDeploymentDrift], - ["code-queue:execution-plane-deprecated-compose-residual", checkDeprecatedComposeResidual], - ["code-queue:execution-plane-progressive-disclosure", checkProgressiveDisclosure], - ["code-queue:execution-plane-d601-tran-transport", checkLiveCollectorUsesD601TranTransport], - ] as const; - const results = []; - for (const [name, check] of checks) { - await check(); - results.push({ name, ok: true }); - } - process.stdout.write(`${JSON.stringify({ ok: true, results }, null, 2)}\n`); -} - -if (import.meta.main) { - await main(); -} diff --git a/scripts/src/check.ts b/scripts/src/check.ts index 159bd825..2bb34525 100644 --- a/scripts/src/check.ts +++ b/scripts/src/check.ts @@ -49,7 +49,6 @@ const syntaxFiles = [ "scripts/code-queue-submit-summary-contract-test.ts", "scripts/code-queue-cli-read-terminal-contract-test.ts", "scripts/code-queue-gh-auth-redaction-contract-test.ts", - "scripts/code-queue-execution-plane-contract-test.ts", "scripts/d601-recovery-guardrails-contract-test.ts", "scripts/hwlab-cd-wrapper-contract-test.ts", "scripts/code-queue-queues-shape-contract-test.ts", @@ -363,7 +362,6 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default fileItem("scripts/code-queue-submit-summary-contract-test.ts"), fileItem("scripts/code-queue-submit-routing-contract-test.ts"), fileItem("scripts/code-queue-gh-auth-redaction-contract-test.ts"), - fileItem("scripts/code-queue-execution-plane-contract-test.ts"), fileItem("scripts/code-queue-queues-shape-contract-test.ts"), fileItem("scripts/code-queue-supervisor-disclosure-contract-test.ts"), fileItem("scripts/code-queue-commander-view-contract-test.ts"), @@ -424,7 +422,6 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default items.push(commandItem("code-queue:submit-summary-contract", ["bun", "scripts/code-queue-submit-summary-contract-test.ts"], 30_000)); items.push(commandItem("code-queue:submit-routing-contract", ["bun", "scripts/code-queue-submit-routing-contract-test.ts"], 30_000)); items.push(commandItem("code-queue:gh-auth-redaction-contract", ["bun", "scripts/code-queue-gh-auth-redaction-contract-test.ts"], 30_000)); - items.push(commandItem("code-queue:execution-plane-contract", ["bun", "scripts/code-queue-execution-plane-contract-test.ts"], 30_000)); items.push(commandItem("code-queue:queues-shape-contract", ["bun", "scripts/code-queue-queues-shape-contract-test.ts"], 30_000)); items.push(commandItem("code-queue:supervisor-disclosure-contract", ["bun", "scripts/code-queue-supervisor-disclosure-contract-test.ts"], 30_000)); items.push(commandItem("code-queue:commander-view-contract", ["bun", "scripts/code-queue-commander-view-contract-test.ts"], 30_000)); @@ -470,7 +467,6 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default items.push(skippedItem("code-queue:submit-summary-contract", "Code Queue submit summary contract is opt-in with script checks", "--scripts-typecheck or --full")); items.push(skippedItem("code-queue:submit-routing-contract", "Code Queue submit routing contract is opt-in with script checks", "--scripts-typecheck or --full")); items.push(skippedItem("code-queue:gh-auth-redaction-contract", "Code Queue GitHub auth output redaction contract is opt-in with script checks", "--scripts-typecheck or --full")); - items.push(skippedItem("code-queue:execution-plane-contract", "Code Queue execution plane drift contract is opt-in with script checks", "--scripts-typecheck or --full")); items.push(skippedItem("code-queue:queues-shape-contract", "Code Queue queues shape contract is opt-in with script checks", "--scripts-typecheck or --full")); items.push(skippedItem("code-queue:supervisor-disclosure-contract", "Code Queue supervisor disclosure contract is opt-in with script checks", "--scripts-typecheck or --full")); items.push(skippedItem("code-queue:commander-view-contract", "Code Queue commander view contract is opt-in with script checks", "--scripts-typecheck or --full")); diff --git a/scripts/src/code-queue-execution-plane.ts b/scripts/src/code-queue-execution-plane.ts index 1e7cfac5..5d876470 100644 --- a/scripts/src/code-queue-execution-plane.ts +++ b/scripts/src/code-queue-execution-plane.ts @@ -11,7 +11,6 @@ interface ExecutionPlaneOptions { worktreePath: string; full: boolean; raw: boolean; - skipProbe: boolean; timeoutMs: number; } @@ -109,21 +108,6 @@ interface ResidualObservation { }; } -interface JudgeProbeObservation { - ok: boolean; - attempted: boolean; - behaviorVersion: string | null; - expectedBehaviorVersion: string; - configured: boolean | null; - model: string | null; - hits: number | null; - total: number | null; - hitRate: number | null; - serviceProxyPath: string | null; - error: string | null; - raw: unknown; -} - export interface CodeQueueExecutionPlaneObservation { checkedAt: string; namespace: string; @@ -135,7 +119,6 @@ export interface CodeQueueExecutionPlaneObservation { services: ServiceObservation[]; worktree: WorktreeObservation; residual: ResidualObservation; - judgeProbe: JudgeProbeObservation; commandDiagnostics: Record; } @@ -154,7 +137,6 @@ interface DriftSignal { const expectedNamespace = "unidesk"; const expectedWorktreePath = "/home/ubuntu/cq-deploy"; -export const expectedJudgeProbeBehaviorVersion = "code-queue-judge-probe:v1"; const expectedDeployments = [ { name: "code-queue", role: "scheduler" as const, schedulerEnabled: "true" }, @@ -188,7 +170,7 @@ function parsePositiveInteger(value: string | undefined, fallback: number, max: } function parseExecutionPlaneOptions(args: string[]): ExecutionPlaneOptions { - const knownFlags = new Set(["--full", "--raw", "--skip-probe"]); + const knownFlags = new Set(["--full", "--raw"]); const knownValues = new Set(["--namespace", "--kubeconfig", "--worktree", "--timeout-ms"]); for (let index = 0; index < args.length; index += 1) { const arg = args[index] ?? ""; @@ -207,7 +189,6 @@ function parseExecutionPlaneOptions(args: string[]): ExecutionPlaneOptions { worktreePath: optionValue(args, ["--worktree"]) ?? expectedWorktreePath, full: raw || hasFlag(args, "--full"), raw, - skipProbe: hasFlag(args, "--skip-probe"), timeoutMs: parsePositiveInteger(optionValue(args, ["--timeout-ms"]), 15_000, 60_000), }; } @@ -456,7 +437,6 @@ function collectResidual(): ResidualObservation { worktreePath: expectedWorktreePath, full: false, raw: false, - skipProbe: true, timeoutMs: 15_000, }; const docker = runTran(["D601", "argv", "docker", "ps", "-a", "--filter", "name=code-queue-backend", "--format", "{{.Names}}\t{{.Status}}\t{{.Image}}"], remoteOptions, 15_000); @@ -496,100 +476,6 @@ function collectResidual(): ResidualObservation { }; } -function parseJson(text: string): unknown { - try { - return JSON.parse(text) as unknown; - } catch { - return null; - } -} - -function asRecord(value: unknown): Record | null { - return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record : null; -} - -function stringValue(value: unknown): string | null { - return typeof value === "string" && value.trim().length > 0 ? value.trim() : null; -} - -function numberValue(value: unknown): number | null { - return typeof value === "number" && Number.isFinite(value) ? value : null; -} - -function collectJudgeProbe(options: ExecutionPlaneOptions): JudgeProbeObservation { - if (options.skipProbe) { - return { - ok: false, - attempted: false, - behaviorVersion: null, - expectedBehaviorVersion: expectedJudgeProbeBehaviorVersion, - configured: null, - model: null, - hits: null, - total: null, - hitRate: null, - serviceProxyPath: null, - error: "--skip-probe requested", - raw: null, - }; - } - const paths = [ - `/api/v1/namespaces/${options.namespace}/services/code-queue/proxy/api/judge/probe`, - `/api/v1/namespaces/${options.namespace}/services/code-queue:4222/proxy/api/judge/probe`, - `/api/v1/namespaces/${options.namespace}/services/code-queue:http/proxy/api/judge/probe`, - ]; - for (const path of paths) { - const probe = runKubectl(["--request-timeout=15s", "get", "--raw", path], options); - if (!probe.ok) continue; - const raw = parseJson(probe.stdout); - const record = asRecord(raw); - if (record === null) { - return { - ok: false, - attempted: true, - behaviorVersion: null, - expectedBehaviorVersion: expectedJudgeProbeBehaviorVersion, - configured: null, - model: null, - hits: null, - total: null, - hitRate: null, - serviceProxyPath: path, - error: "judge probe returned non-JSON response", - raw: probe.stdout.slice(0, 2000), - }; - } - return { - ok: record.ok === true, - attempted: true, - behaviorVersion: stringValue(record.behaviorVersion ?? asRecord(record.behavior)?.version ?? record.version), - expectedBehaviorVersion: expectedJudgeProbeBehaviorVersion, - configured: typeof record.configured === "boolean" ? record.configured : null, - model: stringValue(record.model), - hits: numberValue(record.hits), - total: numberValue(record.total), - hitRate: numberValue(record.hitRate), - serviceProxyPath: path, - error: record.ok === true ? null : stringValue(record.error) ?? "judge probe returned ok=false", - raw, - }; - } - return { - ok: false, - attempted: true, - behaviorVersion: null, - expectedBehaviorVersion: expectedJudgeProbeBehaviorVersion, - configured: null, - model: null, - hits: null, - total: null, - hitRate: null, - serviceProxyPath: null, - error: "judge probe could not be read through Kubernetes API service proxy", - raw: null, - }; -} - function digestFromText(value: string | null): string | null { if (value === null) return null; const match = value.match(/sha256:[0-9a-f]{64}/iu); @@ -613,20 +499,6 @@ class LiveExecutionPlaneCollector implements ExecutionPlaneCollector { services: [], worktree, residual, - judgeProbe: { - ok: false, - attempted: false, - behaviorVersion: null, - expectedBehaviorVersion: expectedJudgeProbeBehaviorVersion, - configured: null, - model: null, - hits: null, - total: null, - hitRate: null, - serviceProxyPath: null, - error: "D601 k3s guard did not pass; runtime probe skipped", - raw: null, - }, commandDiagnostics: { guard: diagnostics }, }; } @@ -641,7 +513,6 @@ class LiveExecutionPlaneCollector implements ExecutionPlaneCollector { services: collectServices(options), worktree, residual, - judgeProbe: collectJudgeProbe(options), commandDiagnostics: { guard: diagnostics }, }; } @@ -800,34 +671,6 @@ function driftSignals(observation: CodeQueueExecutionPlaneObservation): DriftSig }); } - if (!observation.judgeProbe.attempted) { - signals.push({ - code: "deployment-drift", - severity: "warning", - field: "judgeProbe.behaviorVersion", - message: "/api/judge/probe behavior version was not checked", - expected: expectedJudgeProbeBehaviorVersion, - observed: observation.judgeProbe.error, - }); - } else if (observation.judgeProbe.behaviorVersion !== expectedJudgeProbeBehaviorVersion) { - signals.push({ - code: "deployment-drift", - severity: "blocker", - field: "judgeProbe.behaviorVersion", - message: "/api/judge/probe behavior version does not match the repo contract", - expected: expectedJudgeProbeBehaviorVersion, - observed: observation.judgeProbe.behaviorVersion, - }); - } else if (!observation.judgeProbe.ok) { - signals.push({ - code: "deployment-drift", - severity: "blocker", - field: "judgeProbe.ok", - message: "/api/judge/probe returned a non-ready result", - expected: true, - observed: observation.judgeProbe.error, - }); - } return signals; } @@ -881,23 +724,6 @@ function compactDeployment(deployment: DeploymentObservation): Record { - return { - ok: probe.ok, - attempted: probe.attempted, - behaviorVersion: probe.behaviorVersion, - expectedBehaviorVersion: probe.expectedBehaviorVersion, - configured: probe.configured, - model: probe.model, - hits: probe.hits, - total: probe.total, - hitRate: probe.hitRate, - serviceProxyPath: probe.serviceProxyPath, - error: probe.error, - ...(full ? { raw: probe.raw } : {}), - }; -} - function evaluateObservation(observation: CodeQueueExecutionPlaneObservation, options: ExecutionPlaneOptions): Record { const formalSignals = observation.deployments.flatMap(deploymentFormalSignals); const deploymentDriftSignals = driftSignals(observation); @@ -939,7 +765,6 @@ function evaluateObservation(observation: CodeQueueExecutionPlaneObservation, op artifactDigest: uniqueDigests.length === 1 ? uniqueDigests[0] : null, deploymentCommit: uniqueCommits.length === 1 ? uniqueCommits[0] : null, mountedWorktreeHead: observation.worktree.head, - judgeProbeBehaviorVersion: observation.judgeProbe.behaviorVersion, }, guard: { status: observation.guard.status, @@ -959,7 +784,7 @@ function evaluateObservation(observation: CodeQueueExecutionPlaneObservation, op signalCount: deploymentDriftSignals.length, signals: deploymentDriftSignals.slice(0, options.full ? undefined : 5), omittedSignals: options.full ? 0 : Math.max(0, deploymentDriftSignals.length - 5), - comparedFields: ["deployment env/annotation commit", "artifact digest", "mounted worktree HEAD", "/api/judge/probe behaviorVersion"], + comparedFields: ["deployment env/annotation commit", "artifact digest", "mounted worktree HEAD"], }, residual: { status: deprecatedResidualSignals.some((signal) => signal.code === "deprecated-compose-residual") ? "deprecated-compose-residual" : "none", @@ -968,7 +793,6 @@ function evaluateObservation(observation: CodeQueueExecutionPlaneObservation, op containers: observation.residual.composeBackend.containers, listeners: observation.residual.loopbackPort4222.listeners, }, - judgeProbe: compactJudgeProbe(observation.judgeProbe, options.full), blockers, warnings, commands: { diff --git a/scripts/src/help.ts b/scripts/src/help.ts index a1c7d5f9..3efd4bd2 100644 --- a/scripts/src/help.ts +++ b/scripts/src/help.ts @@ -66,7 +66,7 @@ export function rootHelp(): unknown { { command: "codex prompt-lint [prompt|--prompt-file path|--prompt-stdin]", description: "Dry-run lint a runner prompt for DEV test class read-only/live-read/live-mutating authorization without echoing prompt text or touching live services." }, { command: "codex submit [prompt] [--prompt-file path|--prompt-stdin] [--queue queueId] [--provider-id id] [--cwd path] [--model model] [--execution-mode mode] [--max-attempts N] [--reference-task-id id] [--dry-run]", description: "Submit a Code Queue task through backend-core -> code-queue proxy; --dry-run shows the structured request, routing recommendation, and prompt live-authorization lint while real success only confirms the write and task id." }, { command: "codex skills-sync --dry-run [--full]", description: "Inspect the controlled runner skills hostPath lifecycle contract without copying files, restarting services, reading secrets, or mutating live runner paths." }, - { command: "codex execution-plane [--full|--raw]", description: "Read-only D601 native k3s Code Queue execution-plane drift inspection; compares formal deployments, deprecated Compose residuals, commit markers, pod digest, mounted worktree HEAD, and judge probe behavior version." }, + { command: "codex execution-plane [--full|--raw]", description: "Read-only D601 native k3s Code Queue execution-plane inspection; compares formal deployments, deprecated Compose residuals, commit markers, pod digest, and mounted worktree HEAD." }, { command: "codex pr-preflight [--remote] [--push-dry-run --push-dry-run-ref refs/heads/probe/] [--pr-create-dry-run --pr-create-dry-run-head ] [--issue N] [--full|--raw]", description: "Read-only PR admission check with compact commander output by default; use --full or --raw to expand the full runtime preflight, tool, and observation payload." }, { command: "codex task [--detail] [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]", description: "Fetch the bounded review view by default; --detail is still capped, while --full/trace/output explicitly expand evidence." }, { command: "codex tasks [--view commander|supervisor|full] [--queue id] [--status status[,status]] [--unread|--unread-only] [--limit N] [--before-id id]", description: "Show Code Queue task state with progressive disclosure; --view commander is the recommended bounded host-commander loop, supervisor keeps compact sections, and full returns detailed rows." }, @@ -432,7 +432,7 @@ function codexHelp(): unknown { mutation: false, kubeconfig: "/etc/rancher/k3s/k3s.yaml", namespace: "unidesk", - defaultPolicy: "compact drift/residual summary; deployments, pods, services and probe detail require --full, raw sanitized observations require --raw", + defaultPolicy: "compact drift/residual summary; deployments, pods and services require --full, raw sanitized observations require --raw", blockers: ["deployment-drift", "deprecated-compose-residual", "d601-k3s-guard-blocked"], }, examples: {