import {
  agenticGenerator,
  commandVerifier,
  mcpBuildPrompt,
  mcpServeVerifier,
  toolBuildPrompt
} from "./chunk-VNOOH22O.js";
import "./chunk-7LO5GMAO.js";
import {
  ValidationError
} from "./chunk-YEJR7IXO.js";
import "./chunk-DGUM43GV.js";

// src/lifecycle/apply.ts
function applyArtifact(base, artifact) {
  switch (artifact.kind) {
    case "prompt": {
      const payload = artifact.payload;
      const instructions = [...base.prompt?.instructions ?? [], payload.instruction];
      return { ...base, prompt: { ...base.prompt, instructions } };
    }
    case "skill": {
      const payload = artifact.payload;
      const skills = [...base.resources?.skills ?? [], payload.resource];
      return { ...base, resources: { ...base.resources, skills } };
    }
    case "tool": {
      const payload = artifact.payload;
      const key = keyOf(artifact);
      return { ...base, tools: { ...base.tools, [key]: payload.enabled } };
    }
    case "mcp": {
      const payload = artifact.payload;
      const key = keyOf(artifact);
      return { ...base, mcp: { ...base.mcp, [key]: payload.server } };
    }
    case "hook": {
      const payload = artifact.payload;
      const existing = base.hooks?.[payload.event] ?? [];
      return {
        ...base,
        hooks: { ...base.hooks, [payload.event]: [...existing, ...payload.commands] }
      };
    }
    case "subagent": {
      const payload = artifact.payload;
      const key = keyOf(artifact);
      return { ...base, subagents: { ...base.subagents, [key]: payload.profile } };
    }
  }
}
function applyArtifacts(base, artifacts) {
  return artifacts.reduce((profile, artifact) => applyArtifact(profile, artifact), base);
}
function keyOf(artifact) {
  return artifact.key ?? artifact.id;
}

// src/lifecycle/compose.ts
function composeProfile(registry, base, opts = {}) {
  const eligible = [];
  for (const artifact of registry.list({ status: "active", kind: opts.kind })) {
    const lift = registry.liftOf(artifact.id);
    if (lift === void 0) continue;
    eligible.push({ artifact, lift });
  }
  eligible.sort((a, b) => b.lift - a.lift);
  const k = opts.k ?? eligible.length;
  const selected = eligible.slice(0, Math.max(0, k)).map((e) => e.artifact);
  return applyArtifacts(base, selected);
}

// src/lifecycle/marginal-lift.ts
async function measureMarginalLift(opts) {
  const { baseline, candidate, evalRunner, baselineResult, signal } = opts;
  const withoutArtifact = baselineResult ?? await evalRunner(baseline, signal);
  const withProfile = applyArtifact(baseline, candidate);
  const withArtifact = await evalRunner(withProfile, signal);
  return {
    artifactId: candidate.id,
    withArtifact,
    withoutArtifact,
    scoreDelta: withArtifact.composite - withoutArtifact.composite,
    costDelta: withArtifact.costUsd - withoutArtifact.costUsd
  };
}

// src/lifecycle/dedupe.ts
async function dedupeArtifacts(opts) {
  const tolerance = opts.tolerance ?? 0;
  if (!Number.isFinite(tolerance) || tolerance < 0) {
    throw new ValidationError(
      `dedupeArtifacts: tolerance must be a finite, non-negative number (got ${tolerance})`
    );
  }
  const active = opts.registry.list({ status: "active", kind: opts.kind });
  const baselineResult = opts.baselineResult ?? await opts.evalRunner(opts.baseline, opts.signal);
  const liftCache = /* @__PURE__ */ new Map();
  const liftOf = async (artifact) => {
    const cached = liftCache.get(artifact.id);
    if (cached !== void 0) return cached;
    const lift = await measureMarginalLift({
      baseline: opts.baseline,
      candidate: artifact,
      evalRunner: opts.evalRunner,
      baselineResult,
      signal: opts.signal
    });
    liftCache.set(artifact.id, lift.scoreDelta);
    return lift.scoreDelta;
  };
  const retired = /* @__PURE__ */ new Set();
  const checks = [];
  for (let i = 0; i < active.length; i += 1) {
    if (opts.signal?.aborted) break;
    const a = active[i];
    if (retired.has(a.id)) continue;
    for (let j = i + 1; j < active.length; j += 1) {
      if (opts.signal?.aborted) break;
      const b = active[j];
      if (retired.has(b.id)) continue;
      const liftA = await liftOf(a);
      const liftB = await liftOf(b);
      const combined = await opts.evalRunner(applyArtifacts(opts.baseline, [a, b]), opts.signal);
      const combinedLift = combined.composite - baselineResult.composite;
      const stackGap = combinedLift - (liftA + liftB);
      const redundant = stackGap < -tolerance;
      const check = {
        pair: [a.id, b.id],
        liftA,
        liftB,
        combinedLift,
        stackGap,
        redundant
      };
      if (redundant) {
        const weaker = liftA < liftB ? a : b;
        const reason = `lifts do not stack: combined \u0394=${combinedLift.toFixed(4)} < ${a.id} (\u0394=${liftA.toFixed(4)}) + ${b.id} (\u0394=${liftB.toFixed(4)}) \u2212 tol ${tolerance} \u2014 redundant with ${(weaker.id === a.id ? b : a).id}`;
        opts.registry.retire(weaker.id, reason);
        retired.add(weaker.id);
        check.retiredId = weaker.id;
        checks.push(check);
        if (weaker.id === a.id) break;
      } else {
        checks.push(check);
      }
    }
  }
  return { checks, retired: [...retired], baselineResult };
}

// src/lifecycle/drift-watch.ts
async function driftWatch(opts) {
  if (opts.maxRelativeDecay !== void 0) {
    if (!Number.isFinite(opts.maxRelativeDecay) || opts.maxRelativeDecay < 0) {
      throw new ValidationError(
        `driftWatch: maxRelativeDecay must be a finite, non-negative fraction (got ${opts.maxRelativeDecay})`
      );
    }
  }
  const minLift = opts.minLift ?? 0;
  if (!Number.isFinite(minLift)) {
    throw new ValidationError(`driftWatch: minLift must be a finite number (got ${minLift})`);
  }
  const active = opts.registry.list({ status: "active", kind: opts.kind });
  const baselineResult = opts.baselineResult ?? await opts.evalRunner(opts.baseline, opts.signal);
  const checks = [];
  const demoted = [];
  for (const artifact of active) {
    if (opts.signal?.aborted) break;
    const priorLift = opts.registry.liftOf(artifact.id);
    const lift = await measureMarginalLift({
      baseline: opts.baseline,
      candidate: artifact,
      evalRunner: opts.evalRunner,
      baselineResult,
      signal: opts.signal
    });
    const currentLift = lift.scoreDelta;
    const decision = keepDecision(currentLift, priorLift, minLift, opts.maxRelativeDecay);
    if (decision.keep) {
      const refreshed = opts.registry.promoteWithLift(artifact.id, currentLift);
      checks.push({
        artifact: refreshed,
        priorLift,
        currentLift,
        demoted: false,
        reason: decision.reason
      });
    } else {
      const decayed = opts.registry.demote(artifact.id, decision.reason, currentLift);
      demoted.push(artifact.id);
      checks.push({
        artifact: decayed,
        priorLift,
        currentLift,
        demoted: true,
        reason: decision.reason
      });
    }
  }
  return { checks, demoted, baselineResult };
}
function keepDecision(currentLift, priorLift, minLift, maxRelativeDecay) {
  if (!(currentLift > minLift)) {
    return {
      keep: false,
      reason: `re-measured lift \u0394=${currentLift.toFixed(4)} \u2264 keep-bar ${minLift} \u2014 decayed`
    };
  }
  if (maxRelativeDecay !== void 0 && priorLift !== void 0 && priorLift > 0) {
    const floor = priorLift * (1 - maxRelativeDecay);
    if (currentLift < floor) {
      return {
        keep: false,
        reason: `re-measured lift \u0394=${currentLift.toFixed(4)} fell below ${(maxRelativeDecay * 100).toFixed(0)}%-decay floor ${floor.toFixed(4)} of prior ${priorLift.toFixed(4)} \u2014 decayed`
      };
    }
  }
  return {
    keep: true,
    reason: `re-measured lift \u0394=${currentLift.toFixed(4)} clears the keep-bar \u2014 still active`
  };
}

// src/lifecycle/gate.ts
import { HeldOutGate } from "@tangle-network/agent-eval";
function thresholdPromotionGate(minDelta = 0) {
  return {
    kind: `threshold:${minDelta}`,
    decide(lift) {
      if (lift.scoreDelta > minDelta) {
        return {
          promote: true,
          reason: `held-back lift \u0394=${lift.scoreDelta.toFixed(4)} > ${minDelta}`,
          rejectionCode: null
        };
      }
      return {
        promote: false,
        reason: `held-back lift \u0394=${lift.scoreDelta.toFixed(4)} \u2264 ${minDelta}`,
        rejectionCode: "negative_delta"
      };
    }
  };
}
function heldOutPromotionGate(opts) {
  const gate = new HeldOutGate({
    baselineKey: opts.baselineKey,
    minProductiveRuns: opts.minProductiveRuns,
    pairedDeltaThreshold: opts.pairedDeltaThreshold,
    overfitGapThreshold: opts.overfitGapThreshold,
    seed: opts.seed,
    costPerTaskCeiling: opts.costPerTaskCeiling
  });
  return {
    kind: "heldout",
    decide(lift) {
      const candidateRuns = recordsOf(lift.withArtifact.runs, "withArtifact", lift.artifactId);
      const baselineRuns = recordsOf(lift.withoutArtifact.runs, "withoutArtifact", lift.artifactId);
      const decision = gate.evaluate(candidateRuns, baselineRuns);
      return {
        promote: decision.promote,
        reason: decision.reason,
        rejectionCode: decision.rejectionCode
      };
    }
  };
}
function recordsOf(runs, arm, artifactId) {
  if (runs === void 0 || runs.length === 0) {
    throw new Error(
      `heldOutPromotionGate: the EvalRunner produced no per-task records on the '${arm}' arm for artifact ${JSON.stringify(artifactId)}. The held-out gate runs a paired-bootstrap on per-task holdout records \u2014 it cannot decide from a scalar composite. Either surface EvalResult.runs from your runner, or use thresholdPromotionGate.`
    );
  }
  return runs;
}

// src/lifecycle/prompt-generator.ts
import { callLlmJson } from "@tangle-network/agent-eval";
import {
  gepaProposer,
  isProposedCandidate
} from "@tangle-network/agent-eval/campaign";
function promptGenerator(opts) {
  if (!opts.refine && !opts.authorDiverseSeeds) {
    throw new TypeError(
      "promptGenerator: at least one of `refine` or `authorDiverseSeeds` is required \u2014 a generator with neither can never produce a candidate"
    );
  }
  const seedCount = opts.diverseSeedCount ?? 3;
  return {
    kind: "prompt",
    async generate(ctx) {
      const drafts = [];
      if (opts.authorDiverseSeeds && seedCount > 0) {
        drafts.push(...await opts.authorDiverseSeeds(ctx, seedCount));
      }
      if (opts.refine) {
        drafts.push(...await opts.refine(ctx));
      }
      return dedupeByInstruction(drafts).map(toPromptArtifact);
    }
  };
}
function dedupeByInstruction(drafts) {
  const seen = /* @__PURE__ */ new Set();
  const out = [];
  for (const draft of drafts) {
    const key = draft.instruction.trim();
    if (key.length === 0 || seen.has(key)) continue;
    seen.add(key);
    out.push(draft);
  }
  return out;
}
function toPromptArtifact(draft) {
  return {
    kind: "prompt",
    name: draft.label,
    description: draft.rationale,
    payload: { instruction: draft.instruction },
    metadata: { rationale: draft.rationale }
  };
}
var defaultPromptModel = "deepseek-v4-flash";
function productionPromptGenerator(opts) {
  const model = opts.model ?? defaultPromptModel;
  return promptGenerator({
    refine: gepaRefine(opts.llm, model, opts.refinePopulation ?? 3),
    authorDiverseSeeds: routerSeedAuthor(opts.llm, model, opts.seedTemperature ?? 1),
    diverseSeedCount: opts.diverseSeedCount ?? 3
  });
}
function gepaRefine(llm, model, population) {
  const proposer = gepaProposer({
    llm,
    model,
    target: "agent system prompt"
  });
  return async (ctx) => {
    const baseline = baselinePromptSurface(ctx.baseline);
    const proposeCtx = {
      currentSurface: baseline,
      history: [],
      findings: [...ctx.findings],
      populationSize: population,
      generation: 0,
      signal: ctx.signal ?? new AbortController().signal
    };
    const proposed = await proposer.propose(proposeCtx);
    return proposed.flatMap((p) => promptDraftFromProposal(p, baseline));
  };
}
function routerSeedAuthor(llm, model, temperature) {
  return async (ctx, count) => {
    const spec = baselinePromptSurface(ctx.baseline);
    const findingLines = ctx.findings.map(
      (f) => `- [${f.area}] ${f.claim}${f.recommended_action ? ` \u2192 ${f.recommended_action}` : ""}`
    ).join("\n");
    const system = "You author standing instructions for an autonomous agent. Given the agent task spec and its observed mistakes, write DIVERSE candidate instruction lines. CRITICAL: the candidates must NOT be paraphrases of each other or of the existing spec \u2014 each must take a GENUINELY DIFFERENT framing (e.g. one imperative directive, one as a pre-flight checklist, one written failure-mode-first, one as a principle, \u2026). Different framings let a search escape a local optimum instead of polishing one. Return JSON only.";
    const user = `Agent task spec (what it must do):
${spec || "(no explicit spec \u2014 infer from the domain)"}

Domain: ${ctx.domain}

Observed mistakes from traces:
${findingLines || "(none captured this round)"}

Author exactly ${count} instruction-line candidates, each a single standing instruction, each with a distinct framing.`;
    const { value } = await callLlmJson(
      {
        model,
        messages: [
          { role: "system", content: system },
          { role: "user", content: user }
        ],
        temperature,
        jsonSchema: {
          name: "diverse_prompt_seeds",
          schema: {
            type: "object",
            properties: {
              candidates: {
                type: "array",
                items: {
                  type: "object",
                  properties: {
                    instruction: { type: "string" },
                    framing: { type: "string" },
                    rationale: { type: "string" }
                  },
                  required: ["instruction", "framing"]
                }
              }
            },
            required: ["candidates"]
          }
        }
      },
      llm
    );
    const wire = value.candidates ?? [];
    return wire.slice(0, count).map((c, i) => ({
      instruction: c.instruction,
      label: c.framing?.trim() ? `seed:${c.framing.trim()}` : `seed-${i + 1}`,
      rationale: c.rationale?.trim() || `diverse seed (${c.framing?.trim() || "fresh framing"}) authored from the task spec to escape a local minimum`
    }));
  };
}
function baselinePromptSurface(profile) {
  return profile.prompt?.systemPrompt ?? "";
}
function promptDraftFromProposal(proposal, baseline) {
  if (isProposedCandidate(proposal)) {
    const surface = proposal.surface;
    if (typeof surface !== "string") return [];
    const instruction2 = surfaceDelta(baseline, surface);
    if (!instruction2) return [];
    return [
      {
        instruction: instruction2,
        label: proposal.label?.trim() || "refine",
        rationale: proposal.rationale?.trim() || "incumbent-grounded rewrite (gepaProposer)"
      }
    ];
  }
  if (typeof proposal !== "string") return [];
  const instruction = surfaceDelta(baseline, proposal);
  if (!instruction) return [];
  return [{ instruction, label: "refine", rationale: "incumbent-grounded rewrite (gepaProposer)" }];
}
function surfaceDelta(baseline, proposed) {
  const trimmed = proposed.trim();
  const base = baseline.trim();
  if (trimmed === base) return "";
  if (base && trimmed.startsWith(base)) {
    return trimmed.slice(base.length).trim();
  }
  return trimmed;
}

// src/lifecycle/registry.ts
var liftMetadataKey = "measuredLift";
var lifecycleReasonKey = "lifecycleReason";
var ArtifactRegistry = class {
  artifacts = /* @__PURE__ */ new Map();
  counter = 0;
  /**
   * Register an artifact, returning the stored record (with its assigned id).
   * When `input.id` is set it is honored (idempotent re-registration replaces
   * the record under the same id); otherwise a stable id is minted as
   * `<kind>-<n>`. `status` defaults to `'candidate'`.
   */
  register(input) {
    const id = input.id ?? this.mintId(input.kind);
    if (input.id !== void 0 && (input.id.length === 0 || input.id.trim() !== input.id)) {
      throw new ValidationError(
        `ArtifactRegistry.register: explicit id must be a non-empty, untrimmed-free string (got ${JSON.stringify(input.id)})`
      );
    }
    const record = {
      id,
      kind: input.kind,
      key: input.key,
      name: input.name,
      description: input.description,
      payload: input.payload,
      status: input.status ?? "candidate",
      metadata: input.metadata
    };
    this.artifacts.set(id, record);
    return record;
  }
  /** Get an artifact by id, or `undefined` if it was never registered. */
  get(id) {
    return this.artifacts.get(id);
  }
  /**
   * List artifacts, optionally filtered by `kind` and/or `status`. Returns a new
   * array in registration order; callers may safely sort/mutate the result.
   */
  list(query = {}) {
    const out = [];
    for (const artifact of this.artifacts.values()) {
      if (query.kind !== void 0 && artifact.kind !== query.kind) continue;
      if (query.status !== void 0 && artifact.status !== query.status) continue;
      out.push(artifact);
    }
    return out;
  }
  /**
   * Mark an artifact `active`. Fails loud on an unknown id — promoting a
   * non-existent artifact is a caller bug, not a no-op. Returns the updated
   * record. Idempotent: promoting an already-active artifact is a no-op return.
   *
   * NOTE: the artifact-lifecycle INVARIANT (no measured lift ⇒ not active) is
   * enforced by `promoteWithLift`, the path the closed loop uses. This bare
   * `promote` exists for callers that gate elsewhere and just flip the flag; it
   * does NOT record a lift score, so `liftOf` returns `undefined` and a
   * lift-ranked `composeProfile` will skip it. Prefer `promoteWithLift`.
   */
  promote(id) {
    const artifact = this.artifacts.get(id);
    if (!artifact) {
      throw new ValidationError(
        `ArtifactRegistry.promote: no artifact with id ${JSON.stringify(id)} is registered`
      );
    }
    if (artifact.status === "active") return artifact;
    const promoted = { ...artifact, status: "active" };
    this.artifacts.set(id, promoted);
    return promoted;
  }
  /**
   * Promote an artifact AND record the measured held-back lift that earned it.
   * This is the closed loop's promotion path and the enforcement point of the
   * lifecycle invariant: an artifact becomes `active` only WITH a finite lift
   * number stamped under `liftMetadataKey`. A non-finite `lift` (NaN/Infinity)
   * fails loud — promoting on a broken measurement is exactly the silent-zero the
   * doctrine forbids. Re-promotes a `decayed` artifact whose lift recovered.
   * Returns the updated record.
   */
  promoteWithLift(id, lift) {
    if (!Number.isFinite(lift)) {
      throw new ValidationError(
        `ArtifactRegistry.promoteWithLift: lift for ${JSON.stringify(id)} must be a finite number (got ${lift})`
      );
    }
    const artifact = this.artifacts.get(id);
    if (!artifact) {
      throw new ValidationError(
        `ArtifactRegistry.promoteWithLift: no artifact with id ${JSON.stringify(id)} is registered`
      );
    }
    const promoted = {
      ...artifact,
      status: "active",
      metadata: { ...artifact.metadata, [liftMetadataKey]: lift }
    };
    this.artifacts.set(id, promoted);
    return promoted;
  }
  /**
   * Demote an `active` artifact to `decayed`: it was promoted, but a later
   * re-measure (`driftWatch`) found its held-back lift fell below the keep-bar.
   * Records the latest re-measured `lift` (so `liftOf` reflects current evidence)
   * and the `reason` (so the demotion is auditable). The artifact stays in the
   * registry — `decayed`, not deleted — so it can be re-promoted if a future
   * re-measure recovers the lift. Fails loud on an unknown id. Demoting a
   * non-`active` artifact fails loud too: only the active set decays.
   */
  demote(id, reason, lift) {
    const artifact = this.artifacts.get(id);
    if (!artifact) {
      throw new ValidationError(
        `ArtifactRegistry.demote: no artifact with id ${JSON.stringify(id)} is registered`
      );
    }
    if (artifact.status !== "active") {
      throw new ValidationError(
        `ArtifactRegistry.demote: artifact ${JSON.stringify(id)} is '${artifact.status}', not 'active' \u2014 only an active artifact can decay`
      );
    }
    if (lift !== void 0 && !Number.isFinite(lift)) {
      throw new ValidationError(
        `ArtifactRegistry.demote: re-measured lift for ${JSON.stringify(id)} must be a finite number (got ${lift})`
      );
    }
    const demoted = {
      ...artifact,
      status: "decayed",
      metadata: {
        ...artifact.metadata,
        [lifecycleReasonKey]: reason,
        ...lift !== void 0 ? { [liftMetadataKey]: lift } : {}
      }
    };
    this.artifacts.set(id, demoted);
    return demoted;
  }
  /**
   * Retire an artifact to the terminal `retired` state: it is permanently out of
   * the active set (`dedupeArtifacts` retires the weaker half of a non-stacking
   * pair). Records the `reason` for the audit trail. Unlike `demote`, this is
   * terminal — a retired artifact is never re-promoted by the loop. Idempotent on
   * an already-retired artifact; fails loud on an unknown id.
   */
  retire(id, reason) {
    const artifact = this.artifacts.get(id);
    if (!artifact) {
      throw new ValidationError(
        `ArtifactRegistry.retire: no artifact with id ${JSON.stringify(id)} is registered`
      );
    }
    if (artifact.status === "retired") return artifact;
    const retired = {
      ...artifact,
      status: "retired",
      metadata: { ...artifact.metadata, [lifecycleReasonKey]: reason }
    };
    this.artifacts.set(id, retired);
    return retired;
  }
  /**
   * The measured held-back lift recorded at promotion time (and overwritten by
   * the latest `driftWatch` re-measure), or `undefined` when the artifact was
   * never promoted WITH a lift (a fresh candidate, or one promoted via the bare
   * `promote`). The lifecycle invariant in one accessor: `liftOf(id) ===
   * undefined` ⇒ the artifact has no measured lift ⇒ it is not eligible for a
   * lift-ranked compose. Note this returns the recorded lift regardless of status
   * — `composeProfile` separately filters to `active`, so a `decayed` artifact's
   * stale lift is visible for audit but never folded into a profile.
   */
  liftOf(id) {
    const value = this.artifacts.get(id)?.metadata?.[liftMetadataKey];
    return typeof value === "number" && Number.isFinite(value) ? value : void 0;
  }
  /**
   * Compose a set of registered artifacts onto a baseline profile. With no ids
   * given, composes every `active` artifact (the "ship the passing set"
   * default). With explicit ids, composes exactly those (in id order given),
   * failing loud on any unknown id. The applied order is the order passed (or
   * registration order for the active-default), and later artifacts win on key
   * conflicts — same semantics as `applyArtifacts`.
   */
  compose(base, ids) {
    const selected = ids === void 0 ? this.list({ status: "active" }) : ids.map((id) => {
      const artifact = this.artifacts.get(id);
      if (!artifact) {
        throw new ValidationError(
          `ArtifactRegistry.compose: no artifact with id ${JSON.stringify(id)} is registered`
        );
      }
      return artifact;
    });
    return applyArtifacts(base, selected);
  }
  /** Number of registered artifacts (any status). */
  get size() {
    return this.artifacts.size;
  }
  mintId(kind) {
    let id;
    do {
      this.counter += 1;
      id = `${kind}-${this.counter}`;
    } while (this.artifacts.has(id));
    return id;
  }
};
function createArtifactRegistry() {
  return new ArtifactRegistry();
}

// src/lifecycle/run-lifecycle.ts
async function runLifecycle(opts) {
  if (opts.generators.length === 0) {
    throw new ValidationError("runLifecycle: at least one CandidateGenerator is required");
  }
  const registry = opts.registry ?? new ArtifactRegistry();
  const generation = opts.generation ?? 0;
  const findings = opts.findings ?? [];
  const ctx = {
    baseline: opts.baseline,
    domain: opts.domain,
    findings,
    traces: opts.traces,
    signal: opts.signal
  };
  const candidates = [];
  for (const generator of opts.generators) {
    if (opts.signal?.aborted) break;
    const inputs = await generator.generate(ctx);
    for (const input of inputs) {
      const stored = registry.register({
        ...input,
        // Provenance: who proposed this, for which domain, in which generation.
        metadata: {
          ...input.metadata,
          domain: opts.domain,
          generation,
          generatorKind: generator.kind
        }
      });
      candidates.push(stored);
    }
  }
  const baselineResult = await opts.evalRunner(opts.baseline, opts.signal);
  const outcomes = [];
  const promoted = [];
  for (const candidate of candidates) {
    if (opts.signal?.aborted) break;
    const lift = await measureMarginalLift({
      baseline: opts.baseline,
      candidate,
      evalRunner: opts.evalRunner,
      baselineResult,
      signal: opts.signal
    });
    const verdict = opts.gate.decide(lift);
    let artifact = candidate;
    if (verdict.promote) {
      artifact = registry.promoteWithLift(candidate.id, lift.scoreDelta);
      promoted.push(candidate.id);
    } else {
      artifact = registry.register({
        ...toInput(candidate),
        metadata: {
          ...candidate.metadata,
          gateReason: verdict.reason,
          gateRejectionCode: verdict.rejectionCode,
          scoreDelta: lift.scoreDelta
        }
      });
    }
    outcomes.push({
      artifact,
      kind: candidate.kind,
      scoreDelta: lift.scoreDelta,
      costDelta: lift.costDelta,
      verdict,
      promoted: verdict.promote
    });
  }
  return { registry, outcomes, promoted, baselineResult };
}
function toInput(artifact) {
  return {
    id: artifact.id,
    kind: artifact.kind,
    key: artifact.key,
    name: artifact.name,
    description: artifact.description,
    payload: artifact.payload
  };
}

// src/lifecycle/skill-generator.ts
function skillGenerator(opts) {
  return {
    kind: "skill",
    async generate(ctx) {
      const drafts = await opts.distill(ctx);
      const out = [];
      for (const draft of drafts) {
        const refined = opts.refine ? await opts.refine(draft) : draft;
        out.push(toSkillArtifact(refined));
      }
      return out;
    }
  };
}
function toSkillArtifact(draft) {
  const resource = {
    kind: "inline",
    name: draft.name,
    content: draft.content
  };
  return {
    kind: "skill",
    name: draft.name,
    description: draft.description,
    payload: { resource }
  };
}

// src/lifecycle/tool-build.ts
import {
  gitWorktreeAdapter,
  resolveWorktreePath
} from "@tangle-network/agent-eval/campaign";
function worktreeBuildCandidate(opts) {
  const harness = opts.harness ?? "claude";
  const baseRef = opts.baseRef ?? "main";
  const maxShots = opts.maxShots ?? 3;
  const worktree = gitWorktreeAdapter({
    repoRoot: opts.repoRoot,
    branchPrefix: `build-${opts.kind}`
  });
  const generator = agenticGenerator({
    harness,
    ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
    buildPrompt: opts.kind === "mcp" ? mcpBuildPrompt : toolBuildPrompt,
    verify: buildVerifier(opts)
  });
  return async (ctx, index, signal) => {
    const label = `${opts.kind}-cand${index}`;
    const wt = await worktree.create({ baseRef, label });
    try {
      const { applied, summary } = await generator.generate({
        worktreePath: wt.path,
        report: void 0,
        findings: [...ctx.findings],
        maxShots,
        signal
      });
      if (!applied) {
        await worktree.discard(wt).catch(() => {
        });
        return {
          label,
          verified: false,
          worktreeRef: wt.path,
          failureReason: "no verified candidate within maxShots"
        };
      }
      const surface = await worktree.finalize(wt, summary);
      return verifiedBuild(opts, label, surface);
    } catch (err) {
      await worktree.discard(wt).catch(() => {
      });
      throw err;
    }
  };
}
function buildVerifier(opts) {
  if (opts.kind === "mcp") {
    if (!opts.mcp) {
      throw new ValidationError(
        "worktreeBuildCandidate: an mcp build requires opts.mcp (the boot-and-probe serve spec)"
      );
    }
    return mcpServeVerifier(opts.mcp);
  }
  const command = opts.tool?.verifyCommand ?? "pnpm";
  const args = opts.tool?.verifyArgs ?? (opts.tool?.verifyCommand ? [] : ["test"]);
  return commandVerifier(command, args);
}
function verifiedBuild(opts, label, surface) {
  const worktreeRef = resolveWorktreePath(surface);
  if (opts.kind === "tool") {
    const toolName = opts.tool?.toolName;
    if (!toolName || toolName.trim().length === 0) {
      throw new ValidationError(
        "worktreeBuildCandidate: a tool build requires opts.tool.toolName for the grant key"
      );
    }
    return {
      label,
      verified: true,
      worktreeRef,
      toolName,
      metadata: { summary: surface.summary, baseRef: surface.baseRef }
    };
  }
  const mcp = opts.mcp;
  return {
    label,
    verified: true,
    worktreeRef,
    serve: {
      command: mcp.command,
      ...mcp.args ? { args: mcp.args } : {},
      cwd: worktreeRef,
      ...mcp.env ? { env: mcp.env } : {}
    },
    metadata: { summary: surface.summary, baseRef: surface.baseRef }
  };
}

// src/lifecycle/tool-generator.ts
function buildableGenerator(opts) {
  const fanout = opts.fanout ?? 3;
  if (fanout < 1) {
    throw new ValidationError(
      `buildableGenerator: fanout must be >= 1 (got ${fanout}) \u2014 a dispatch with no candidates can never build anything`
    );
  }
  return {
    kind: opts.kind,
    async generate(ctx) {
      const signal = ctx.signal ?? new AbortController().signal;
      const settled = await Promise.all(
        Array.from({ length: fanout }, (_unused, i) => opts.buildCandidate(ctx, i, signal))
      );
      const verified = settled.filter((b) => b.verified);
      if (verified.length === 0) return [];
      const baselineResult = await opts.evalRunner(ctx.baseline, signal);
      const ranked = [];
      for (const built of verified) {
        if (signal.aborted) break;
        const probe = stageProbeArtifact(opts.kind, built);
        const lift = await measureMarginalLift({
          baseline: ctx.baseline,
          candidate: probe,
          evalRunner: opts.evalRunner,
          baselineResult,
          signal
        });
        ranked.push({ built, scoreDelta: lift.scoreDelta, costDelta: lift.costDelta });
      }
      if (ranked.length === 0) return [];
      ranked.sort((a, b) => b.scoreDelta - a.scoreDelta);
      const winner = ranked[0];
      return [toArtifact(opts.kind, winner.built, winner.scoreDelta, winner.costDelta, fanout)];
    }
  };
}
var probeRegistry = new ArtifactRegistry();
function stageProbeArtifact(kind, built) {
  return probeRegistry.register(bareArtifact(kind, built));
}
function bareArtifact(kind, built) {
  if (kind === "tool") {
    const toolName = built.toolName;
    if (!toolName || toolName.trim().length === 0) {
      throw new ValidationError(
        `buildableGenerator: a verified 'tool' build must report a toolName (label=${built.label})`
      );
    }
    return {
      kind: "tool",
      key: toolName,
      name: toolName,
      payload: { enabled: true }
    };
  }
  const serve = built.serve;
  if (!serve?.command || serve.command.trim().length === 0) {
    throw new ValidationError(
      `buildableGenerator: a verified 'mcp' build must report a serve command (label=${built.label})`
    );
  }
  const server = {
    transport: "stdio",
    command: serve.command,
    ...serve.args ? { args: serve.args } : {},
    ...serve.cwd ? { cwd: serve.cwd } : { cwd: built.worktreeRef },
    ...serve.env ? { env: serve.env } : {},
    enabled: true
  };
  return {
    kind: "mcp",
    key: built.label,
    name: built.label,
    payload: { server }
  };
}
function toArtifact(kind, built, scoreDelta, costDelta, fanout) {
  const bare = bareArtifact(kind, built);
  return {
    ...bare,
    description: `built via ${fanout}-way fan-out; won on +${scoreDelta.toFixed(4)} held-back lift`,
    metadata: {
      ...built.metadata,
      worktreeRef: built.worktreeRef,
      buildLabel: built.label,
      fanout,
      // The INTERNAL rank lift (best-of-N selection), distinct from the
      // orchestrator's promotion-gate measurement.
      siblingScoreDelta: scoreDelta,
      siblingCostDelta: costDelta
    }
  };
}
export {
  ArtifactRegistry,
  applyArtifact,
  applyArtifacts,
  buildableGenerator,
  composeProfile,
  createArtifactRegistry,
  dedupeArtifacts,
  driftWatch,
  gepaRefine,
  heldOutPromotionGate,
  lifecycleReasonKey,
  liftMetadataKey,
  measureMarginalLift,
  productionPromptGenerator,
  promptGenerator,
  routerSeedAuthor,
  runLifecycle,
  skillGenerator,
  thresholdPromotionGate,
  worktreeBuildCandidate
};
//# sourceMappingURL=lifecycle.js.map