// src/mcp/codex-diagnostics.ts
import { constants } from "fs";
import { open } from "fs/promises";
import { stripVTControlCharacters } from "util";
var CodexExecutionDiagnosticError = class extends Error {
  constructor(reason, diagnostic, cause) {
    super(
      `runLocalHarness: reproducible Codex execution failed: ${reason}; diagnostic=${JSON.stringify(diagnostic)}`,
      { cause }
    );
    this.reason = reason;
    this.diagnostic = diagnostic;
    this.name = "CodexExecutionDiagnosticError";
  }
  reason;
  diagnostic;
  code = "CODEX_EXECUTION_DIAGNOSTIC";
};
var CODEX_FAILURE_STREAM_MAX_CHARS = 4096;
var CODEX_AUTH_MAX_BYTES = 1024 * 1024;
var CODEX_REDACTED = "<REDACTED_CREDENTIAL>";
var codexSensitiveEnvironmentName = /(TOKEN|KEY|SECRET|PASSWORD|CREDENTIAL|AUTH|COOKIE)/i;
function createCodexExecutionDiagnosticError(opts) {
  const redact = (value) => redactCodexDiagnostic(value, opts.codexHome, opts.redactionValues);
  const boundedStdout = boundCodexDiagnostic(redact(opts.stdout));
  const boundedStderr = boundCodexDiagnostic(redact(opts.stderr));
  const diagnostic = {
    exitCode: opts.exitCode,
    killedBySignal: opts.killedBySignal,
    timedOut: opts.timedOut,
    durationMs: opts.durationMs,
    stdout: boundedStdout.value,
    stderr: boundedStderr.value,
    stdoutTruncated: boundedStdout.truncated,
    stderrTruncated: boundedStderr.truncated
  };
  const safeReason = boundCodexDiagnostic(redact(opts.reason), 1024).value;
  return new CodexExecutionDiagnosticError(
    safeReason,
    diagnostic,
    redactCodexErrorCause(opts.cause, safeReason, redact)
  );
}
function redactCodexHome(value, codexHome) {
  return codexHome ? value.replaceAll(codexHome, "<ISOLATED_CODEX_HOME>") : value;
}
function collectCodexDiagnosticRedactionValues(env, authText) {
  const values = Object.entries(env).filter(
    ([name, value]) => codexSensitiveEnvironmentName.test(name) && typeof value === "string"
  ).map(([, value]) => value);
  try {
    collectStringLeaves(JSON.parse(authText), values);
  } catch {
  }
  const encoded = values.filter((value) => value.length >= 8).flatMap((value) => [
    Buffer.from(value, "utf8").toString("base64"),
    Buffer.from(value, "utf8").toString("base64url"),
    encodeURIComponent(value),
    JSON.stringify(value).slice(1, -1)
  ]);
  return [.../* @__PURE__ */ new Set([...values, ...encoded])];
}
async function readCodexAuthRedactionText(path) {
  const handle = await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
  try {
    const stats = await handle.stat();
    if (!stats.isFile() || !Number.isSafeInteger(stats.size) || stats.size > CODEX_AUTH_MAX_BYTES) {
      throw new Error("Codex auth.json must be a regular file no larger than 1 MiB");
    }
    const buffer = Buffer.alloc(stats.size);
    let offset = 0;
    while (offset < buffer.length) {
      const { bytesRead } = await handle.read(buffer, offset, buffer.length - offset, offset);
      if (bytesRead === 0) break;
      offset += bytesRead;
    }
    return buffer.subarray(0, offset).toString("utf8");
  } finally {
    await handle.close();
  }
}
function boundCodexDiagnostic(value, maxChars = CODEX_FAILURE_STREAM_MAX_CHARS) {
  if (value.length <= maxChars) return { value, truncated: false };
  const marker = "\n<... OUTPUT TRUNCATED ...>\n";
  const contentChars = maxChars - marker.length;
  const headChars = Math.floor(contentChars / 2);
  const tailChars = contentChars - headChars;
  return {
    value: `${value.slice(0, headChars)}${marker}${value.slice(-tailChars)}`,
    truncated: true
  };
}
function redactCodexDiagnostic(value, codexHome, protectedValues) {
  let redacted = redactCodexHome(stripVTControlCharacters(value), codexHome);
  const exactValues = [...new Set(protectedValues.filter((item) => item.length >= 6))].sort(
    (a, b) => b.length - a.length
  );
  for (const secret of exactValues) redacted = redacted.replaceAll(secret, CODEX_REDACTED);
  redacted = redacted.replace(/(\bBearer\s+)[A-Za-z0-9._~+/=-]{6,}/gi, `$1${CODEX_REDACTED}`).replace(/\b(?:sk|rk|pk)-[A-Za-z0-9._-]{8,}\b/g, CODEX_REDACTED).replace(/\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b/g, CODEX_REDACTED).replace(
    /((?:["']?(?:api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|client[-_]?secret|private[-_]?key|session[-_]?(?:id|token)|secret|password|passwd|authorization|credential|cookie)["']?)\s*[:=]\s*)(["'])[^"'\r\n]*\2/gi,
    `$1$2${CODEX_REDACTED}$2`
  ).replace(
    /((?:["']?(?:api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|client[-_]?secret|private[-_]?key|session[-_]?(?:id|token)|secret|password|passwd|authorization|credential|cookie)["']?)\s*[:=]\s*)([^\s,;}]+)/gi,
    `$1${CODEX_REDACTED}`
  );
  for (const secret of exactValues) redacted = redacted.replaceAll(secret, CODEX_REDACTED);
  return redacted;
}
function redactCodexErrorCause(cause, safeReason, redact) {
  if (!(cause instanceof Error)) return void 0;
  const safeCause = new Error(safeReason);
  safeCause.name = cause.name;
  if (cause.stack) safeCause.stack = boundCodexDiagnostic(redact(cause.stack)).value;
  return safeCause;
}
function collectStringLeaves(value, output) {
  if (typeof value === "string") {
    output.push(value);
    return;
  }
  if (Array.isArray(value)) {
    for (const item of value) collectStringLeaves(item, output);
    return;
  }
  if (value !== null && typeof value === "object") {
    for (const item of Object.values(value)) collectStringLeaves(item, output);
  }
}

// src/mcp/local-harness.ts
import { spawn } from "child_process";
import { createHash, randomUUID } from "crypto";
import { constants as constants2, createReadStream } from "fs";
import {
  access,
  chmod,
  copyFile,
  mkdir,
  mkdtemp,
  open as open2,
  readFile,
  realpath,
  rm,
  symlink,
  writeFile
} from "fs/promises";
import { homedir, tmpdir } from "os";
import { basename, delimiter, dirname, isAbsolute, join, resolve, sep } from "path";
var codexReasoningEffort = {
  none: "none",
  minimal: "minimal",
  low: "low",
  medium: "medium",
  high: "high",
  xhigh: "xhigh",
  ultracode: "xhigh"
};
function codexReasoningArgs(reasoningEffort) {
  const mapped = codexReasoningEffort[reasoningEffort];
  if (mapped === void 0) {
    throw new Error(
      `harnessInvocation: unsupported Codex reasoning effort ${String(reasoningEffort)}`
    );
  }
  return ["-c", `model_reasoning_effort="${mapped}"`];
}
var HARNESS_INVOCATIONS = {
  claude: {
    command: "claude",
    // `-p` IS headless/print mode; the old `--headless` flag was removed from the CLI.
    // Permission bypass is an explicit per-run opt-in below, never the public default.
    buildArgs: (taskPrompt) => ["-p", taskPrompt],
    modelArgs: (model) => ["-m", model]
  },
  codex: {
    command: "codex",
    buildArgs: (taskPrompt) => ["exec", taskPrompt],
    modelArgs: (model) => ["-m", model],
    reasoningArgs: codexReasoningArgs
  },
  opencode: {
    command: "opencode",
    buildArgs: (taskPrompt) => ["run", taskPrompt],
    modelArgs: (model) => ["-m", model]
  }
};
var CODEX_REPRODUCIBLE_ARGS = [
  "--ephemeral",
  "--ignore-rules",
  "--json",
  "-c",
  'approval_policy="never"',
  "-c",
  'web_search="disabled"',
  "-c",
  "project_doc_max_bytes=0",
  "-c",
  "skills.include_instructions=false",
  "-c",
  "include_apps_instructions=false",
  "--disable",
  "tool_suggest",
  "-c",
  'features.multi_agent_v2.root_agent_usage_hint_text=""',
  "-c",
  'features.multi_agent_v2.subagent_usage_hint_text=""',
  "-c",
  'features.multi_agent_v2.multi_agent_mode_hint_text=""',
  "--strict-config"
];
function buildHarnessArgs(harness, taskPrompt, options = {}) {
  const args = HARNESS_INVOCATIONS[harness].buildArgs(taskPrompt);
  if (harness === "claude" && options.dangerouslySkipPermissions) {
    args.push("--dangerously-skip-permissions");
  }
  if (options.codexReproducible) {
    if (harness !== "codex") {
      throw new Error("harnessInvocation: codexReproducible requires the Codex harness");
    }
    args.push(...CODEX_REPRODUCIBLE_ARGS);
  }
  return args;
}
function harnessInvocation(harness, profile, taskPrompt, options = {}) {
  const invocation = HARNESS_INVOCATIONS[harness];
  if (!invocation) {
    throw new Error(`harnessInvocation: unknown harness ${String(harness)}`);
  }
  if (options.codexReproducible) {
    const model2 = profile.model?.default;
    if (typeof model2 !== "string" || model2.trim().length === 0) {
      throw new Error("harnessInvocation: codexReproducible requires profile.model.default");
    }
    if (profile.model?.reasoningEffort === void 0) {
      throw new Error("harnessInvocation: codexReproducible requires profile.model.reasoningEffort");
    }
  }
  const systemPrompt = profile.prompt?.systemPrompt;
  const instructions = profile.prompt?.instructions;
  if (instructions !== void 0 && (!Array.isArray(instructions) || instructions.some((instruction) => typeof instruction !== "string"))) {
    throw new Error("harnessInvocation: profile.prompt.instructions must be an array of strings");
  }
  const promptSections = [
    ...typeof systemPrompt === "string" && systemPrompt.trim().length > 0 ? [systemPrompt] : [],
    ...instructions?.filter((instruction) => instruction.trim().length > 0) ?? [],
    taskPrompt
  ];
  const composedPrompt = promptSections.join("\n\n");
  const args = buildHarnessArgs(harness, composedPrompt, options);
  const model = profile.model?.default;
  if (typeof model === "string" && model.length > 0) {
    args.push(...invocation.modelArgs(model));
  }
  const reasoningEffort = profile.model?.reasoningEffort;
  if (reasoningEffort !== void 0 && invocation.reasoningArgs) {
    args.push(...invocation.reasoningArgs(reasoningEffort));
  }
  return { command: invocation.command, args, prompt: composedPrompt };
}
var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
var processKillGraceMs = 250;
async function runLocalHarness(options) {
  const { harness, cwd, taskPrompt } = options;
  if (options.codexReproducible && harness !== "codex") {
    throw new Error("runLocalHarness: codexReproducible requires the Codex harness");
  }
  if (options.codexReproducible && process.platform !== "linux") {
    throw new Error("runLocalHarness: codexReproducible currently requires Linux");
  }
  if (options.codexReadDeniedPaths !== void 0 && !options.codexReproducible) {
    throw new Error("runLocalHarness: codexReadDeniedPaths requires codexReproducible");
  }
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
  const spawnImpl = options.spawn ?? spawn;
  const invocation = HARNESS_INVOCATIONS[harness];
  if (!invocation) {
    throw new Error(`runLocalHarness: unknown harness ${String(harness)}`);
  }
  const startedAt = Date.now();
  const requestedCommand = options.invocation?.command ?? invocation.command;
  const args = options.invocation ? [...options.invocation.args] : buildHarnessArgs(harness, taskPrompt, options);
  if (options.codexReproducible) assertCodexReproducibleInvocation(requestedCommand, args);
  const baseEnv = { ...options.env ?? process.env, PWD: cwd };
  const isolated = options.codexReproducible ? await isolateCodexHome({
    baseEnv,
    cwd,
    command: requestedCommand,
    readDeniedPaths: options.codexReadDeniedPaths ?? [],
    resolveExecutable: options.resolveCodexExecutable ?? resolveCodexNativeExecutable
  }) : {
    env: baseEnv,
    command: requestedCommand,
    cleanup: async () => void 0,
    controlledConfigSha256: "",
    executableSha256: "",
    readDeniedPathsSha256: "",
    readDeniedPathCount: 0,
    readDeniedPaths: [],
    diagnosticRedactionValues: [],
    ambientAuth: "",
    isolatedAuth: "",
    writeProbe: "",
    stagedWriteProbe: "",
    deniedProbePaths: []
  };
  const env = isolated.env;
  const command = isolated.command;
  if (options.codexReproducible) assertCodexReproducibleInvocation(command, args);
  try {
    const evidence = options.codexReproducible ? await collectCodexExecutionEvidence({
      command,
      args,
      cwd,
      env,
      spawn: spawnImpl,
      controlledConfigSha256: isolated.controlledConfigSha256,
      executableSha256: isolated.executableSha256,
      readDeniedPathsSha256: isolated.readDeniedPathsSha256,
      readDeniedPathCount: isolated.readDeniedPathCount,
      readDeniedPaths: isolated.readDeniedPaths,
      ambientAuth: isolated.ambientAuth,
      isolatedAuth: isolated.isolatedAuth,
      writeProbe: isolated.writeProbe,
      stagedWriteProbe: isolated.stagedWriteProbe,
      deniedProbePaths: isolated.deniedProbePaths,
      ...options.signal ? { signal: options.signal } : {}
    }) : void 0;
    return await new Promise((resolve2, reject) => {
      let child;
      try {
        child = spawnImpl(command, args, {
          cwd,
          env,
          stdio: "pipe",
          detached: process.platform !== "win32"
        });
      } catch (err) {
        reject(err instanceof Error ? err : new Error(String(err)));
        return;
      }
      child.stdin?.end();
      let stdout = "";
      let stderr = "";
      let timedOut = false;
      let settled = false;
      let forceKillTimer = null;
      let terminationStarted = false;
      const terminate = () => {
        if (terminationStarted) return;
        terminationStarted = true;
        signalProcessTree(child, "SIGTERM");
        forceKillTimer = setTimeout(() => signalProcessTree(child, "SIGKILL"), processKillGraceMs);
        forceKillTimer.unref?.();
      };
      const timer = timeoutMs > 0 ? setTimeout(() => {
        timedOut = true;
        terminate();
      }, timeoutMs) : null;
      if (timer && typeof timer.unref === "function") {
        ;
        timer.unref();
      }
      const onAbort = () => {
        terminate();
      };
      if (options.signal) {
        if (options.signal.aborted) onAbort();
        else options.signal.addEventListener("abort", onAbort, { once: true });
      }
      child.stdout?.on("data", (chunk) => {
        stdout += String(chunk);
      });
      child.stderr?.on("data", (chunk) => {
        stderr += String(chunk);
      });
      const finalize = (result) => {
        if (settled) return;
        settled = true;
        if (timer) clearTimeout(timer);
        if (forceKillTimer) clearTimeout(forceKillTimer);
        options.signal?.removeEventListener("abort", onAbort);
        resolve2(result);
      };
      child.on("error", (err) => {
        if (settled) return;
        settled = true;
        if (timer) clearTimeout(timer);
        if (forceKillTimer) clearTimeout(forceKillTimer);
        options.signal?.removeEventListener("abort", onAbort);
        reject(err);
      });
      child.on("close", (code, signal) => {
        const durationMs = Date.now() - startedAt;
        try {
          const usage = options.codexReproducible ? parseCodexTokenUsage(stdout) : void 0;
          finalize({
            exitCode: code,
            stdout,
            stderr: redactCodexHome(stderr, env.CODEX_HOME),
            killedBySignal: signal,
            durationMs,
            timedOut,
            ...usage ? { usage } : {},
            ...evidence ? { evidence } : {}
          });
        } catch (err) {
          if (settled) return;
          settled = true;
          if (timer) clearTimeout(timer);
          if (forceKillTimer) clearTimeout(forceKillTimer);
          options.signal?.removeEventListener("abort", onAbort);
          const reason = err instanceof Error ? err.message : String(err);
          reject(
            options.codexReproducible ? createCodexExecutionDiagnosticError({
              reason,
              exitCode: code,
              killedBySignal: signal,
              timedOut,
              durationMs,
              stdout,
              stderr,
              codexHome: env.CODEX_HOME,
              redactionValues: isolated.diagnosticRedactionValues,
              cause: err
            }) : err instanceof Error ? err : new Error(reason)
          );
        }
      });
    });
  } finally {
    await isolated.cleanup();
  }
}
var CODEX_EXECUTION_POLICY = {
  sessionPersistence: "ephemeral",
  userConfig: false,
  rules: false,
  projectInstructions: false,
  skillInstructions: false,
  appInstructions: false,
  toolSuggestions: false,
  multiAgentInstructions: false,
  sandbox: "workspace-write",
  permissionProfile: "agent_runtime_reproducible",
  approvalPolicy: "never",
  shellNetwork: false,
  webSearch: false,
  serviceTier: "default",
  shellEnvironment: "core-filtered",
  loginShell: false,
  credentialsReadable: false,
  hostHomeReadable: false,
  procEnvironment: "private-sanitized",
  sensitiveEnvironmentNamesVisible: false,
  parentRepoRead: false,
  gitMetadata: false,
  temporaryDirectory: "workspace-private",
  stagedExecutable: "static-elf-read-only",
  callerReadDeniedPaths: "enforced",
  containerSockets: false
};
var FORBIDDEN_CODEX_PROMPT_MARKERS = [
  "<skills_instructions>",
  "# AGENTS.md instructions",
  "<apps_instructions>",
  "<recommended_plugins>",
  "<multi_agent_mode>",
  "You are `/root`, the primary agent"
];
async function collectCodexExecutionEvidence(opts) {
  assertCodexReproducibleInvocation(opts.command, opts.args);
  const prompt = opts.args[1];
  if (opts.args[0] !== "exec" || typeof prompt !== "string" || prompt.length === 0) {
    throw new Error("runLocalHarness: reproducible Codex invocation must be codex exec <prompt>");
  }
  const cliVersion = (await runCodexProbe(opts, ["--version"])).stdout.trim();
  if (!/^codex-cli \d+\.\d+\.\d+(?:[-+].+)?$/.test(cliVersion)) {
    throw new Error(
      `runLocalHarness: unexpected Codex CLI version output ${JSON.stringify(cliVersion)}`
    );
  }
  const hiddenEnvironmentChecks = [
    "CODEX_HOME",
    "CODEX_ACCESS_TOKEN",
    "CODEX_API_KEY",
    "OPENAI_API_KEY"
  ].map((name) => `test -z "\${${name}:-}"`).join(" && ");
  const sandboxProof = [
    hiddenEnvironmentChecks,
    "test -r .",
    "! test -r .git",
    'touch "$1"',
    'rm "$1"',
    'staged_dir=$(dirname "$2")',
    'test -x "$staged_dir/codex"',
    '! chmod 700 "$staged_dir" 2>/dev/null',
    '! rm "$staged_dir/codex" 2>/dev/null',
    '! touch "$2" 2>/dev/null',
    "shift 2",
    'for path in "$@"; do ! test -r "$path" || exit 1; done',
    'touch "$TMPDIR/.agent-runtime-tmp-proof"',
    'rm "$TMPDIR/.agent-runtime-tmp-proof"'
  ].join(" && ");
  await runCodexProbe(opts, [
    "sandbox",
    "-P",
    CODEX_PERMISSION_PROFILE,
    "-C",
    opts.cwd,
    "sh",
    "-c",
    sandboxProof,
    "sh",
    opts.writeProbe,
    opts.stagedWriteProbe,
    ...opts.deniedProbePaths
  ]);
  await runCodexProbe(opts, [
    "sandbox",
    "-P",
    CODEX_PERMISSION_PROFILE,
    "-C",
    opts.cwd,
    "python3",
    "-c",
    `import os,re
pattern=re.compile(br'(TOKEN|KEY|SECRET|PASSWORD|CREDENTIAL|AUTH|COOKIE|CODEX_HOME)', re.I)
paths=('/proc/1/environ', '/proc/self/environ', f'/proc/{os.getppid()}/environ')
for path in dict.fromkeys(paths):
 data=open(path,'rb').read().split(b'\\0')
 names=(item.split(b'=',1)[0] for item in data if b'=' in item)
 assert not any(pattern.search(name) for name in names), path`
  ]);
  await runCodexProbe(opts, [
    "sandbox",
    "-P",
    CODEX_PERMISSION_PROFILE,
    "-C",
    opts.cwd,
    "python3",
    "-c",
    "import socket,sys\nfor path in sys.argv[1:]:\n s=socket.socket(socket.AF_UNIX)\n try: s.connect(path)\n except OSError: continue\n raise SystemExit(1)",
    "/var/run/docker.sock",
    "/run/docker.sock",
    "/var/run/containerd/containerd.sock",
    "/run/containerd/containerd.sock"
  ]);
  const debugArgs = codexPromptDebugArgs(opts.args, prompt);
  const renderedPrompt = (await runCodexProbe(opts, debugArgs)).stdout;
  let parsedPrompt;
  try {
    parsedPrompt = JSON.parse(renderedPrompt);
  } catch {
    throw new Error("runLocalHarness: codex debug prompt-input returned invalid JSON");
  }
  const promptEvidenceText = normalizeCodexDebugPromptNewlines(prompt);
  if (!Array.isArray(parsedPrompt) || !jsonTextContains(parsedPrompt, promptEvidenceText)) {
    throw new Error("runLocalHarness: Codex prompt evidence did not contain the exact task prompt");
  }
  const promptContextWithoutTask = JSON.stringify(redactJsonText(parsedPrompt, promptEvidenceText));
  for (const marker of FORBIDDEN_CODEX_PROMPT_MARKERS) {
    if (promptContextWithoutTask.includes(marker)) {
      throw new Error(`runLocalHarness: Codex prompt evidence contains forbidden marker ${marker}`);
    }
  }
  for (const marker of ["<permissions instructions>", "<environment_context>"]) {
    if (!renderedPrompt.includes(marker)) {
      throw new Error(`runLocalHarness: Codex prompt evidence is missing required marker ${marker}`);
    }
  }
  const nonPromptArgs = [
    "codex",
    ...opts.args.map((arg, index) => index === 1 ? "<PROMPT>" : arg)
  ];
  return {
    cliVersion,
    executableSha256: opts.executableSha256,
    requestedPromptSha256: sha256(prompt),
    effectivePromptSha256: sha256(renderedPrompt),
    nonPromptArgsSha256: sha256(JSON.stringify(nonPromptArgs)),
    controlledConfigSha256: opts.controlledConfigSha256,
    readDeniedPathsSha256: opts.readDeniedPathsSha256,
    readDeniedPathCount: opts.readDeniedPathCount,
    readDeniedPaths: [...opts.readDeniedPaths],
    policy: { ...CODEX_EXECUTION_POLICY }
  };
}
function assertCodexReproducibleInvocation(command, args) {
  const executable = basename(command);
  if (executable !== "codex" && executable !== "codex.exe") {
    throw new Error("runLocalHarness: reproducible Codex invocation must use the Codex executable");
  }
  const prompt = args[1];
  const expectedPrefix = ["exec", prompt, ...CODEX_REPRODUCIBLE_ARGS];
  const hasExactPrefix = expectedPrefix.every((arg, index) => args[index] === arg);
  const tail = args.slice(expectedPrefix.length);
  const validModel = tail[0] === "-m" && typeof tail[1] === "string" && tail[1].length > 0 && !tail[1].startsWith("-");
  const validReasoning = tail[2] === "-c" && typeof tail[3] === "string" && /^model_reasoning_effort="(?:none|minimal|low|medium|high|xhigh)"$/.test(tail[3]);
  if (!hasExactPrefix || tail.length !== 4 || !validModel || !validReasoning) {
    throw new Error(
      "runLocalHarness: reproducible Codex invocation does not match the required isolated argv"
    );
  }
}
function codexPromptDebugArgs(execArgs, prompt) {
  const debugArgs = ["debug", "prompt-input"];
  for (let index = 2; index < execArgs.length; index += 1) {
    const arg = execArgs[index];
    const value = execArgs[index + 1];
    if (arg === "-c" && value !== void 0) {
      debugArgs.push("-c", value);
      index += 1;
    } else if (arg === "--disable" && value !== void 0) {
      debugArgs.push("--disable", value);
      index += 1;
    } else if (arg === "-m" && value !== void 0) {
      debugArgs.push("-c", `model=${JSON.stringify(value)}`);
      index += 1;
    } else if (arg === "-s" && value !== void 0) {
      debugArgs.push("-c", `sandbox_mode=${JSON.stringify(value)}`);
      index += 1;
    }
  }
  debugArgs.push(prompt);
  return debugArgs;
}
function runCodexProbe(opts, args) {
  return new Promise((resolve2, reject) => {
    let child;
    try {
      child = opts.spawn(opts.command, args, {
        cwd: opts.cwd,
        env: opts.env,
        stdio: "pipe",
        detached: process.platform !== "win32"
      });
    } catch (err) {
      reject(err instanceof Error ? err : new Error(String(err)));
      return;
    }
    child.stdin?.end();
    let stdout = "";
    let stderr = "";
    let settled = false;
    let forceKillTimer = null;
    const timer = setTimeout(() => {
      signalProcessTree(child, "SIGTERM");
      forceKillTimer = setTimeout(() => signalProcessTree(child, "SIGKILL"), processKillGraceMs);
      forceKillTimer.unref?.();
    }, 1e4);
    timer.unref?.();
    const onAbort = () => {
      signalProcessTree(child, "SIGTERM");
      if (!forceKillTimer) {
        forceKillTimer = setTimeout(() => signalProcessTree(child, "SIGKILL"), processKillGraceMs);
        forceKillTimer.unref?.();
      }
    };
    if (opts.signal) {
      if (opts.signal.aborted) onAbort();
      else opts.signal.addEventListener("abort", onAbort, { once: true });
    }
    child.stdout?.on("data", (chunk) => {
      stdout += String(chunk);
    });
    child.stderr?.on("data", (chunk) => {
      stderr += String(chunk);
    });
    child.on("error", (err) => {
      if (settled) return;
      settled = true;
      clearTimeout(timer);
      if (forceKillTimer) clearTimeout(forceKillTimer);
      opts.signal?.removeEventListener("abort", onAbort);
      reject(err);
    });
    child.on("close", (code, signal) => {
      if (settled) return;
      settled = true;
      clearTimeout(timer);
      if (forceKillTimer) clearTimeout(forceKillTimer);
      opts.signal?.removeEventListener("abort", onAbort);
      if (code !== 0) {
        const safeStderr = redactCodexHome(stderr, opts.env.CODEX_HOME);
        reject(
          new Error(
            `runLocalHarness: Codex evidence probe failed (exit ${String(code)}, signal ${String(signal)}): ${safeStderr.trim()}`
          )
        );
        return;
      }
      resolve2({ stdout, stderr });
    });
  });
}
function sha256(value) {
  return createHash("sha256").update(value).digest("hex");
}
function normalizeCodexDebugPromptNewlines(value) {
  return value.replaceAll("\r\n", "\n");
}
function jsonTextContains(value, needle) {
  if (typeof value === "string") return value.includes(needle);
  if (Array.isArray(value)) return value.some((item) => jsonTextContains(item, needle));
  if (isRecord(value)) return Object.values(value).some((item) => jsonTextContains(item, needle));
  return false;
}
function redactJsonText(value, text) {
  if (typeof value === "string") return value.replaceAll(text, "");
  if (Array.isArray(value)) return value.map((item) => redactJsonText(item, text));
  if (isRecord(value)) {
    return Object.fromEntries(
      Object.entries(value).map(([key, item]) => [key, redactJsonText(item, text)])
    );
  }
  return value;
}
var CODEX_AUTH_ENV = ["CODEX_ACCESS_TOKEN", "CODEX_API_KEY", "OPENAI_API_KEY"];
var CODEX_PERMISSION_PROFILE = "agent_runtime_reproducible";
async function isolateCodexHome(opts) {
  const isolatedHome = await mkdtemp(join(tmpdir(), "agent-runtime-codex-"));
  await chmod(isolatedHome, 448);
  let workspaceTemp = "";
  let stagedExecutableDir = "";
  let ownsStagedExecutableDir = false;
  let writeProbe = "";
  const cleanup = async () => {
    if (ownsStagedExecutableDir) {
      await chmod(stagedExecutableDir, 448).catch(() => void 0);
    }
    await Promise.all([
      ...writeProbe ? [rm(writeProbe, { force: true })] : [],
      ...workspaceTemp ? [rm(workspaceTemp, { recursive: true, force: true })] : [],
      ...ownsStagedExecutableDir ? [rm(stagedExecutableDir, { recursive: true, force: true })] : [],
      rm(isolatedHome, { recursive: true, force: true })
    ]);
  };
  try {
    const readDeniedPaths = await normalizeReadDeniedPaths(opts.readDeniedPaths);
    const candidateRoot = await realpath(opts.cwd);
    writeProbe = join(candidateRoot, `.agent-runtime-write-proof-${randomUUID()}`);
    const stagedPath = join(candidateRoot, ".agent-runtime-bin");
    if (readDeniedPaths.some(
      (path) => isSameOrDescendant(candidateRoot, path) || isSameOrDescendant(stagedPath, path) || isSameOrDescendant(path, stagedPath)
    )) {
      throw new Error(
        "runLocalHarness: codexReadDeniedPaths cannot contain the candidate root or staged executable"
      );
    }
    const nativeExecutable = await opts.resolveExecutable(opts.command, opts.baseEnv);
    if (!await isStaticElfExecutable(nativeExecutable)) {
      throw new Error(
        "runLocalHarness: reproducible Codex mode requires a statically linked Linux Codex ELF"
      );
    }
    const sourceExecutableSha256 = await sha256File(nativeExecutable);
    stagedExecutableDir = stagedPath;
    try {
      await mkdir(stagedExecutableDir, { mode: 448 });
      ownsStagedExecutableDir = true;
    } catch (err) {
      throw new Error(
        `runLocalHarness: candidate-private .agent-runtime-bin must not already exist: ${String(err.code ?? err)}`
      );
    }
    const stagedExecutable = join(stagedExecutableDir, "codex");
    await copyFile(nativeExecutable, stagedExecutable, constants2.COPYFILE_FICLONE);
    await chmod(stagedExecutable, 320);
    const executableSha256 = await sha256File(stagedExecutable);
    if (executableSha256 !== sourceExecutableSha256 || !await isStaticElfExecutable(stagedExecutable)) {
      throw new Error("runLocalHarness: staged Codex executable digest mismatch");
    }
    await chmod(stagedExecutableDir, 320);
    workspaceTemp = await mkdtemp(join(candidateRoot, ".agent-runtime-tmp-"));
    await chmod(workspaceTemp, 448);
    const ambientHome = resolve(opts.baseEnv.CODEX_HOME?.trim() || join(homedir(), ".codex"));
    const ambientAuth = join(ambientHome, "auth.json");
    const isolatedAuth = join(isolatedHome, "auth.json");
    let authText = "";
    try {
      await access(ambientAuth, constants2.R_OK);
      authText = await readCodexAuthRedactionText(ambientAuth);
      await symlink(ambientAuth, isolatedAuth);
    } catch (err) {
      throw new Error(
        `runLocalHarness: reproducible Codex mode requires readable auth.json: ${String(err.code ?? err)}`
      );
    }
    const deniedHostRoots = [homedir(), opts.baseEnv.HOME?.trim(), ambientHome].filter((path) => Boolean(path)).map((path) => resolve(path)).filter((path, index, paths) => paths.indexOf(path) === index);
    const controlledConfig = codexControlledConfig({
      ambientTmp: opts.baseEnv.TMPDIR?.trim() || tmpdir(),
      deniedHostRoots,
      workspaceTemp,
      stagedExecutableDir,
      readDeniedPaths
    });
    await writeFile(join(isolatedHome, "config.toml"), controlledConfig, { mode: 384 });
    const env = { ...opts.baseEnv };
    for (const name of Object.keys(env)) {
      if (codexSensitiveEnvironmentName.test(name) || CODEX_AUTH_ENV.some((authName) => authName === name)) {
        delete env[name];
      }
    }
    env.CODEX_HOME = isolatedHome;
    const home = homedir();
    const deniedProbePaths = [
      ...deniedHostRoots,
      ambientAuth,
      isolatedAuth,
      join(home, ".claude", ".credentials.json"),
      join(home, ".claude.json"),
      join(home, ".local", "share", "opencode", "auth.json"),
      join(home, ".agents"),
      join(home, "Documents"),
      join(home, "Downloads"),
      join(home, ".npm"),
      join(home, "code"),
      ...readDeniedPaths
    ].filter((path, index, paths) => paths.indexOf(path) === index);
    return {
      env,
      command: stagedExecutable,
      cleanup,
      controlledConfigSha256: sha256(controlledConfig),
      executableSha256,
      readDeniedPaths,
      readDeniedPathsSha256: sha256(JSON.stringify(readDeniedPaths)),
      readDeniedPathCount: readDeniedPaths.length,
      diagnosticRedactionValues: collectCodexDiagnosticRedactionValues(opts.baseEnv, authText),
      ambientAuth,
      isolatedAuth,
      writeProbe,
      stagedWriteProbe: join(stagedExecutableDir, "write-proof"),
      deniedProbePaths
    };
  } catch (err) {
    await cleanup();
    throw err;
  }
}
function codexControlledConfig(opts) {
  const rules = /* @__PURE__ */ new Map();
  const broadDeniedPaths = minimalPathRoots([
    ...opts.deniedHostRoots.map((path) => resolve(path)),
    tmpdir(),
    opts.ambientTmp,
    "/proc",
    "/run/docker",
    "/run/containerd"
  ]);
  for (const path of broadDeniedPaths) {
    rules.set(path, "deny");
  }
  const workspaceRoot = dirname(opts.workspaceTemp);
  for (const path of opts.readDeniedPaths) {
    const alreadyDenied = broadDeniedPaths.some((root) => isSameOrDescendant(path, root));
    if (!alreadyDenied || isSameOrDescendant(path, workspaceRoot)) rules.set(path, "deny");
  }
  if (!rules.has(opts.workspaceTemp)) rules.set(opts.workspaceTemp, "write");
  if (!rules.has(opts.stagedExecutableDir)) rules.set(opts.stagedExecutableDir, "read");
  const filesystemRules = [...rules].sort(([a], [b]) => a.localeCompare(b)).map(([path, access2]) => `${JSON.stringify(path)} = ${JSON.stringify(access2)}`).join("\n");
  return `default_permissions = "${CODEX_PERMISSION_PROFILE}"
approval_policy = "never"
allow_login_shell = false
service_tier = "default"

[shell_environment_policy]
inherit = "core"
ignore_default_excludes = false
exclude = ["^CODEX_HOME$", "(?i).*TOKEN.*", "(?i).*KEY.*", "(?i).*SECRET.*", "(?i).*PASSWORD.*", "(?i).*CREDENTIAL.*", "(?i).*AUTH.*", "(?i).*COOKIE.*"]
set = { TMPDIR = ${JSON.stringify(opts.workspaceTemp)} }

[permissions.${CODEX_PERMISSION_PROFILE}.filesystem]
":minimal" = "read"
${filesystemRules}
":slash_tmp" = "deny"

[permissions.${CODEX_PERMISSION_PROFILE}.filesystem.":workspace_roots"]
"." = "write"
".git" = "deny"

[permissions.${CODEX_PERMISSION_PROFILE}.network]
enabled = false

[permissions.${CODEX_PERMISSION_PROFILE}.network.unix_sockets]
"/var/run/docker.sock" = "deny"
"/run/docker.sock" = "deny"
"/var/run/containerd/containerd.sock" = "deny"
"/run/containerd/containerd.sock" = "deny"
`;
}
function isSameOrDescendant(path, root) {
  const normalizedPath = resolve(path);
  const normalizedRoot = resolve(root);
  return normalizedPath === normalizedRoot || normalizedPath.startsWith(`${normalizedRoot}${sep}`);
}
function minimalPathRoots(paths) {
  const ordered = [...new Set(paths.map((path) => resolve(path)))].sort(
    (a, b) => a.length - b.length || a.localeCompare(b)
  );
  return ordered.filter(
    (path, index) => !ordered.slice(0, index).some((root) => isSameOrDescendant(path, root))
  );
}
async function normalizeReadDeniedPaths(paths) {
  if (!Array.isArray(paths)) {
    throw new Error("runLocalHarness: codexReadDeniedPaths must be an array of absolute paths");
  }
  const normalized = /* @__PURE__ */ new Set();
  for (const path of paths) {
    if (typeof path !== "string" || path.length === 0 || path.includes("\0") || !isAbsolute(path)) {
      throw new Error("runLocalHarness: codexReadDeniedPaths must contain absolute paths");
    }
    const absolute = resolve(path);
    normalized.add(absolute);
    try {
      normalized.add(await realpath(absolute));
    } catch (err) {
      if (err.code !== "ENOENT") throw err;
    }
  }
  return [...normalized].sort();
}
async function resolveCodexNativeExecutable(command, env) {
  const candidates = command.includes(sep) || isAbsolute(command) ? [resolve(command)] : (env.PATH ?? "").split(delimiter).filter(Boolean).map((entry) => join(entry, command));
  const seen = /* @__PURE__ */ new Set();
  for (const candidate of candidates) {
    let resolved;
    try {
      await access(candidate, constants2.X_OK);
      resolved = await realpath(candidate);
    } catch {
      continue;
    }
    if (seen.has(resolved)) continue;
    seen.add(resolved);
    if (await isStaticElfExecutable(resolved)) return resolved;
    const packageRoot = await findCodexPackageRoot(resolved);
    if (!packageRoot) continue;
    const bundled = await findBundledCodexExecutable(packageRoot);
    if (bundled) return bundled;
  }
  throw new Error(
    "runLocalHarness: could not resolve the native Codex executable from the requested command"
  );
}
async function findCodexPackageRoot(file) {
  let cursor = dirname(file);
  while (true) {
    try {
      const parsed = JSON.parse(await readFile(join(cursor, "package.json"), "utf8"));
      if (parsed.name === "@openai/codex") return cursor;
    } catch {
    }
    const parent = dirname(cursor);
    if (parent === cursor) return void 0;
    cursor = parent;
  }
}
async function findBundledCodexExecutable(packageRoot) {
  const target = linuxCodexTarget();
  const candidates = [
    join(
      packageRoot,
      "node_modules",
      "@openai",
      target.packageName,
      "vendor",
      target.triple,
      "bin",
      "codex"
    ),
    join(packageRoot, "vendor", target.triple, "bin", "codex")
  ];
  for (const executable of candidates) {
    if (await isStaticElfExecutable(executable)) return executable;
  }
  return void 0;
}
function linuxCodexTarget() {
  if (process.platform !== "linux") {
    throw new Error("runLocalHarness: reproducible Codex mode requires Linux");
  }
  if (process.arch === "x64") {
    return { packageName: "codex-linux-x64", triple: "x86_64-unknown-linux-musl" };
  }
  if (process.arch === "arm64") {
    return { packageName: "codex-linux-arm64", triple: "aarch64-unknown-linux-musl" };
  }
  throw new Error(`runLocalHarness: unsupported Linux architecture ${process.arch}`);
}
async function isStaticElfExecutable(path) {
  let handle;
  try {
    await access(path, constants2.X_OK);
    handle = await open2(path, "r");
    const header = Buffer.alloc(64);
    const { bytesRead } = await handle.read(header, 0, header.length, 0);
    if (bytesRead !== header.length || !header.subarray(0, 4).equals(Buffer.from([127, 69, 76, 70])) || header[4] !== 2 || header[5] !== 1) {
      return false;
    }
    const programHeaderOffset = Number(header.readBigUInt64LE(32));
    const programHeaderSize = header.readUInt16LE(54);
    const programHeaderCount = header.readUInt16LE(56);
    const expectedMachine = process.arch === "x64" ? 62 : process.arch === "arm64" ? 183 : -1;
    if (![2, 3].includes(header.readUInt16LE(16)) || header.readUInt16LE(18) !== expectedMachine || !Number.isSafeInteger(programHeaderOffset) || programHeaderOffset < 64 || programHeaderSize < 56 || programHeaderSize > 1024 || programHeaderCount === 0 || programHeaderCount > 1024) {
      return false;
    }
    const tableSize = programHeaderSize * programHeaderCount;
    const table = Buffer.alloc(tableSize);
    const tableRead = await handle.read(table, 0, tableSize, programHeaderOffset);
    if (tableRead.bytesRead !== tableSize) return false;
    for (let index = 0; index < programHeaderCount; index += 1) {
      const type = table.readUInt32LE(index * programHeaderSize);
      if (type === 3) return false;
    }
    return true;
  } catch {
    return false;
  } finally {
    await handle?.close();
  }
}
function sha256File(path) {
  return new Promise((resolveDigest, reject) => {
    const hash = createHash("sha256");
    const stream = createReadStream(path);
    stream.on("error", reject);
    stream.on("data", (chunk) => hash.update(chunk));
    stream.on("end", () => resolveDigest(hash.digest("hex")));
  });
}
function signalProcessTree(child, signal) {
  if (process.platform !== "win32" && typeof child.pid === "number") {
    try {
      process.kill(-child.pid, signal);
      return;
    } catch (err) {
      if (err.code === "ESRCH") return;
    }
  }
  try {
    child.kill(signal);
  } catch {
  }
}
function parseCodexTokenUsage(stdout) {
  const completed = [];
  for (const [index, line] of stdout.split(/\r?\n/).entries()) {
    if (line.trim().length === 0) continue;
    let event2;
    try {
      event2 = JSON.parse(line);
    } catch {
      throw new Error(`runLocalHarness: Codex JSONL line ${index + 1} is not valid JSON`);
    }
    if (isRecord(event2) && event2.type === "turn.completed") completed.push(event2);
  }
  if (completed.length !== 1) {
    throw new Error(
      `runLocalHarness: expected exactly one Codex turn.completed usage event, received ${completed.length}`
    );
  }
  const event = completed[0];
  if (!isRecord(event) || !isRecord(event.usage)) {
    throw new Error("runLocalHarness: Codex turn.completed event is missing usage");
  }
  const usage = event.usage;
  const inputTokens = naturalNumber(usage.input_tokens, "input_tokens");
  const cachedInputTokens = naturalNumber(usage.cached_input_tokens, "cached_input_tokens");
  const outputTokens = naturalNumber(usage.output_tokens, "output_tokens");
  const reasoningOutputTokens = naturalNumber(
    usage.reasoning_output_tokens,
    "reasoning_output_tokens"
  );
  if (cachedInputTokens > inputTokens) {
    throw new Error("runLocalHarness: Codex cached_input_tokens exceeds input_tokens");
  }
  if (reasoningOutputTokens > outputTokens) {
    throw new Error("runLocalHarness: Codex reasoning_output_tokens exceeds output_tokens");
  }
  return { inputTokens, cachedInputTokens, outputTokens, reasoningOutputTokens };
}
function isRecord(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}
function naturalNumber(value, field) {
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
    throw new Error(`runLocalHarness: Codex usage.${field} must be a non-negative safe integer`);
  }
  return value;
}

export {
  CodexExecutionDiagnosticError,
  harnessInvocation,
  runLocalHarness,
  parseCodexTokenUsage
};
//# sourceMappingURL=chunk-EP6RVHMX.js.map