import { spawnSync } from "node:child_process"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; type JsonRecord = Record; function assertCondition(condition: unknown, message: string, detail: unknown = {}): 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, "submit dry-run should succeed", response); const data = nestedRecord(response.data, []); assertCondition(data.dryRun === true, "submit dry-run should expose dryRun=true", data); const request = nestedRecord(response.data, ["request"]); const prompt = nestedRecord(request, ["prompt"]); assertCondition(prompt.text === expectedText, "submit dry-run prompt text mismatch", prompt); assertCondition(prompt.chars === expectedText.length, "submit dry-run prompt char count mismatch", prompt); assertCondition(prompt.truncated === false, "submit dry-run prompt must expose the full prompt", prompt); } export function runCodeQueueCliSubmitPromptContract(): JsonRecord { const multilinePrompt = [ "Goal: verify stdin prompt path", "JSON: {\"quote\":\"'single' and \\\"double\\\"\"}", "Markdown: `code` | table | value", "Backslash: C:\\tmp\\prompt", "", ].join("\n"); const stdin = runCli(["codex", "submit", "--prompt-stdin", "--queue", "prompt-contract", "--dry-run"], multilinePrompt); assertDryRunPrompt(stdin.json ?? {}, multilinePrompt); assertCondition(String(stdin.json?.command || "") === "codex submit --prompt-stdin --queue prompt-contract --dry-run", "stdin command should list flags without echoing prompt", stdin.json ?? {}); const tmp = mkdtempSync(join(tmpdir(), "unidesk-code-queue-submit-")); const promptFile = join(tmp, "prompt.md"); const filePrompt = `${multilinePrompt}file prompt tail\n`; writeFileSync(promptFile, filePrompt, "utf8"); try { const fromFile = runCli(["codex", "submit", "--prompt-file", promptFile, "--queue", "prompt-contract", "--dry-run"]); assertDryRunPrompt(fromFile.json ?? {}, filePrompt); assertCondition(String(fromFile.json?.command || "").includes(`--prompt-file ${promptFile}`), "prompt-file command should retain file path for review", fromFile.json ?? {}); assertCondition(!String(fromFile.json?.command || "").includes("file prompt tail"), "prompt-file command must not echo file prompt text", fromFile.json ?? {}); } finally { rmSync(tmp, { recursive: true, force: true }); } const positional = runCli(["codex", "submit", "short smoke prompt", "--dry-run"]); assertDryRunPrompt(positional.json ?? {}, "short smoke prompt"); assertCondition(String(positional.json?.command || "").includes(""), "outer command should redact positional submit prompt", positional.json ?? {}); assertCondition(!String(positional.json?.command || "").includes("short smoke prompt"), "outer command must not echo positional submit prompt", positional.json ?? {}); const duplicateSource = runCli(["codex", "submit", "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 help = runCli(["codex", "submit", "--help"]); assertCondition(help.status === 0 && help.json?.ok === true, "codex submit help should succeed", help.json ?? { stdout: help.stdout }); const data = nestedRecord(help.json?.data, []); const usage = stringArray(data.usage); const promptInput = nestedRecord(data, ["promptInput"]); const recommended = stringArray(promptInput.recommended); const examples = nestedRecord(data, ["examples"]); assertCondition(usage.some((line) => line.includes("--prompt-stdin")), "help usage should include --prompt-stdin", { usage }); assertCondition(usage.some((line) => line.includes("--prompt-file")), "help usage should include --prompt-file", { usage }); assertCondition(usage.some((line) => line.includes("cat <<'PROMPT'")), "help usage should include a quoted heredoc example", { usage }); assertCondition(recommended.includes("--prompt-stdin") && recommended.includes("--prompt-file"), "help should recommend stdin and file prompt sources", promptInput); assertCondition(String(promptInput.sourceRule || "").includes("Exactly one prompt source"), "help should document exact prompt source rule", promptInput); assertCondition(stringArray(examples.stdin).some((line) => line.includes("--prompt-stdin")), "help examples should include stdin command", examples); assertCondition(String(examples.file || "").includes("--prompt-file"), "help examples should include file command", examples); return { ok: true, checks: [ "submit --prompt-stdin preserves multiline quotes and newlines", "submit --prompt-file preserves reviewed file contents", "submit positional prompt is redacted from the outer command envelope", "duplicate submit prompt source fails explicitly", "codex submit help documents stdin/file recommendations and copyable examples", ], }; } if (import.meta.main) { process.stdout.write(`${JSON.stringify(runCodeQueueCliSubmitPromptContract(), null, 2)}\n`); }