fix: expose code queue runner skills contract
This commit is contained in:
@@ -405,6 +405,12 @@ const skillsPreflightTransport = {
|
||||
const defaultPreflightSummary = asRecord(codexPrPreflightQueryForTest(["--remote"], skillsPreflightTransport), "default preflight summary");
|
||||
assertCondition(defaultPreflightSummary.failureKind === "runner-skills-blocker", "missing target should classify as runner skills blocker even when source exists", defaultPreflightSummary);
|
||||
assertCondition(asRecord(defaultPreflightSummary.skillsContract, "defaultPreflightSummary.skillsContract").hostRolloutRequired === true, "default preflight should expose host rollout blocker separately", defaultPreflightSummary);
|
||||
assertCondition(asRecord(defaultPreflightSummary.skillsContract, "defaultPreflightSummary.skillsContract").source === missing.source, "default preflight should expose skills source in the bounded contract", defaultPreflightSummary.skillsContract);
|
||||
assertCondition(asRecord(defaultPreflightSummary.skillsContract, "defaultPreflightSummary.skillsContract").target === missing.target, "default preflight should expose skills target in the bounded contract", defaultPreflightSummary.skillsContract);
|
||||
assertCondition(Array.isArray(asRecord(defaultPreflightSummary.skillsContract, "defaultPreflightSummary.skillsContract").requiredSkills), "default preflight should expose requiredSkills in the bounded contract", defaultPreflightSummary.skillsContract);
|
||||
assertCondition(Array.isArray(asRecord(defaultPreflightSummary.skillsContract, "defaultPreflightSummary.skillsContract").missingSkills), "default preflight should expose missingSkills in the bounded contract", defaultPreflightSummary.skillsContract);
|
||||
assertCondition(asRecord(defaultPreflightSummary.skillsContract, "defaultPreflightSummary.skillsContract").repairHint !== null, "default preflight should expose repairHint in the bounded contract", defaultPreflightSummary.skillsContract);
|
||||
assertCondition(asRecord(defaultPreflightSummary.skillsContract, "defaultPreflightSummary.skillsContract").valuesPrinted === false, "default preflight skills contract must declare valuesPrinted=false", defaultPreflightSummary.skillsContract);
|
||||
assertCondition(defaultPreflightSummary.preflight === undefined, "default PR preflight should omit detailed preflight internals", defaultPreflightSummary);
|
||||
assertCondition(asRecord(defaultPreflightSummary.disclosure, "defaultPreflightSummary.disclosure").fullDetailOmitted === true, "default PR preflight should disclose full detail omission", defaultPreflightSummary.disclosure);
|
||||
assertCondition(String(asRecord(defaultPreflightSummary.disclosure, "defaultPreflightSummary.disclosure").expandWith ?? "").includes("--full"), "default PR preflight should point to --full expansion", defaultPreflightSummary.disclosure);
|
||||
@@ -424,6 +430,190 @@ assertCondition(asRecord(preflightSkillsSync.plannedActions, "preflight.skillsSy
|
||||
assertCondition(preflightSkillsSync.valuesPrinted === false, "full preflight skills sync must declare valuesPrinted=false", preflightSkillsSync);
|
||||
assertCondition(!JSON.stringify(preflightSkillsSync).includes(forbiddenPathLiteral), "full preflight must not propagate misspelled path literal");
|
||||
|
||||
const legacyRuntimeSkills = {
|
||||
ok: false,
|
||||
runnerUsable: false,
|
||||
contractOk: false,
|
||||
path: "/root/.agents/skills",
|
||||
resolvedPath: "/root/.agents/skills",
|
||||
resolvedPathSource: null,
|
||||
resolution: null,
|
||||
source: "/home/ubuntu/.agents/skills",
|
||||
target: "/root/.agents/skills",
|
||||
exists: false,
|
||||
available: false,
|
||||
degraded: true,
|
||||
blocker: "skills-target-missing",
|
||||
degradedReason: "skills-target-missing",
|
||||
readonly: false,
|
||||
skillCount: 0,
|
||||
requiredSkills: ["docs-spec", "cli-spec", "frontend-design", "playwright-cli"],
|
||||
missingSkills: ["docs-spec", "cli-spec", "frontend-design", "playwright-cli"],
|
||||
valuesPrinted: false,
|
||||
pathSpelling: {
|
||||
expectedTarget: "/root/.agents/skills",
|
||||
forbiddenPathChecked: true,
|
||||
forbiddenPathExists: false,
|
||||
forbiddenPathConfigured: false,
|
||||
forbiddenPathRoles: [],
|
||||
forbiddenPathMustNotBeUsed: true,
|
||||
},
|
||||
repairHint: "Mount /home/ubuntu/.agents/skills read-only at /root/.agents/skills, set UNIDESK_SKILLS_PATH=/root/.agents/skills, and remove any forbidden skills path spelling.",
|
||||
};
|
||||
const legacyRuntimeSkillsSync = {
|
||||
ok: false,
|
||||
degraded: true,
|
||||
blocker: "skills-target-missing",
|
||||
checkedAt: "2026-05-23T00:00:00.000Z",
|
||||
mode: "dry-run",
|
||||
dryRun: true,
|
||||
mutation: false,
|
||||
syncMode: "hostPath-read-only-projection",
|
||||
source: {
|
||||
path: "/home/ubuntu/.agents/skills",
|
||||
approved: true,
|
||||
exists: true,
|
||||
directory: true,
|
||||
readable: true,
|
||||
writable: true,
|
||||
readonly: false,
|
||||
mountPoint: "/home/ubuntu",
|
||||
symlink: false,
|
||||
realPath: null,
|
||||
skillCount: 49,
|
||||
version: null,
|
||||
requiredSkills: ["docs-spec", "cli-spec", "frontend-design", "playwright-cli"],
|
||||
missingSkills: [],
|
||||
error: null,
|
||||
},
|
||||
target: {
|
||||
path: "/root/.agents/skills",
|
||||
approved: true,
|
||||
exists: false,
|
||||
directory: false,
|
||||
readable: false,
|
||||
writable: false,
|
||||
readonly: false,
|
||||
mountPoint: "/",
|
||||
symlink: false,
|
||||
realPath: null,
|
||||
skillCount: 0,
|
||||
version: null,
|
||||
requiredSkills: ["docs-spec", "cli-spec", "frontend-design", "playwright-cli"],
|
||||
missingSkills: ["docs-spec", "cli-spec", "frontend-design", "playwright-cli"],
|
||||
error: null,
|
||||
},
|
||||
expected: {
|
||||
source: "/home/ubuntu/.agents/skills",
|
||||
target: "/root/.agents/skills",
|
||||
env: "UNIDESK_SKILLS_PATH",
|
||||
envValue: "/root/.agents/skills",
|
||||
mount: "/home/ubuntu/.agents/skills mounted read-only to /root/.agents/skills",
|
||||
requiredSkills: ["docs-spec", "cli-spec", "frontend-design", "playwright-cli"],
|
||||
},
|
||||
counts: {
|
||||
sourceSkills: 49,
|
||||
targetSkills: 0,
|
||||
requiredSkills: 4,
|
||||
missingSourceSkills: 0,
|
||||
missingTargetSkills: 4,
|
||||
},
|
||||
version: null,
|
||||
missing: {
|
||||
sourceSkills: [],
|
||||
targetSkills: ["docs-spec", "cli-spec", "frontend-design", "playwright-cli"],
|
||||
},
|
||||
permissionFailures: [],
|
||||
pathSpelling: {
|
||||
expectedTarget: "/root/.agents/skills",
|
||||
forbiddenPathChecked: true,
|
||||
forbiddenPathExists: false,
|
||||
forbiddenPathConfigured: false,
|
||||
forbiddenPathRoles: [],
|
||||
forbiddenPathMustNotBeUsed: true,
|
||||
},
|
||||
plannedActions: {
|
||||
copy: false,
|
||||
writesSource: false,
|
||||
writesTarget: false,
|
||||
restartRequired: false,
|
||||
readsSecrets: false,
|
||||
copyFromArbitraryPath: false,
|
||||
},
|
||||
commands: {
|
||||
dryRun: "bun scripts/cli.ts codex skills-sync --dry-run",
|
||||
full: "bun scripts/cli.ts codex skills-sync --dry-run --full",
|
||||
health: "bun scripts/cli.ts microservice health code-queue",
|
||||
runtimePreflight: "bun scripts/cli.ts codex pr-preflight --remote",
|
||||
contractTest: "bun scripts/code-queue-runner-skills-contract-test.ts",
|
||||
},
|
||||
valuesPrinted: false,
|
||||
};
|
||||
const legacyRuntimePreflightTransport = {
|
||||
config: null,
|
||||
coreFetch: () => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
body: {
|
||||
runtimePreflight: {
|
||||
ok: false,
|
||||
checkedAt: "2026-05-23T00:00:00.000Z",
|
||||
cwd: "/workspace/unidesk",
|
||||
pid: 601,
|
||||
skills: legacyRuntimeSkills,
|
||||
skillsSync: legacyRuntimeSkillsSync,
|
||||
ports: {},
|
||||
pullRequestDelivery: {
|
||||
ok: true,
|
||||
checkedAt: "2026-05-23T00:00:00.000Z",
|
||||
tools: {},
|
||||
unideskGhCli: { ok: true, path: "/workspace/unidesk/scripts/cli.ts", present: true },
|
||||
authBroker: { ok: true, configured: true, source: "auth-broker" },
|
||||
credentials: {
|
||||
ghTokenPresent: true,
|
||||
githubTokenPresent: false,
|
||||
ghHostsConfigPresent: false,
|
||||
gitCredentialsPresent: false,
|
||||
},
|
||||
git: {
|
||||
insideWorktree: true,
|
||||
branch: "code-queue/issue-68-runner-skills-lifecycle",
|
||||
head: "abc1234",
|
||||
originMaster: "def5678",
|
||||
remoteOrigin: "git@github.com:pikasTech/unidesk.git",
|
||||
home: "/root",
|
||||
homeWritable: true,
|
||||
knownHostsPresent: true,
|
||||
privateKeyPresent: true,
|
||||
},
|
||||
githubContext: {
|
||||
host: "github.com",
|
||||
apiBaseUrl: "https://api.github.com",
|
||||
repo: "pikasTech/unidesk",
|
||||
issueProbeNumber: 68,
|
||||
},
|
||||
egress: { proxy: {} },
|
||||
remote: null,
|
||||
limitations: [],
|
||||
risks: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
const legacyDefaultPreflight = asRecord(codexPrPreflightQueryForTest(["--remote"], legacyRuntimePreflightTransport), "legacy default preflight");
|
||||
const legacySkillsContract = asRecord(legacyDefaultPreflight.skillsContract, "legacyDefaultPreflight.skillsContract");
|
||||
assertCondition(legacyDefaultPreflight.failureKind === "runner-skills-blocker", "legacy runtime shape should still classify missing target as runner skills blocker", legacyDefaultPreflight);
|
||||
assertCondition(legacySkillsContract.source === "/home/ubuntu/.agents/skills", "legacy runtime shape should expose source path from skillsSync", legacySkillsContract);
|
||||
assertCondition(legacySkillsContract.target === "/root/.agents/skills", "legacy runtime shape should expose target path from skillsSync", legacySkillsContract);
|
||||
assertCondition(legacySkillsContract.hostRolloutRequired === true, "legacy runtime shape with source available and target missing should require host rollout", legacySkillsContract);
|
||||
assertCondition(legacySkillsContract.degradedReason === "skills-target-missing", "legacy runtime shape should keep actionable degraded reason", legacySkillsContract);
|
||||
assertCondition(Array.isArray(legacySkillsContract.requiredSkills) && legacySkillsContract.requiredSkills.includes("docs-spec"), "legacy runtime shape should expose requiredSkills", legacySkillsContract);
|
||||
assertCondition(Array.isArray(legacySkillsContract.missingSkills) && legacySkillsContract.missingSkills.includes("docs-spec"), "legacy runtime shape should expose missingSkills", legacySkillsContract);
|
||||
assertCondition(legacySkillsContract.sourceSkillCount === 49 && legacySkillsContract.targetSkillCount === 0, "legacy runtime shape should expose source/target skill counts", legacySkillsContract);
|
||||
assertCondition(legacySkillsContract.repairHint !== null, "legacy runtime shape should expose repairHint", legacySkillsContract);
|
||||
assertCondition(legacySkillsContract.valuesPrinted === false, "legacy runtime shape contract must declare valuesPrinted=false", legacySkillsContract);
|
||||
|
||||
const typoPreflightTransport = {
|
||||
config: null,
|
||||
coreFetch: () => ({
|
||||
|
||||
Reference in New Issue
Block a user