import {
  harnessInvocation,
  runLocalHarness
} from "./chunk-EP6RVHMX.js";

// src/improvement/agentic-generator.ts
import { spawnSync } from "child_process";
import { createHash } from "crypto";
import { existsSync, readFileSync, rmSync } from "fs";
import { join, resolve, sep } from "path";
import {
  applyWorkspacePlan,
  materializeProfile
} from "@tangle-network/agent-profile-materialize";
var RAW_TRACE_ANALYST_ID = "raw-trace-distiller";
var RAW_TRACE_AREA = "raw-trace-context";
var RAW_TRACE_DIAGNOSIS_PATH = ".improve/raw-trace-diagnosis.md";
var AGENTIC_PROFILE_RESOURCE_ROOT = ".agent-runtime-profile-resources";
function agenticGenerator(opts = {}) {
  const harness = opts.harness ?? "claude";
  if (opts.codexReproducible && harness !== "codex") {
    throw new Error("agenticGenerator: codexReproducible requires harness 'codex'");
  }
  if (opts.codexReproducible && !opts.profile) {
    throw new Error("agenticGenerator: codexReproducible requires an explicit author profile");
  }
  if (opts.codexReadDeniedPaths && !opts.codexReproducible) {
    throw new Error("agenticGenerator: codexReadDeniedPaths requires codexReproducible");
  }
  if (opts.maximumCharge && !opts.codexReproducible) {
    throw new Error("agenticGenerator: maximumCharge requires codexReproducible");
  }
  const profileResourcePlan = opts.codexReproducible ? authorProfileResourcePlan(opts.profile) : null;
  const buildPrompt = opts.buildPrompt ?? defaultBuildPrompt;
  const run = opts.runHarness ?? runLocalHarness;
  const dirty = opts.isDirty ?? worktreeDirty;
  const verify = opts.verify;
  return {
    kind: `agentic:${harness}`,
    // The seed repo + (in rawTraceContext mode) the raw-trace filesystem context
    // are the change signal — an agentic coder proposes from them even when the
    // distiller yielded zero findings. Without this, the improvementDriver's
    // empty-findings guard short-circuits and generates ZERO candidates on the
    // first (and, for a single-generation run, only) proposal round.
    proposesWithoutFindings: true,
    async generate({
      worktreePath,
      report,
      findings,
      maxShots,
      signal,
      generation,
      candidateIndex,
      costLedger,
      costPhase
    }) {
      if (opts.codexReproducible && !costLedger) {
        throw new Error(
          "agenticGenerator: reproducible Codex requires the run-wide CostLedger supplied by agent-eval 0.117+"
        );
      }
      const basePrompt = appendProfileResourcePaths(
        buildPrompt({ report, findings }),
        profileResourcePlan
      );
      const needsRawTraceEvidence = requiresRawTraceEvidence(findings);
      const shots = Math.max(1, maxShots);
      let attemptNote = "";
      for (let shot = 0; shot < shots; shot++) {
        if (signal.aborted) break;
        const taskPrompt = attemptNote ? `${basePrompt}

${attemptNote}` : basePrompt;
        const invocation = opts.profile ? harnessInvocation(harness, opts.profile, taskPrompt, {
          dangerouslySkipPermissions: harness === "claude",
          ...opts.codexReproducible ? { codexReproducible: true } : {}
        }) : void 0;
        const exactPrompt = invocation?.prompt ?? taskPrompt;
        const readDeniedPaths = typeof opts.codexReadDeniedPaths === "function" ? opts.codexReadDeniedPaths(worktreePath) : opts.codexReadDeniedPaths;
        const startedAt = /* @__PURE__ */ new Date();
        let harnessResult = null;
        let profileWorkspaceReceipt = null;
        let costReceipt = null;
        let costCallId = null;
        let shotError = null;
        try {
          const execute = async (executionSignal) => {
            harnessResult = await withAuthorProfileResources(
              profileResourcePlan,
              worktreePath,
              async (receipt) => {
                profileWorkspaceReceipt = receipt;
                const result2 = await run({
                  harness,
                  cwd: worktreePath,
                  taskPrompt,
                  ...invocation ? { invocation: { command: invocation.command, args: invocation.args } } : {},
                  // The candidate worktree is isolated and must be editable without an
                  // interactive permission prompt. Other runLocalHarness callers remain
                  // permission-safe by default.
                  dangerouslySkipPermissions: harness === "claude",
                  ...opts.codexReproducible ? { codexReproducible: true } : {},
                  ...readDeniedPaths ? { codexReadDeniedPaths: readDeniedPaths } : {},
                  timeoutMs: opts.timeoutMs,
                  signal: executionSignal
                });
                harnessResult = result2;
                return result2;
              }
            );
            const failure = shotFailure(harnessResult, exactPrompt, opts.codexReproducible === true);
            if (failure) throw failure;
            return harnessResult;
          };
          if (opts.codexReproducible) {
            const ledger = costLedger;
            const model = opts.profile?.model?.default;
            if (!model) {
              throw new Error("agenticGenerator: reproducible Codex requires profile.model.default");
            }
            const paid = await ledger.runPaidCall({
              channel: "driver",
              phase: costPhase ?? "search.proposal",
              actor: `agentic-generator:${harness}`,
              model,
              tags: {
                generation: String(generation ?? -1),
                candidateIndex: String(candidateIndex ?? -1),
                shot: String(shot + 1)
              },
              signal,
              ...opts.maximumCharge ? { maximumCharge: opts.maximumCharge } : {},
              execute,
              receipt: (result2) => costReceiptFromHarness(result2, model),
              receiptFromError: () => harnessResult?.usage ? costReceiptFromHarness(harnessResult, model) : void 0
            });
            costCallId = paid.callId ?? null;
            costReceipt = paid.receipt ?? null;
            if (!paid.succeeded) throw paid.error;
            harnessResult = paid.value;
          } else {
            harnessResult = await execute(signal);
          }
        } catch (cause) {
          shotError = cause instanceof Error ? cause : new Error(String(cause));
        }
        await emitShotReceipt(
          opts.onShotCompleted,
          shotReceipt({
            generation,
            candidateIndex,
            shot,
            maxShots: shots,
            harness,
            profile: opts.profile,
            prompt: exactPrompt,
            startedAt,
            completedAt: /* @__PURE__ */ new Date(),
            result: harnessResult,
            profileWorkspaceReceipt,
            costCallId,
            costReceipt,
            error: shotError
          }),
          shotError
        );
        if (!harnessResult) {
          throw new Error("agenticGenerator: author shot completed without a harness result");
        }
        if (!dirty(worktreePath)) {
          attemptNote = EMPTY_TREE_NOTE;
          continue;
        }
        if (needsRawTraceEvidence) {
          const problem = rawTraceEvidenceProblem(worktreePath, findings);
          if (problem) {
            attemptNote = problem;
            continue;
          }
        }
        if (!verify) {
          return { applied: true, summary: summarize(findings) };
        }
        const result = await verify(worktreePath);
        if (result.ok) {
          return { applied: true, summary: summarize(findings) };
        }
        attemptNote = failureNote(result.feedback);
      }
      return { applied: false, summary: "" };
    }
  };
}
function authorProfileResourcePlan(profile) {
  const resources = profile.resources;
  if (!resources) return null;
  const unsupportedKinds = [
    resources.tools?.length ? "tools" : null,
    resources.skills?.length ? "skills" : null,
    resources.agents?.length ? "agents" : null
  ].filter((kind) => kind !== null);
  if (unsupportedKinds.length > 0) {
    throw new Error(
      `agenticGenerator: reproducible Codex author resources support files only; unsupported: ${unsupportedKinds.join(", ")}`
    );
  }
  if (!resources.files || resources.files.length === 0) return null;
  const plan = materializeProfile(
    {
      name: profile.name,
      resources: { files: resources.files }
    },
    "codex"
  );
  if (plan.unsupported.length > 0) {
    throw new Error(
      `agenticGenerator: author profile files could not be materialized: ${plan.unsupported.map((item) => item.reason).join("; ")}`
    );
  }
  if (Object.keys(plan.env).length > 0 || plan.flags.length > 0) {
    throw new Error(
      "agenticGenerator: generic author profile files unexpectedly changed spawn values"
    );
  }
  const virtualRoot = resolve("/", AGENTIC_PROFILE_RESOURCE_ROOT);
  const seen = /* @__PURE__ */ new Set();
  for (const file of plan.files) {
    const target = resolve("/", file.relPath);
    if (!target.startsWith(`${virtualRoot}${sep}`)) {
      throw new Error(
        `agenticGenerator: author profile file must be below ${AGENTIC_PROFILE_RESOURCE_ROOT}: ${file.relPath}`
      );
    }
    if (seen.has(target)) {
      throw new Error(`agenticGenerator: duplicate author profile file path: ${file.relPath}`);
    }
    seen.add(target);
  }
  return plan;
}
function appendProfileResourcePaths(prompt, plan) {
  if (!plan) return prompt;
  return [
    prompt,
    "",
    "Profile resource files available for this shot:",
    ...plan.files.map((file) => `- ${file.relPath}`)
  ].join("\n");
}
async function withAuthorProfileResources(plan, worktreePath, run) {
  if (!plan) return run(null);
  const rootPath = resolve(worktreePath, AGENTIC_PROFILE_RESOURCE_ROOT);
  if (existsSync(rootPath)) {
    throw new Error(
      `agenticGenerator: ephemeral author profile root already exists: ${AGENTIC_PROFILE_RESOURCE_ROOT}`
    );
  }
  let value;
  let primaryError;
  try {
    const receipt = applyWorkspacePlan(plan, worktreePath);
    value = await run(receipt);
  } catch (cause) {
    primaryError = cause;
  }
  let cleanupError;
  try {
    rmSync(rootPath, { recursive: true, force: true });
    if (existsSync(rootPath)) {
      throw new Error(
        `agenticGenerator: ephemeral author profile root survived cleanup: ${AGENTIC_PROFILE_RESOURCE_ROOT}`
      );
    }
  } catch (cause) {
    cleanupError = cause;
  }
  if (primaryError !== void 0 && cleanupError !== void 0) {
    throw new AggregateError(
      [primaryError, cleanupError],
      "agenticGenerator: author shot and profile resource cleanup both failed"
    );
  }
  if (primaryError !== void 0) throw primaryError;
  if (cleanupError !== void 0) throw cleanupError;
  return value;
}
async function emitShotReceipt(callback, receipt, primaryError) {
  try {
    await callback?.(receipt);
  } catch (callbackError) {
    if (primaryError !== null) {
      throw new AggregateError(
        [primaryError, callbackError],
        "agenticGenerator: author shot failed and its receipt could not be persisted"
      );
    }
    throw callbackError;
  }
  if (primaryError !== null) throw primaryError;
}
function shotReceipt(input) {
  const error = input.error ? {
    name: input.error instanceof Error ? input.error.name : "Error",
    message: input.error instanceof Error ? input.error.message : String(input.error)
  } : null;
  const result = input.result;
  const costBasis = costBasisFor(input.costReceipt);
  return {
    schemaVersion: 1,
    generation: input.generation ?? null,
    candidateIndex: input.candidateIndex ?? null,
    shot: input.shot + 1,
    maxShots: input.maxShots,
    harness: input.harness,
    model: input.profile?.model?.default ?? null,
    reasoningEffort: input.profile?.model?.reasoningEffort ?? null,
    promptSha256: sha256(input.prompt),
    startedAt: input.startedAt.toISOString(),
    completedAt: input.completedAt.toISOString(),
    durationMs: result?.durationMs ?? input.completedAt.getTime() - input.startedAt.getTime(),
    exitCode: result?.exitCode ?? null,
    timedOut: result?.timedOut ?? false,
    killedBySignal: result?.killedBySignal ?? null,
    stdoutBytes: result ? Buffer.byteLength(result.stdout) : null,
    stdoutSha256: result ? sha256(result.stdout) : null,
    stderrBytes: result ? Buffer.byteLength(result.stderr) : null,
    stderrSha256: result ? sha256(result.stderr) : null,
    usage: result?.usage ? { ...result.usage } : null,
    profileWorkspacePlanDigest: input.profileWorkspaceReceipt?.workspacePlanDigest ?? null,
    profileWorkspaceFileCount: input.profileWorkspaceReceipt?.written.length ?? 0,
    costCallId: input.costCallId,
    costBasis,
    costUsd: costBasis === "unknown" ? null : input.costReceipt?.costUsd ?? null,
    costUsdKnown: costBasis === "provider-reported",
    evidence: result?.evidence ? {
      ...result.evidence,
      readDeniedPaths: [...result.evidence.readDeniedPaths],
      policy: { ...result.evidence.policy }
    } : null,
    error
  };
}
function costBasisFor(receipt) {
  if (receipt === null || receipt.costUnknown) return "unknown";
  return receipt.actualCostUsd === void 0 ? "estimated-pricing" : "provider-reported";
}
function shotFailure(result, exactPrompt, codexReproducible) {
  if (result.timedOut) {
    return new Error("agenticGenerator: author shot timed out");
  }
  if (result.killedBySignal) {
    return new Error(`agenticGenerator: author shot was killed by ${result.killedBySignal}`);
  }
  if (result.exitCode !== 0) {
    return new Error(`agenticGenerator: author shot exited with code ${String(result.exitCode)}`);
  }
  if (!codexReproducible) return null;
  if (!result.usage || !result.evidence) {
    return new Error(
      "agenticGenerator: reproducible Codex shot completed without usage or execution evidence"
    );
  }
  const expectedPromptSha256 = sha256(exactPrompt).slice("sha256:".length);
  if (result.evidence.requestedPromptSha256 !== expectedPromptSha256) {
    return new Error(
      "agenticGenerator: reproducible Codex prompt evidence does not match the exact authored prompt"
    );
  }
  return null;
}
function costReceiptFromHarness(result, model) {
  if (!result.usage) {
    throw new Error("agenticGenerator: author shot did not report terminal token usage");
  }
  return {
    model,
    inputTokens: result.usage.inputTokens - result.usage.cachedInputTokens,
    outputTokens: result.usage.outputTokens,
    ...result.usage.cachedInputTokens > 0 ? { cachedTokens: result.usage.cachedInputTokens } : {}
  };
}
function sha256(value) {
  return `sha256:${createHash("sha256").update(value).digest("hex")}`;
}
function defaultBuildPrompt(args) {
  const lines = [
    "You are improving this codebase based on an evaluation analysis.",
    "Make the smallest set of edits that addresses the findings below, then stop.",
    "Do not change unrelated code. Do not commit \u2014 leave changes in the working tree.",
    "",
    "Findings:"
  ];
  for (const f of args.findings) {
    const where = f.subject ? ` [${f.subject}]` : "";
    lines.push(`- (${f.severity})${where} ${f.claim}`);
    if (f.recommended_action) lines.push(`    \u2192 ${f.recommended_action}`);
  }
  if (requiresRawTraceEvidence(args.findings)) {
    lines.push(
      "",
      "Raw trace evidence requirement:",
      `- Inspect at least one raw trace path named above before editing.`,
      `- Write ${RAW_TRACE_DIAGNOSIS_PATH} in this worktree.`,
      "- Include the exact trace path(s) inspected, the failure mechanism, and the code change made.",
      "- A candidate without this file, or with only this file changed, is discarded."
    );
  }
  return lines.join("\n");
}
var EMPTY_TREE_NOTE = "NOTE: your previous attempt left the working tree unchanged. Make the concrete file edits now.";
function failureNote(feedback) {
  const detail = feedback?.trim();
  return [
    "NOTE: your edits are in the working tree but verification FAILED.",
    "Fix the problem in place \u2014 build on your existing edits, do not revert them.",
    detail ? `Verifier output:
${truncate(detail, 4e3)}` : "No verifier detail was captured."
  ].join("\n");
}
function rawTraceEvidenceProblem(worktreePath, findings) {
  const changedPaths = worktreeChangedPaths(worktreePath);
  const substantive = changedPaths.filter((path) => path !== RAW_TRACE_DIAGNOSIS_PATH);
  if (substantive.length === 0) {
    return [
      `NOTE: raw-trace mode requires a real code/config edit in addition to ${RAW_TRACE_DIAGNOSIS_PATH}.`,
      "Your previous attempt only changed the diagnosis artifact. Inspect the cited traces and make the causal code change."
    ].join("\n");
  }
  const diagnosisPath = join(worktreePath, RAW_TRACE_DIAGNOSIS_PATH);
  if (!existsSync(diagnosisPath)) {
    return [
      `NOTE: raw-trace mode requires ${RAW_TRACE_DIAGNOSIS_PATH}.`,
      "Before retrying, inspect at least one cited spans.jsonl/cached-result.json/artifact path, then write the diagnosis file with the exact path, failure mechanism, and code change."
    ].join("\n");
  }
  const body = readFileSync(diagnosisPath, "utf8");
  const evidencePaths = traceEvidencePaths(findings);
  if (evidencePaths.length > 0 && !evidencePaths.some((path) => body.includes(path))) {
    return [
      `${RAW_TRACE_DIAGNOSIS_PATH} exists, but it does not cite any exact raw trace path from the findings.`,
      `Cite at least one of these inspected paths exactly: ${evidencePaths.slice(0, 5).join(", ")}`
    ].join("\n");
  }
  return null;
}
function requiresRawTraceEvidence(findings) {
  return findings.some((finding) => {
    const f = finding;
    return f.analyst_id === RAW_TRACE_ANALYST_ID || f.area === RAW_TRACE_AREA;
  });
}
function traceEvidencePaths(findings) {
  const out = [];
  for (const finding of findings) {
    const refs = finding.evidence_refs;
    if (!Array.isArray(refs)) continue;
    for (const ref of refs) {
      if (!ref || typeof ref !== "object") continue;
      const uri = ref.uri;
      if (typeof uri === "string" && uri.length > 0) out.push(uri);
    }
  }
  return [...new Set(out)];
}
function commandVerifier(command, args = [], timeoutMs = 3e5) {
  return (worktreePath) => {
    const result = spawnSync(command, args, {
      cwd: worktreePath,
      encoding: "utf-8",
      timeout: timeoutMs
    });
    if (result.signal) {
      return {
        ok: false,
        feedback: `verifier '${command}' killed by ${result.signal} (likely timeout after ${timeoutMs}ms)`
      };
    }
    if (result.error) {
      const code = result.error.code;
      if (code === "ENOENT") {
        throw new Error(
          `commandVerifier: '${command}' not found in PATH (setup bug, not a failed candidate)`
        );
      }
      throw new Error(`commandVerifier: '${command}' failed to spawn: ${result.error.message}`);
    }
    if (result.status === 0) return { ok: true };
    const out = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
    return { ok: false, feedback: out.length > 0 ? out : `exit ${result.status}` };
  };
}
function summarize(findings) {
  if (findings.length === 0) return "agentic improvement";
  if (findings.length === 1) return `agentic: ${truncate(findings[0].claim, 64)}`;
  return `agentic: ${findings.length} findings addressed`;
}
function truncate(s, n) {
  return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
}
function worktreeDirty(worktreePath) {
  return worktreeChangedPaths(worktreePath).length > 0;
}
function worktreeChangedPaths(worktreePath) {
  const result = spawnSync("git", ["status", "--porcelain", "--untracked-files=all"], {
    cwd: worktreePath,
    encoding: "utf-8"
  });
  if (result.error) {
    throw new Error(
      `agenticGenerator: git status failed to spawn in ${worktreePath}: ${result.error.message}`
    );
  }
  if (result.status !== 0) {
    throw new Error(
      `agenticGenerator: git status exited ${result.status} in ${worktreePath}: ${result.stderr.trim()}`
    );
  }
  return result.stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => line.slice(3).trim());
}

export {
  AGENTIC_PROFILE_RESOURCE_ROOT,
  agenticGenerator,
  commandVerifier
};
//# sourceMappingURL=chunk-GHXW56PO.js.map