import { AnalystFinding } from '@tangle-network/agent-eval';
import { L as LocalHarness, r as runLocalHarness } from './local-harness-sI0S_XNA.js';
import { LabeledScenarioStore, WorktreeAdapter, SurfaceProposer } from '@tangle-network/agent-eval/campaign';

/**
 *
 * `improvementDriver` — the ONE reflective/agentic improvement proposer for
 * agent-eval's improvement loop. It implements `SurfaceProposer` and owns
 * the candidate lifecycle (worktree create → generate → finalize/discard,
 * × populationSize); it delegates the only thing that genuinely varies — HOW
 * a candidate change is produced — to a pluggable `CandidateGenerator`.
 *
 * There is no separate "analyst driver" vs "autoresearch driver": those are
 * the SAME driver at two settings of a dial.
 *   - cheap reflective path  → `reflectiveGenerator` (shots=1, no sandbox;
 *                              applies pre-drafted patches)
 *   - full agentic path      → `agenticGenerator` (shots=N, multi-shot
 *                              verify-in-session loop; an agent reads code +
 *                              report, edits, and re-tries on verifier failure)
 * Both emit changes into a worktree the driver finalizes into a
 * `CodeSurface{ worktreeRef }` the loop measures on the holdout. See
 * agent-eval's `docs/design/self-improvement-engine.md`.
 *
 * @experimental
 */

/** The byte-producing seam — the ONE thing that differs between the cheap
 *  reflective path and the full agentic path. A generator makes (uncommitted)
 *  changes inside `worktreePath`; the driver commits them via the worktree
 *  adapter's `finalize`. */
interface CandidateGenerator {
    kind: string;
    generate(args: {
        /** The candidate worktree — a fresh checkout of baseRef. Write changes here. */
        worktreePath: string;
        /** Phase-2 research report (analyst findings + diff), opaque. */
        report: unknown;
        /** Findings resolved from the report or the loop context. */
        findings: AnalystFinding[];
        /** Handle to all captured data, to ground the change. */
        dataset?: LabeledScenarioStore;
        /** DEPTH: max iterations the generator may take (agentic uses this; the
         *  reflective generator ignores it). */
        maxShots: number;
        signal: AbortSignal;
    }): Promise<{
        applied: boolean;
        summary: string;
    }>;
}
interface ImprovementDriverOptions {
    worktree: WorktreeAdapter;
    generator: CandidateGenerator;
    /** Base ref candidate worktrees fork from. Default `main`. */
    baseRef?: string;
}
/** The one reflective/agentic improvement proposer (`SurfaceProposer`): owns the candidate worktree lifecycle and delegates HOW a change is produced to a pluggable `CandidateGenerator`. */
declare function improvementDriver(opts: ImprovementDriverOptions): SurfaceProposer<AnalystFinding>;

/**
 *
 * `agenticGenerator` — the full-agentic `CandidateGenerator`: the
 * `shots=N, sandbox=on` setting of the one `improvementDriver`. It runs a real
 * coding harness (claude / codex / opencode) inside the candidate worktree the
 * driver already created, letting the agent read the codebase + the research
 * report and make the change in place. The driver then commits the worktree
 * into a `CodeSurface`.
 *
 * Mechanism: identical to the proven Phase-2.8 in-process executor — spawn the
 * harness as a subprocess with `cwd` = the worktree, on the same filesystem,
 * so edits land in place (no sandbox-mount round-trip). `runLocalHarness` is
 * the verified primitive. The OUTER sandbox is the improvement loop's own
 * execution context; the generator does not nest a second sandbox per
 * candidate (which would reintroduce a host↔sandbox worktree-transport
 * problem that does not need solving here).
 *
 * `maxShots` is the DEPTH dial — a multi-shot verify-in-session loop, NOT the
 * kernel `runLoop`. Each shot runs one full harness session in the (persistent)
 * worktree; between shots the loop refines based on what the last shot produced:
 *   - empty tree   → "you changed nothing, make the edits" → retry
 *   - dirty + `verify` fails → feed the verifier's failure into the next shot
 *       (the worktree persists, so the harness RESUMES atop its own failing
 *       edits with the error in hand — no `--resume` session plumbing needed,
 *       and harness-agnostic across claude/codex/opencode)
 *   - dirty + `verify` ok (or no verifier configured) → return the candidate
 * A candidate that never verifies within `maxShots` is discarded (`applied:
 * false`), never shipped — if you configured a verifier, a non-passing tree is
 * not a candidate. With no verifier the legacy behavior holds: first dirty shot
 * is the candidate.
 *
 * @experimental
 */

/** Outcome of verifying a candidate worktree. `feedback` (compiler errors,
 *  failing test output) is fed into the next shot when `ok` is false. */
interface VerifyResult {
    ok: boolean;
    feedback?: string;
}
/** Verifies the edited worktree. Sync or async; throws only on a setup fault
 *  (a candidate that fails verification returns `{ok:false}`, it does not
 *  throw). */
type Verifier = (worktreePath: string) => Promise<VerifyResult> | VerifyResult;
interface AgenticGeneratorOptions {
    /** Local coding harness to run in the worktree. Default `claude`. */
    harness?: LocalHarness;
    /** Per-shot wall-clock timeout (ms). Default = `runLocalHarness` default (5m). */
    timeoutMs?: number;
    /** Build the harness task prompt from the report + findings. Override for
     *  domain phrasing; the default turns findings into a concrete coder task. */
    buildPrompt?: (args: {
        report: unknown;
        findings: AnalystFinding[];
    }) => string;
    /** Verify the worktree after each dirtying shot. When set, a candidate that
     *  fails verification is NOT returned — the failure feeds the next shot
     *  (verify-in-session), up to `maxShots`; a candidate that never verifies is
     *  discarded (`applied:false`), never shipped. Omitted ⇒ legacy behavior:
     *  the first dirty shot is the candidate. See `commandVerifier`. */
    verify?: Verifier;
    /** Test seam — inject the harness runner (defaults to `runLocalHarness`). */
    runHarness?: typeof runLocalHarness;
    /** Test seam — inject the worktree-dirty check (defaults to `git status`). */
    isDirty?: (worktreePath: string) => boolean;
}
/** Full-agentic `CandidateGenerator` (the `shots=N, sandbox=on` setting): run a real coding harness inside the candidate worktree so the agent makes the change in place. */
declare function agenticGenerator(opts?: AgenticGeneratorOptions): CandidateGenerator;
/** A `Verifier` that runs a command in the worktree: exit 0 ⇒ ok, any other
 *  exit ⇒ failed with stdout+stderr as feedback. The common case — verify by
 *  `tsc --noEmit`, `pnpm build`, or a test command. A timeout is treated as a
 *  FAILED candidate (a change that hangs the build is a bad change); a missing
 *  binary or spawn fault throws (a setup bug, not a failed candidate — no
 *  silent fallback). */
declare function commandVerifier(command: string, args?: string[], timeoutMs?: number): Verifier;

/**
 * `mcpServeVerifier` — the intrinsic verifier for a built MCP server: the
 * boot-and-probe checker named in docs/artifact-lifecycle-frontier.md. A
 * generated MCP server is only a candidate if it actually *serves* — so this
 * boots it over stdio (the default local MCP transport) and runs the real
 * handshake: `initialize` → `notifications/initialized` → `tools/list`, and
 * asserts the server answers with at least `minTools` tools.
 *
 * Outcomes follow the `Verifier` contract: a server that fails to start, exits
 * early, errors the handshake, times out, or exposes no tools is a FAILED
 * candidate (`{ok:false}`, fed back into the next generation shot); a missing
 * start binary or spawn fault THROWS (a setup bug, never a silent fallback).
 *
 * Protocol matches the runtime's own stdio MCP server (src/mcp/server.ts):
 * newline-delimited JSON-RPC 2.0, protocol version 2024-11-05.
 */

interface McpServeSpec {
    /** Command that starts the built MCP server in the worktree (stdio transport). */
    command: string;
    args?: string[];
    /** Extra env for the server process (merged over `process.env`). */
    env?: Record<string, string>;
    /** Handshake timeout (ms). Default 30s. */
    timeoutMs?: number;
    /** Minimum tools the server must expose to pass. Default 1. */
    minTools?: number;
}
/** Build a `Verifier` that boots a generated MCP server over stdio and checks it exposes tools. */
declare function mcpServeVerifier(spec: McpServeSpec): Verifier;

export { type AgenticGeneratorOptions as A, type CandidateGenerator as C, type ImprovementDriverOptions as I, type McpServeSpec as M, type Verifier as V, type VerifyResult as a, agenticGenerator as b, commandVerifier as c, improvementDriver as i, mcpServeVerifier as m };
