fix: project runner skills into dev containers

This commit is contained in:
Codex
2026-05-24 03:08:21 +00:00
parent 99e91c1c83
commit 9145c063f9
10 changed files with 112 additions and 7 deletions
@@ -3,6 +3,7 @@ import { tmpdir } from "node:os";
import { join } from "node:path";
import { spawnSync } from "node:child_process";
import { collectSkillAvailability, collectSkillSyncPreflight } from "../src/components/microservices/code-queue/src/skill-availability";
import { buildDevContainerPlan, configureProviderRuntime, providerRuntimeForTest } from "../src/components/microservices/code-queue/src/provider-runtime";
import { codexPrPreflightQueryForTest } from "./src/code-queue";
import { summarizeMicroserviceObservation } from "./src/microservices";
@@ -71,6 +72,9 @@ assertCondition(!docsReference.includes(forbiddenPathLiteral), "reference docs m
assertCondition(countOccurrences(productionManifest, "name: UNIDESK_SKILLS_PATH") === 3, "production read/write/scheduler must set UNIDESK_SKILLS_PATH", {
count: countOccurrences(productionManifest, "name: UNIDESK_SKILLS_PATH"),
});
assertCondition(countOccurrences(productionManifest, "name: CODE_QUEUE_RUNNER_SKILLS_SOURCE_PATH") === 3, "production read/write/scheduler must expose the approved runner skills source path", {
count: countOccurrences(productionManifest, "name: CODE_QUEUE_RUNNER_SKILLS_SOURCE_PATH"),
});
assertCondition(countOccurrences(productionManifest, "mountPath: /root/.agents/skills") === 3, "production read/write/scheduler must mount skills target", {
count: countOccurrences(productionManifest, "mountPath: /root/.agents/skills"),
});
@@ -81,6 +85,9 @@ assertCondition(countOccurrences(productionManifest, "name: skills-dir") >= 6, "
count: countOccurrences(productionManifest, "name: skills-dir"),
});
assertCondition(devManifest.includes("path: /home/ubuntu/.agents/skills"), "dev manifest should keep the same hostPath source of truth");
assertCondition(countOccurrences(devManifest, "name: CODE_QUEUE_RUNNER_SKILLS_SOURCE_PATH") === 3, "dev read/write/scheduler must expose the approved runner skills source path", {
count: countOccurrences(devManifest, "name: CODE_QUEUE_RUNNER_SKILLS_SOURCE_PATH"),
});
const devCodeQueueDeploy = (deployJson.environments?.dev?.services ?? []).find((service) => service.id === "code-queue");
assertCondition(devCodeQueueDeploy !== undefined, "deploy.json dev environment must include code-queue");
@@ -107,6 +114,71 @@ assertCondition(pinnedRuntimePreflight.includes("skills.contractOk && ports.code
assertCondition(pinnedIndexSource.includes("skills.contractOk === true"), "deploy.json dev code-queue commit dev-ready must require target projection contract");
assertCondition(pinnedIndexSource.includes("return config.skillsPath"), "deploy.json dev code-queue commit must keep runner UNIDESK_SKILLS_PATH on the configured target");
configureProviderRuntime({
config: {
codexHome: "/var/lib/unidesk/code-queue/codex-home",
defaultWorkdir: "/workspace",
devContainerDefaultProviderId: "D601",
devContainerImage: "unidesk-code-queue:d601",
devContainerMasterHost: "74.48.78.17",
devContainerWorkdir: "/home/ubuntu",
executionProviderIds: ["D601"],
mainProviderId: "D601-main",
remoteCodexEnvKeys: [],
remoteDefaultWorkdir: "/home/ubuntu",
runnerSkillsSourcePath: "/home/ubuntu/.agents/skills",
skillsPath: "/root/.agents/skills",
sourceCodexConfig: "/root/.codex/config.toml",
windowsNativeCodexBridgeDir: "/home/ubuntu/.unidesk/code-queue/windows-native-codex",
windowsNativeCodexCommand: "codex app-server --listen stdio://",
windowsNativeCodexConnectHost: "host.docker.internal",
windowsNativeCodexDefaultWorkdir: "/mnt/f/Work/ConStart",
windowsNativeCodexIdleTimeoutMs: 600_000,
},
safePreview: (value: string, max = 1000) => value.slice(0, max),
});
const devContainerPlan = buildDevContainerPlan("D601", { workdir: "/home/ubuntu" });
const devContainerStartScript = providerRuntimeForTest.remoteContainerStartScript(devContainerPlan, false);
assertCondition(devContainerStartScript.includes("SKILLS_SOURCE='/home/ubuntu/.agents/skills'"), "provider dev container start must use the D601 host skills source", devContainerStartScript);
assertCondition(devContainerStartScript.includes("SKILLS_TARGET='/root/.agents/skills'"), "provider dev container start must use the runner target skills path", devContainerStartScript);
assertCondition(devContainerStartScript.includes('-v "$SKILLS_SOURCE":"$SKILLS_TARGET":ro'), "provider dev container must bind source skills read-only to target", devContainerStartScript);
assertCondition(devContainerStartScript.includes('-e UNIDESK_SKILLS_PATH="$SKILLS_TARGET"'), "provider dev container must export UNIDESK_SKILLS_PATH in docker run", devContainerStartScript);
assertCondition(devContainerStartScript.includes('test -r "$UNIDESK_SKILLS_PATH/docs-spec/SKILL.md"'), "provider dev container readiness must verify required docs-spec skill at target", devContainerStartScript);
assertCondition(devContainerStartScript.includes('test -r "$UNIDESK_SKILLS_PATH/cli-spec/SKILL.md"'), "provider dev container readiness must verify required cli-spec skill at target", devContainerStartScript);
assertCondition(devContainerStartScript.includes('test -r "$UNIDESK_SKILLS_PATH/frontend-design/SKILL.md"'), "provider dev container readiness must verify required frontend-design skill at target", devContainerStartScript);
assertCondition(devContainerStartScript.includes("playwright-cli/SKILL.md") && devContainerStartScript.includes("playwright/SKILL.md"), "provider dev container readiness must accept the playwright-cli alias", devContainerStartScript);
assertCondition(devContainerStartScript.includes("reuse_ready") && devContainerStartScript.includes('test "$UNIDESK_SKILLS_PATH" = "/root/.agents/skills"'), "provider dev container reuse must revalidate target skills before keeping an old container", devContainerStartScript);
const remoteCodexCommand = providerRuntimeForTest.remoteAppServerCommand({
id: "task",
queueId: "default",
prompt: "",
status: "running",
cwd: "/home/ubuntu",
providerId: "D601",
model: "gpt-5.5",
executionMode: "default",
currentAttempt: 1,
attempts: 1,
maxAttempts: 1,
codexThreadId: null,
reasoningEffort: null,
createdAt: "2026-05-24T00:00:00.000Z",
updatedAt: "2026-05-24T00:00:00.000Z",
startedAt: "2026-05-24T00:00:00.000Z",
completedAt: null,
lastActivityAt: "2026-05-24T00:00:00.000Z",
branch: null,
commitSha: null,
title: null,
error: null,
judge: null,
outputSeq: 0,
outputs: [],
events: [],
metadata: {},
} as never);
assertCondition(remoteCodexCommand.includes("export UNIDESK_SKILLS_PATH=") && remoteCodexCommand.includes("/root/.agents/skills"), "remote codex app-server must receive the target skills env", remoteCodexCommand);
const available = collectSkillAvailability({
source: "/home/ubuntu/.agents/skills",
target: "/home/ubuntu/.agents/skills",
@@ -446,6 +518,7 @@ process.stdout.write(`${JSON.stringify({
ok: true,
checks: [
"production Code Queue mounts /home/ubuntu/.agents/skills read-only at /root/.agents/skills",
"provider dev containers bind /home/ubuntu/.agents/skills read-only at /root/.agents/skills and pass UNIDESK_SKILLS_PATH to Codex/OpenCode",
"deploy.json dev Code Queue pins a commit whose manifest and runtime require the target skills projection",
"skill availability report exposes source, target, requiredSkills, missingSkills, version fingerprint/mtime, degraded/blocker and valuesPrinted=false",
"skills sync dry-run reports source, target, counts, version fingerprint/mtime, missing skills, permission failures, instructions and no-copy actions",