145 lines
7.7 KiB
TypeScript
145 lines
7.7 KiB
TypeScript
import { spawnSync } from "node:child_process";
|
|
import {
|
|
normalizeCodeExecutionMode,
|
|
normalizeRequestedCodeExecutionMode,
|
|
requestedCodeExecutionModeIsRecognized,
|
|
} from "../src/components/microservices/code-queue/src/code-agent/common";
|
|
import { compactSubmitSuccessResponseForTest } from "./src/code-queue";
|
|
|
|
type JsonRecord = Record<string, unknown>;
|
|
|
|
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
|
|
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
|
|
}
|
|
|
|
function runCli(args: string[]): { status: number | null; stdout: string; stderr: string; json: JsonRecord | null } {
|
|
const result = spawnSync("bun", ["scripts/cli.ts", ...args], {
|
|
cwd: process.cwd(),
|
|
encoding: "utf8",
|
|
});
|
|
const stdout = String(result.stdout || "");
|
|
let json: JsonRecord | null = null;
|
|
try {
|
|
json = JSON.parse(stdout) as JsonRecord;
|
|
} catch {
|
|
json = null;
|
|
}
|
|
return {
|
|
status: result.status,
|
|
stdout,
|
|
stderr: String(result.stderr || ""),
|
|
json,
|
|
};
|
|
}
|
|
|
|
function nestedRecord(value: unknown, path: string[]): JsonRecord {
|
|
let current: unknown = value;
|
|
for (const key of path) {
|
|
assertCondition(current !== null && typeof current === "object" && !Array.isArray(current), "expected object while traversing JSON", { path, key, current });
|
|
current = (current as JsonRecord)[key];
|
|
}
|
|
assertCondition(current !== null && typeof current === "object" && !Array.isArray(current), "expected nested object", { path, current });
|
|
return current as JsonRecord;
|
|
}
|
|
|
|
function asArray(value: unknown): unknown[] {
|
|
assertCondition(Array.isArray(value), "expected JSON array", { value });
|
|
return value as unknown[];
|
|
}
|
|
|
|
function assertSecretFree(output: string): void {
|
|
const forbidden = ["GH_TOKEN=", "GITHUB_TOKEN=", "OPENAI_API_KEY=", "CRS_OAI_KEY=", "DEEPSEEK_API_KEY=", "MINIMAX_API_KEY="];
|
|
for (const needle of forbidden) {
|
|
assertCondition(!output.includes(needle), "submit execution-mode contract must not print credential assignments", { needle });
|
|
}
|
|
}
|
|
|
|
function assertLegacyFrozenWrite(result: { status: number | null; stdout: string; stderr: string; json: JsonRecord | null }, command: string): void {
|
|
assertCondition(result.status !== 0 && result.json?.ok === false, `${command} should be frozen`, result.json ?? { stdout: result.stdout, stderr: result.stderr });
|
|
const data = nestedRecord(result.json?.data, []);
|
|
assertCondition(data.ok === false, `${command} frozen payload should be ok=false`, data);
|
|
assertCondition(data.frozen === true, `${command} frozen payload should expose frozen=true`, data);
|
|
assertCondition(data.mutation === false, `${command} frozen payload should be non-mutating`, data);
|
|
assertCondition(data.degradedReason === "legacy-code-queue-frozen", `${command} should use the legacy frozen reason`, data);
|
|
const replacement = nestedRecord(data, ["replacement"]);
|
|
assertCondition(String(replacement.queueSubmit || "").includes("agentrun v01 queue submit"), `${command} should point to AgentRun queue submit`, replacement);
|
|
const legacy = nestedRecord(data, ["legacy"]);
|
|
assertCondition(legacy.noDoubleWrite === true, `${command} should document no double-write`, legacy);
|
|
}
|
|
|
|
export function runCodeQueueSubmitExecutionModeContract(): JsonRecord {
|
|
assertCondition(normalizeRequestedCodeExecutionMode("full-access") === "full-access", "shared parser should preserve short requested mode ids");
|
|
assertCondition(normalizeCodeExecutionMode("full-access") === "default", "shared execution-mode normalizer should keep full-access on effective default");
|
|
assertCondition(requestedCodeExecutionModeIsRecognized("full-access") === false, "shared recognition helper should reject full-access as a runtime mode");
|
|
assertCondition(requestedCodeExecutionModeIsRecognized("default") === true, "shared recognition helper should accept default mode");
|
|
|
|
const defaultMode = runCli(["codex", "submit", "execution mode default smoke", "--dry-run"]);
|
|
assertLegacyFrozenWrite(defaultMode, "codex submit");
|
|
assertSecretFree(defaultMode.stdout);
|
|
|
|
const fullAccess = runCli(["codex", "submit", "execution mode full access smoke", "--execution-mode", "full-access", "--dry-run"]);
|
|
assertLegacyFrozenWrite(fullAccess, "codex submit");
|
|
assertSecretFree(fullAccess.stdout);
|
|
|
|
const promptText = "submitted full-access prompt body must stay omitted";
|
|
const submitted = compactSubmitSuccessResponseForTest({
|
|
tasks: [{
|
|
id: "codex_exec_mode_contract",
|
|
queueId: "commander-efficiency",
|
|
status: "queued",
|
|
providerId: "D601",
|
|
model: "gpt-5.5",
|
|
cwd: "/workspace",
|
|
prompt: promptText,
|
|
executionMode: "default",
|
|
requestedExecutionMode: "full-access",
|
|
maxAttempts: 99,
|
|
createdAt: "2026-05-23T00:00:00.000Z",
|
|
updatedAt: "2026-05-23T00:00:00.000Z",
|
|
}],
|
|
queue: {
|
|
total: 1,
|
|
queueCount: 1,
|
|
counts: { queued: 1 },
|
|
queuedTaskIds: ["codex_exec_mode_contract"],
|
|
runnerPermissions: {
|
|
observed: true,
|
|
scope: "code-queue-service-config",
|
|
sandbox: "danger-full-access",
|
|
approvalPolicy: "never",
|
|
perTaskOverrideSupported: false,
|
|
secretsPrinted: false,
|
|
},
|
|
},
|
|
}, { ok: true, status: 200 }, { mode: "local-atomic-directory-submit-serialization", acquiredAfterMs: 1, heldMs: 2, throttleMs: 2000 });
|
|
const submittedExecutionMode = nestedRecord(submitted, ["executionMode"]);
|
|
const submittedPermissions = nestedRecord(submitted, ["runnerPermissions"]);
|
|
const firstTask = nestedRecord(asArray(nestedRecord(submitted, ["submitted"]).tasks)[0], []);
|
|
const taskExecutionMode = nestedRecord(firstTask, ["executionModeRequest"]);
|
|
const queuePermissions = nestedRecord(submitted, ["queue", "runnerPermissions"]);
|
|
const submittedJson = JSON.stringify(submitted);
|
|
assertCondition(submittedExecutionMode.requested === "full-access" && submittedExecutionMode.effective === "default", "real submit summary should show requested/effective mode", submittedExecutionMode);
|
|
assertCondition(submittedPermissions.observed === true && submittedPermissions.sandbox === "danger-full-access" && submittedPermissions.approvalPolicy === "never", "real submit summary should expose observed service-level runner permissions", submittedPermissions);
|
|
assertCondition(submittedPermissions.perTaskOverrideSupported === false, "real submit summary should not imply per-task sandbox override", submittedPermissions);
|
|
assertCondition(firstTask.requestedExecutionMode === "full-access" && firstTask.executionMode === "default", "submitted task should carry requested and effective mode", firstTask);
|
|
assertCondition(taskExecutionMode.warning === submittedExecutionMode.warning, "task-level execution mode summary should match top-level warning", { taskExecutionMode, submittedExecutionMode });
|
|
assertCondition(queuePermissions.sandbox === "danger-full-access", "queue summary should keep runner permissions visible", queuePermissions);
|
|
assertCondition(!submittedJson.includes(promptText), "real submit summary must keep prompt text omitted", submitted);
|
|
assertCondition(!submittedJson.includes("promptPreview"), "real submit summary must not reintroduce promptPreview", submitted);
|
|
|
|
return {
|
|
ok: true,
|
|
checks: [
|
|
"legacy codex submit dry-run is frozen and points to AgentRun",
|
|
"legacy --execution-mode full-access submit dry-run is frozen without printing credentials",
|
|
"real submit summary fixture exposes requested/effective mode plus observed runnerPermissions without prompt echo",
|
|
"shared execution-mode helpers preserve requested full-access while normalizing effective runtime to default",
|
|
"execution-mode frozen output does not print credential assignments",
|
|
],
|
|
};
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
process.stdout.write(`${JSON.stringify(runCodeQueueSubmitExecutionModeContract(), null, 2)}\n`);
|
|
}
|