fix: expose codex submit execution mode mapping
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
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"]);
|
||||
assertCondition(defaultMode.status === 0 && defaultMode.json?.ok === true, "default submit dry-run should succeed", defaultMode.json ?? { stdout: defaultMode.stdout, stderr: defaultMode.stderr });
|
||||
assertSecretFree(defaultMode.stdout);
|
||||
const defaultData = nestedRecord(defaultMode.json?.data, []);
|
||||
const defaultRequest = nestedRecord(defaultData, ["request"]);
|
||||
const defaultExecutionMode = nestedRecord(defaultData, ["executionMode"]);
|
||||
const defaultPermissions = nestedRecord(defaultData, ["runnerPermissions"]);
|
||||
assertCondition(defaultRequest.executionMode === undefined, "default payload should omit executionMode so service default is authoritative", defaultRequest);
|
||||
assertCondition(defaultExecutionMode.requested === null, "default mode should show no explicit requested mode", defaultExecutionMode);
|
||||
assertCondition(defaultExecutionMode.effective === "default", "default mode should expose effective default", defaultExecutionMode);
|
||||
assertCondition(defaultExecutionMode.normalized === false, "default mode should not be reported as normalized", defaultExecutionMode);
|
||||
assertCondition(defaultExecutionMode.recognized === true, "default mode should be recognized", defaultExecutionMode);
|
||||
assertCondition(defaultPermissions.observed === false && defaultPermissions.perTaskOverrideSupported === false, "dry-run should mark runner permissions unobserved and non per-task", defaultPermissions);
|
||||
|
||||
const fullAccess = runCli(["codex", "submit", "execution mode full access smoke", "--execution-mode", "full-access", "--dry-run"]);
|
||||
assertCondition(fullAccess.status === 0 && fullAccess.json?.ok === true, "full-access submit dry-run should succeed", fullAccess.json ?? { stdout: fullAccess.stdout, stderr: fullAccess.stderr });
|
||||
assertSecretFree(fullAccess.stdout);
|
||||
const fullData = nestedRecord(fullAccess.json?.data, []);
|
||||
const fullRequest = nestedRecord(fullData, ["request"]);
|
||||
const fullExecutionMode = nestedRecord(fullData, ["executionMode"]);
|
||||
assertCondition(fullRequest.executionMode === "full-access", "payload should preserve the requested executionMode value for backend visibility", fullRequest);
|
||||
assertCondition(fullExecutionMode.requested === "full-access", "full-access request should be visible", fullExecutionMode);
|
||||
assertCondition(fullExecutionMode.effective === "default", "full-access should normalize to the effective default runtime mode", fullExecutionMode);
|
||||
assertCondition(fullExecutionMode.recognized === false, "full-access should not be treated as a recognized Code Queue execution mode", fullExecutionMode);
|
||||
assertCondition(fullExecutionMode.normalized === true, "full-access should explicitly show normalization", fullExecutionMode);
|
||||
assertCondition(fullExecutionMode.requestedLooksLikeSandbox === true, "full-access should be classified as a sandbox-like request", fullExecutionMode);
|
||||
assertCondition(String(fullExecutionMode.permissionBoundary || "").includes("runnerPermissions.sandbox"), "permission boundary should point at runnerPermissions.sandbox", fullExecutionMode);
|
||||
assertCondition(String(fullExecutionMode.warning || "").includes("not applied"), "full-access warning should say it is not a per-task sandbox override", fullExecutionMode);
|
||||
|
||||
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: [
|
||||
"default codex submit dry-run omits executionMode, reports effective default, and marks runner permissions unobserved",
|
||||
"--execution-mode full-access preserves requested mode, reports effective default, and warns that sandbox permissions are service-level",
|
||||
"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 dry-run output does not print credential assignments",
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
process.stdout.write(`${JSON.stringify(runCodeQueueSubmitExecutionModeContract(), null, 2)}\n`);
|
||||
}
|
||||
@@ -34,6 +34,7 @@ const syntaxFiles = [
|
||||
"scripts/code-queue-prompt-lint-contract-test.ts",
|
||||
"scripts/code-queue-cli-steer-test.ts",
|
||||
"scripts/code-queue-cli-submit-prompt-contract-test.ts",
|
||||
"scripts/code-queue-submit-execution-mode-contract-test.ts",
|
||||
"scripts/code-queue-submit-summary-contract-test.ts",
|
||||
"scripts/code-queue-cli-read-terminal-contract-test.ts",
|
||||
"scripts/code-queue-gh-auth-redaction-contract-test.ts",
|
||||
@@ -362,6 +363,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
|
||||
items.push(commandItem("code-queue:cli-steer-contract", ["bun", "scripts/code-queue-cli-steer-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:read-terminal-contract", ["bun", "scripts/code-queue-cli-read-terminal-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:submit-prompt-contract", ["bun", "scripts/code-queue-cli-submit-prompt-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:submit-execution-mode-contract", ["bun", "scripts/code-queue-submit-execution-mode-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:submit-summary-contract", ["bun", "scripts/code-queue-submit-summary-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:submit-routing-contract", ["bun", "scripts/code-queue-submit-routing-contract-test.ts"], 30_000));
|
||||
items.push(commandItem("code-queue:gh-auth-redaction-contract", ["bun", "scripts/code-queue-gh-auth-redaction-contract-test.ts"], 30_000));
|
||||
@@ -396,6 +398,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
|
||||
items.push(skippedItem("code-queue:cli-steer-contract", "Code Queue steer CLI contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:read-terminal-contract", "Code Queue terminal read contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:submit-prompt-contract", "Code Queue submit prompt contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:submit-execution-mode-contract", "Code Queue submit execution-mode contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:submit-summary-contract", "Code Queue submit summary contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:submit-routing-contract", "Code Queue submit routing contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
items.push(skippedItem("code-queue:gh-auth-redaction-contract", "Code Queue GitHub auth output redaction contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||
|
||||
@@ -3,7 +3,16 @@ import { runCommand } from "./command";
|
||||
import { type UniDeskConfig, repoRoot, rootPath } from "./config";
|
||||
import { coreInternalFetch } from "./microservices";
|
||||
import { previewJson } from "./preview";
|
||||
import { codeAgentPortForModel, codeModelPorts as sharedCodeModelPorts, defaultCodeModels as sharedDefaultCodeModels, opencodeModels as sharedOpencodeModels } from "../../src/components/microservices/code-queue/src/code-agent/common";
|
||||
import {
|
||||
codeAgentPortForModel,
|
||||
codeExecutionModes,
|
||||
codeModelPorts as sharedCodeModelPorts,
|
||||
defaultCodeModels as sharedDefaultCodeModels,
|
||||
normalizeCodeExecutionMode,
|
||||
normalizeRequestedCodeExecutionMode,
|
||||
opencodeModels as sharedOpencodeModels,
|
||||
requestedCodeExecutionModeIsRecognized,
|
||||
} from "../../src/components/microservices/code-queue/src/code-agent/common";
|
||||
|
||||
const defaultToolLimit = 3;
|
||||
const defaultTraceLimit = 80;
|
||||
@@ -25,6 +34,7 @@ const diagnosticsIdPreviewLimit = 3;
|
||||
const diagnosticsReasonPreviewLimit = 2;
|
||||
const mutationQueueIdPreviewLimit = 15;
|
||||
const steerPromptPreviewChars = 320;
|
||||
const sandboxLikeExecutionModes = new Set(["full-access", "danger-full-access", "workspace-write", "read-only"]);
|
||||
const detailAttemptReturnedLimit = 3;
|
||||
const detailInitialPromptPreviewChars = 1200;
|
||||
const detailBasePromptPreviewChars = 800;
|
||||
@@ -3921,6 +3931,61 @@ function referenceTaskIdsFromOptions(args: string[]): string[] {
|
||||
return ids;
|
||||
}
|
||||
|
||||
function parseRequestedExecutionMode(value: string | undefined): string | undefined {
|
||||
if (value === undefined) return undefined;
|
||||
const requested = normalizeRequestedCodeExecutionMode(value);
|
||||
if (requested === null) throw new Error("--execution-mode must be a short mode identifier");
|
||||
return requested;
|
||||
}
|
||||
|
||||
function executionModeSummary(requestedValue: string | null | undefined, effectiveValue?: unknown): Record<string, unknown> {
|
||||
const requested = normalizeRequestedCodeExecutionMode(requestedValue);
|
||||
const effective = typeof effectiveValue === "string" && effectiveValue.trim().length > 0
|
||||
? normalizeCodeExecutionMode(effectiveValue)
|
||||
: normalizeCodeExecutionMode(requested);
|
||||
const requestedLooksLikeSandbox = requested !== null && sandboxLikeExecutionModes.has(requested);
|
||||
const recognized = requestedCodeExecutionModeIsRecognized(requested);
|
||||
return {
|
||||
requested,
|
||||
effective,
|
||||
recognized,
|
||||
normalized: requested !== null && requested !== effective,
|
||||
availableModes: codeExecutionModes,
|
||||
requestedLooksLikeSandbox,
|
||||
permissionBoundary: "--execution-mode selects the Code Queue runtime mode; Codex sandbox permissions come from runnerPermissions.sandbox.",
|
||||
...(requestedLooksLikeSandbox ? { warning: `${requested} is not a Code Queue execution mode and is not applied as a per-task sandbox override.` } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
function dryRunRunnerPermissionsSummary(): Record<string, unknown> {
|
||||
return {
|
||||
observed: false,
|
||||
scope: "code-queue-service-config",
|
||||
sandbox: null,
|
||||
approvalPolicy: null,
|
||||
perTaskOverrideSupported: false,
|
||||
note: "Dry-run does not contact Code Queue; real submit responses include observed runnerPermissions from the service.",
|
||||
secretsPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function compactRunnerPermissions(value: unknown): Record<string, unknown> | null {
|
||||
const record = asRecord(value);
|
||||
if (record === null) return null;
|
||||
return {
|
||||
observed: record.observed ?? true,
|
||||
scope: record.scope ?? "code-queue-service-config",
|
||||
sandbox: record.sandbox ?? null,
|
||||
approvalPolicy: record.approvalPolicy ?? null,
|
||||
perTaskOverrideSupported: record.perTaskOverrideSupported ?? false,
|
||||
secretsPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function compactTaskExecutionModeRequest(record: Record<string, unknown>): Record<string, unknown> {
|
||||
return executionModeSummary(asString(record.requestedExecutionMode) || null, record.executionMode);
|
||||
}
|
||||
|
||||
function parseSubmitOptions(args: string[]): CodexSubmitOptions {
|
||||
assertKnownOptions(args, {
|
||||
flags: ["--prompt-stdin", "--stdin", "--dry-run"],
|
||||
@@ -3953,7 +4018,7 @@ function parseSubmitOptions(args: string[]): CodexSubmitOptions {
|
||||
cwd: optionValue(args, ["--cwd", "--workdir"]),
|
||||
model: optionValue(args, ["--model"]),
|
||||
reasoningEffort: optionValue(args, ["--reasoning-effort"]),
|
||||
executionMode: optionValue(args, ["--execution-mode", "--mode"]),
|
||||
executionMode: parseRequestedExecutionMode(optionValue(args, ["--execution-mode", "--mode"])),
|
||||
maxAttempts,
|
||||
referenceTaskIds: referenceTaskIdsFromOptions(args),
|
||||
dryRun: hasFlag(args, "--dry-run"),
|
||||
@@ -4014,6 +4079,8 @@ function compactTaskMutationResponse(task: unknown, options: CompactTaskMutation
|
||||
reasoningEffort: record.reasoningEffort ?? null,
|
||||
cwd: record.cwd ?? null,
|
||||
executionMode: record.executionMode ?? null,
|
||||
requestedExecutionMode: record.requestedExecutionMode ?? null,
|
||||
executionModeRequest: compactTaskExecutionModeRequest(record),
|
||||
maxAttempts: record.maxAttempts ?? null,
|
||||
currentAttempt: record.currentAttempt ?? null,
|
||||
cancelRequested: record.cancelRequested ?? null,
|
||||
@@ -4048,6 +4115,8 @@ function compactSubmitTaskConfirmation(task: unknown): Record<string, unknown> {
|
||||
reasoningEffort: record.reasoningEffort ?? null,
|
||||
cwd: record.cwd ?? null,
|
||||
executionMode: record.executionMode ?? null,
|
||||
requestedExecutionMode: record.requestedExecutionMode ?? null,
|
||||
executionModeRequest: compactTaskExecutionModeRequest(record),
|
||||
maxAttempts: record.maxAttempts ?? null,
|
||||
createdAt: record.createdAt ?? null,
|
||||
updatedAt: record.updatedAt ?? null,
|
||||
@@ -4220,6 +4289,7 @@ function compactSubmitQueueConfirmation(value: unknown, options: CompactSubmitQu
|
||||
databaseActiveTaskIds: databaseActivePreview,
|
||||
queuedTaskIds: queuedPreview,
|
||||
executionDiagnostics: compactQueueExecutionDiagnostics(record.executionDiagnostics),
|
||||
runnerPermissions: compactRunnerPermissions(record.runnerPermissions),
|
||||
...(submittedTasks.length === 0 ? {} : { submittedTaskIds: submittedPreview }),
|
||||
countContext: {
|
||||
queued: countForStatus(counts, "queued"),
|
||||
@@ -4265,9 +4335,14 @@ function compactSubmitSuccessResponse(body: Record<string, unknown>, upstream: R
|
||||
const queueIds = Array.from(new Set(tasks.map((task) => asString(task.queueId)).filter(Boolean))).sort();
|
||||
const firstTaskId = taskIds[0] ?? null;
|
||||
const firstQueueId = queueIds[0] ?? null;
|
||||
const firstSubmittedTask = submittedTasks[0] ?? {};
|
||||
const queueRecord = asRecord(body.queue);
|
||||
const runnerPermissions = compactRunnerPermissions(queueRecord?.runnerPermissions);
|
||||
return {
|
||||
ok: true,
|
||||
upstream,
|
||||
executionMode: executionModeSummary(asString(firstSubmittedTask.requestedExecutionMode) || null, firstSubmittedTask.executionMode),
|
||||
runnerPermissions,
|
||||
submitted: {
|
||||
accepted: true,
|
||||
taskCount: allTasks.length,
|
||||
@@ -4393,6 +4468,11 @@ function compactTerminalReadTask(summary: unknown, readTask: unknown, taskId: st
|
||||
readAt,
|
||||
providerId: summaryRecord.providerId ?? readRecord.providerId ?? null,
|
||||
executionMode: summaryRecord.executionMode ?? readRecord.executionMode ?? null,
|
||||
requestedExecutionMode: summaryRecord.requestedExecutionMode ?? readRecord.requestedExecutionMode ?? null,
|
||||
executionModeRequest: compactTaskExecutionModeRequest({
|
||||
requestedExecutionMode: summaryRecord.requestedExecutionMode ?? readRecord.requestedExecutionMode ?? null,
|
||||
executionMode: summaryRecord.executionMode ?? readRecord.executionMode ?? null,
|
||||
}),
|
||||
executionModeInfo: summaryRecord.executionModeInfo ?? readRecord.executionModeInfo ?? null,
|
||||
model: summaryRecord.model ?? readRecord.model ?? null,
|
||||
agentPort: summaryRecord.agentPort ?? readRecord.agentPort ?? null,
|
||||
@@ -5848,6 +5928,8 @@ function codexSubmitTask(args: string[]): unknown {
|
||||
ok: true,
|
||||
dryRun: true,
|
||||
promptLint,
|
||||
executionMode: executionModeSummary(options.executionMode),
|
||||
runnerPermissions: dryRunRunnerPermissionsSummary(),
|
||||
routingRecommendation: submitRoutingRecommendation(options),
|
||||
modelRegistry: submitModelRegistry(),
|
||||
request: {
|
||||
|
||||
@@ -276,6 +276,11 @@ function codexHelp(): unknown {
|
||||
positional: "Keep positional prompt usage to short one-line smoke prompts only.",
|
||||
sourceRule: "Exactly one prompt source is accepted: positional prompt, --prompt-file, or --prompt-stdin.",
|
||||
},
|
||||
executionMode: {
|
||||
validModes: ["default", "windows-native"],
|
||||
boundary: "--execution-mode selects Code Queue runtime placement, not Codex sandbox permissions.",
|
||||
permissionVisibility: "Submit dry-runs show requested/effective mode; real submit responses include service runnerPermissions.sandbox and approvalPolicy.",
|
||||
},
|
||||
readOutput: {
|
||||
default: "codex read marks a terminal task read and returns terminal metadata, final response, last error/judge, counts, and drill-down commands.",
|
||||
disclosure: "Full prompt, tool logs, and feedback prompts are not printed by codex read; use codex task/detail/trace/output for progressive disclosure.",
|
||||
|
||||
Reference in New Issue
Block a user