import { spawnSync } from "node:child_process"; import { writeFileSync, unlinkSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; type JsonRecord = Record; function assertCondition(condition: unknown, message: string, detail: JsonRecord = {}): void { if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`); } function runCli(args: string[], stdin?: string): { status: number | null; stdout: string; stderr: string; json: JsonRecord | null } { const result = spawnSync("bun", ["scripts/cli.ts", ...args], { cwd: process.cwd(), input: stdin, 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 stringArray(value: unknown): string[] { return Array.isArray(value) ? value.map((item) => String(item)) : []; } function assertDryRunPrompt(response: JsonRecord, expectedText: string): void { assertCondition(response.ok === true, "CLI dry-run should succeed", response); const data = nestedRecord(response.data, []); assertCondition(data.dryRun === true, "dry-run response should expose dryRun=true", data); const prompt = nestedRecord(response.data, ["request", "body", "prompt"]); assertCondition(prompt.text === expectedText, "dry-run prompt text mismatch", prompt); assertCondition(prompt.chars === expectedText.length, "dry-run prompt char count mismatch", prompt); assertCondition(prompt.truncated === false, "dry-run prompt must not truncate", prompt); } export function runCodeQueueCliSteerContract(): JsonRecord { const positional = runCli(["codex", "steer", "codex_test_task", "correct the running task", "--dry-run"]); assertDryRunPrompt(positional.json ?? {}, "correct the running task"); const stdin = runCli(["codex", "steer", "codex_test_task", "--prompt-stdin", "--dry-run"], "stdin steer prompt\n"); assertDryRunPrompt(stdin.json ?? {}, "stdin steer prompt\n"); const promptFile = join(tmpdir(), `unidesk-code-queue-steer-${process.pid}.txt`); writeFileSync(promptFile, "file steer prompt", "utf8"); try { const fromFile = runCli(["codex", "steer", "codex_test_task", "--prompt-file", promptFile, "--dry-run"]); assertDryRunPrompt(fromFile.json ?? {}, "file steer prompt"); } finally { unlinkSync(promptFile); } const duplicateSource = runCli(["codex", "steer", "codex_test_task", "positional", "--prompt-stdin", "--dry-run"], "stdin\n"); assertCondition(duplicateSource.status !== 0, "duplicate prompt source should fail", duplicateSource.json ?? { stdout: duplicateSource.stdout }); const duplicateMessage = String(nestedRecord(duplicateSource.json, ["error"]).message || ""); assertCondition(duplicateMessage.includes("exactly one prompt source"), "duplicate prompt source error should be explicit", { duplicateMessage }); const unknownOption = runCli(["codex", "steer", "codex_test_task", "--queue", "default", "prompt", "--dry-run"]); assertCondition(unknownOption.status !== 0, "unknown steer option should fail", unknownOption.json ?? { stdout: unknownOption.stdout }); const unknownMessage = String(nestedRecord(unknownOption.json, ["error"]).message || ""); assertCondition(unknownMessage.includes("unsupported codex steer option: --queue"), "unknown option error should name option", { unknownMessage }); const help = runCli(["codex", "help"]); assertCondition(help.status === 0 && help.json?.ok === true, "codex help should succeed", help.json ?? { stdout: help.stdout }); const usage = stringArray(nestedRecord(help.json?.data, []).usage); assertCondition(usage.some((line) => line.includes("codex steer ")), "codex help should list steer", { usage }); return { ok: true, checks: [ "steer positional dry-run", "steer stdin dry-run", "steer prompt-file dry-run", "duplicate prompt source failure", "unsupported option failure", "codex help lists steer", ], }; } if (import.meta.main) { const result = runCodeQueueCliSteerContract(); process.stdout.write(`${JSON.stringify(result, null, 2)}\n`); }