import { codexOutputQuery, codexTaskQuery } from "./src/code-queue"; type JsonRecord = Record; function assertCondition(condition: unknown, message: string, detail: unknown = {}): void { if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`); } function asRecord(value: unknown): JsonRecord { assertCondition(value !== null && typeof value === "object" && !Array.isArray(value), "expected object", { value }); return value as JsonRecord; } function asArray(value: unknown): unknown[] { assertCondition(Array.isArray(value), "expected array", { value }); return value as unknown[]; } function longText(marker: string, repeat = 220): string { return Array.from({ length: repeat }, (_, index) => `${marker}-${String(index + 1).padStart(3, "0")} ${"abcdefghijklmnopqrstuvwxyz0123456789".repeat(3)}`).join("\n"); } function detailFixture(path: string): JsonRecord { assertCondition(path.includes("/summary"), "detail fixture should only fetch summary", { path }); return { ok: true, status: 200, body: { ok: true, summary: { id: "codex_disclosure_fixture", queueId: "noise", status: "failed", providerId: "D601", model: "gpt-5.5", cwd: "/workspace", prompt: longText("prompt-tail-marker"), basePrompt: longText("base-tail-marker"), transcriptCount: 300, outputCount: 180, eventCount: 40, lastAssistantMessage: { at: "2026-05-23T00:00:00.000Z", seq: 300, source: "assistant", text: longText("assistant-tail-marker"), }, toolSummary: { count: 12, returned: 8, limit: 8, truncated: true, items: Array.from({ length: 8 }, (_, index) => ({ seq: index + 1, at: "2026-05-23T00:00:00.000Z", kind: "ran", title: `tool-${index + 1}`, status: "ok", commandPreview: longText(`command-tail-marker-${index + 1}`, 20), outputPreview: longText(`tool-output-tail-marker-${index + 1}`, 20), rawSeqs: [index + 1], })), }, attempts: Array.from({ length: 8 }, (_, index) => ({ index: index + 1, mode: index === 0 ? "initial" : "retry", terminalStatus: "failed", stderrTail: longText(`stderr-tail-marker-${index + 1}`, 20), finalResponse: longText(`attempt-response-tail-marker-${index + 1}`, 30), feedbackPromptPreview: longText(`feedback-tail-marker-${index + 1}`, 20), runnerErrorClassification: { scope: "runner-local", globalBlocker: false }, })), }, }, }; } function outputFixture(path: string): JsonRecord { assertCondition(path.includes("/output"), "output fixture should fetch output", { path }); assertCondition(path.includes("limit=20"), "default output should cap large requested limit to 20", { path }); assertCondition(path.includes("maxTextChars=500"), "default output should cap text preview chars", { path }); const output = Array.from({ length: 20 }, (_, index) => ({ seq: index + 101, at: "2026-05-23T00:00:00.000Z", channel: index % 2 === 0 ? "command" : "assistant", method: "fixture", text: longText(`raw-output-tail-marker-${index + 1}`, 40), })); return { ok: true, status: 200, body: { ok: true, taskId: "codex_disclosure_fixture", queueId: "noise", status: "running", updatedAt: "2026-05-23T00:00:00.000Z", mode: "tail", limit: 20, total: 240, maxSeq: 1200, afterSeq: 0, nextAfterSeq: 120, previousBeforeSeq: 101, hasMore: true, hasBefore: true, output, }, }; } export function runCodeQueueCliDisclosureContract(): JsonRecord { const detail = codexTaskQuery("codex_disclosure_fixture", ["--detail"], detailFixture) as JsonRecord; const detailJson = JSON.stringify(detail); const summary = asRecord(detail.summary); const attempts = asRecord(summary.attempts); const attemptRecords = asArray(attempts.attemptRecords); const toolSummary = asRecord(summary.toolSummary); const toolItems = asArray(toolSummary.items); assertCondition(attemptRecords.length === 3, "detail should cap attempt records by default", attempts); assertCondition(attempts.attemptRecordCount === 8 && attempts.attemptRecordsTruncated === true, "detail should expose omitted attempt metadata", attempts); assertCondition(detailJson.includes("detailOutputPolicy"), "detail should disclose progressive detail policy", summary); assertCondition(!detailJson.includes("prompt-tail-marker-220"), "detail should not include full prompt tail by default", summary); assertCondition(!detailJson.includes("assistant-tail-marker-220"), "detail should not include full assistant tail by default", summary); assertCondition(!detailJson.includes("attempt-response-tail-marker-1-030"), "detail should not include full attempt response by default", attempts); assertCondition(toolItems.length === 3 && toolSummary.truncated === true, "detail should cap tool summary rows by default", toolSummary); assertCondition(!detailJson.includes("tool-output-tail-marker-1-020"), "detail should compact tool output previews", toolSummary); const output = codexOutputQuery("codex_disclosure_fixture", ["--tail", "--limit", "120"], outputFixture) as JsonRecord; const page = asRecord(output.outputPage); const outputRows = asArray(page.output).map(asRecord); const outputJson = JSON.stringify(output); const disclosure = asRecord(page.disclosure); assertCondition(page.requestedLimit === 120 && page.limit === 20 && page.returned === 20, "output should cap large requested limit by default", page); assertCondition(disclosure.limitCapped === true && disclosure.fullText === false, "output should disclose capped default policy", disclosure); assertCondition(outputRows.every((row) => row.textTruncated === true && Number(row.textChars) > String(row.text).length), "output rows should expose bounded text previews", page); assertCondition(!outputJson.includes("raw-output-tail-marker-1-040"), "output should not include full raw text tail by default", page); assertCondition(String(asRecord(page.commands).fullText).includes("--full-text"), "output should provide explicit full-text command", page); return { ok: true, checks: [ "codex task --detail caps attempts and long text by default", "codex output caps large requested limits by default", "codex output preserves progressive full-text command", ], detailChars: detailJson.length, outputChars: outputJson.length, }; } if (import.meta.main) { process.stdout.write(`${JSON.stringify(runCodeQueueCliDisclosureContract(), null, 2)}\n`); }