import {
  pairedBootstrap
} from "../chunk-HRGUJTER.js";
import {
  DEFAULT_REDACTION_RULES,
  redactString
} from "../chunk-GGE4NNQT.js";
import {
  validateRunRecord
} from "../chunk-LO6IOIJ2.js";
import "../chunk-VSMTAMNK.js";
import {
  ValidationError
} from "../chunk-3BFEG2F6.js";
import "../chunk-PZ5AY32C.js";

// src/workflow/event-schema.ts
var WORKFLOW_EVENT_KINDS = [
  "workflow.started",
  "workflow.phase",
  "workflow.log",
  "workflow.parallel.started",
  "workflow.parallel.ended",
  "workflow.pipeline.started",
  "workflow.pipeline.ended",
  "workflow.branch.started",
  "workflow.branch.ended",
  "workflow.branch.failed",
  "workflow.agent.started",
  "workflow.agent.ended",
  "workflow.agent.failed",
  "workflow.loop.started",
  "workflow.loop.ended",
  "workflow.loop.failed",
  "workflow.verifier.started",
  "workflow.verifier.ended",
  "workflow.verifier.failed",
  "workflow.analyst.started",
  "workflow.analyst.ended",
  "workflow.analyst.failed",
  "workflow.reviewer.started",
  "workflow.reviewer.ended",
  "workflow.reviewer.failed",
  "workflow.failed",
  "workflow.ended"
];
var WORKFLOW_TRACE_EVENT_KINDS = WORKFLOW_EVENT_KINDS;
var WORKFLOW_EVENT_KIND_SET = new Set(WORKFLOW_EVENT_KINDS);
var BRANCH_OPERATIONS = /* @__PURE__ */ new Set(["parallel", "pipeline"]);
function validateWorkflowTraceEventKind(kind) {
  if (!WORKFLOW_EVENT_KIND_SET.has(kind)) {
    throw new ValidationError(`unknown workflow trace event kind: ${kind}`);
  }
  return kind;
}
function validateWorkflowTraceEventPayload(kind, payload) {
  switch (kind) {
    case "workflow.started":
      requireRecord(payload.meta, `${kind}.payload.meta`);
      requireInteger(payload.depth, `${kind}.payload.depth`, { min: 0 });
      requireRecord(payload.caps, `${kind}.payload.caps`);
      return payload;
    case "workflow.phase":
      requireString(payload.title, `${kind}.payload.title`);
      return payload;
    case "workflow.log":
      requireString(payload.message, `${kind}.payload.message`);
      optionalString(payload.phase, `${kind}.payload.phase`);
      return payload;
    case "workflow.parallel.started":
      requireInteger(payload.branchCount, `${kind}.payload.branchCount`, { min: 0 });
      optionalString(payload.phase, `${kind}.payload.phase`);
      return payload;
    case "workflow.parallel.ended":
      requireInteger(payload.branchCount, `${kind}.payload.branchCount`, { min: 0 });
      requireNonNegativeNumber(payload.durationMs, `${kind}.payload.durationMs`);
      optionalString(payload.phase, `${kind}.payload.phase`);
      return payload;
    case "workflow.pipeline.started":
      requireInteger(payload.itemCount, `${kind}.payload.itemCount`, { min: 0 });
      requireInteger(payload.stageCount, `${kind}.payload.stageCount`, { min: 1 });
      optionalString(payload.phase, `${kind}.payload.phase`);
      return payload;
    case "workflow.pipeline.ended":
      requireInteger(payload.itemCount, `${kind}.payload.itemCount`, { min: 0 });
      requireInteger(payload.stageCount, `${kind}.payload.stageCount`, { min: 1 });
      requireNonNegativeNumber(payload.durationMs, `${kind}.payload.durationMs`);
      optionalString(payload.phase, `${kind}.payload.phase`);
      return payload;
    case "workflow.branch.started":
      validateBranchPayload(kind, payload, { terminal: false });
      return payload;
    case "workflow.branch.ended":
      validateBranchPayload(kind, payload, { terminal: true });
      return payload;
    case "workflow.branch.failed":
      validateBranchPayload(kind, payload, { terminal: true });
      requireString(payload.message, `${kind}.payload.message`);
      optionalString(payload.code, `${kind}.payload.code`);
      if (payload.stageIndex !== void 0) {
        requireInteger(payload.stageIndex, `${kind}.payload.stageIndex`, { min: 0 });
      }
      return payload;
    case "workflow.agent.started":
      validateIndexedPayload(kind, payload);
      requireInteger(payload.promptChars, `${kind}.payload.promptChars`, { min: 0 });
      optionalRecord(payload.metadata, `${kind}.payload.metadata`);
      return payload;
    case "workflow.agent.ended":
      validateDelegateEndedPayload(kind, payload);
      return payload;
    case "workflow.agent.failed":
      validateDelegateFailedPayload(kind, payload);
      return payload;
    case "workflow.loop.started":
    case "workflow.verifier.started":
    case "workflow.analyst.started":
    case "workflow.reviewer.started":
      validateIndexedPayload(kind, payload);
      optionalRecord(payload.metadata, `${kind}.payload.metadata`);
      return payload;
    case "workflow.loop.ended":
    case "workflow.verifier.ended":
    case "workflow.analyst.ended":
    case "workflow.reviewer.ended":
      validateDelegateEndedPayload(kind, payload);
      return payload;
    case "workflow.loop.failed":
    case "workflow.verifier.failed":
    case "workflow.analyst.failed":
    case "workflow.reviewer.failed":
      validateDelegateFailedPayload(kind, payload);
      return payload;
    case "workflow.failed":
      requireString(payload.message, `${kind}.payload.message`);
      optionalString(payload.code, `${kind}.payload.code`);
      optionalString(payload.phase, `${kind}.payload.phase`);
      return payload;
    case "workflow.ended":
      requireNonNegativeNumber(payload.durationMs, `${kind}.payload.durationMs`);
      requireNonNegativeNumber(payload.costUsd, `${kind}.payload.costUsd`);
      validateTokenUsage(payload.tokenUsage, `${kind}.payload.tokenUsage`);
      requireInteger(payload.agentCalls, `${kind}.payload.agentCalls`, { min: 0 });
      requireInteger(payload.loopCalls, `${kind}.payload.loopCalls`, { min: 0 });
      return payload;
  }
}
function validateBranchPayload(kind, payload, options) {
  const operation = requireString(payload.operation, `${kind}.payload.operation`);
  if (!BRANCH_OPERATIONS.has(operation)) {
    throw new ValidationError(`${kind}.payload.operation: expected parallel or pipeline`);
  }
  requireInteger(payload.branchIndex, `${kind}.payload.branchIndex`, { min: 0 });
  optionalString(payload.phase, `${kind}.payload.phase`);
  if (payload.stageCount !== void 0) {
    requireInteger(payload.stageCount, `${kind}.payload.stageCount`, { min: 1 });
  }
  if (options.terminal) {
    requireNonNegativeNumber(payload.durationMs, `${kind}.payload.durationMs`);
  }
}
function validateIndexedPayload(kind, payload) {
  requireInteger(payload.index, `${kind}.payload.index`, { min: 0 });
  optionalString(payload.label, `${kind}.payload.label`);
  optionalString(payload.phase, `${kind}.payload.phase`);
}
function validateDelegateEndedPayload(kind, payload) {
  validateIndexedPayload(kind, payload);
  requireNonNegativeNumber(payload.durationMs, `${kind}.payload.durationMs`);
  requireNonNegativeNumber(payload.costUsd, `${kind}.payload.costUsd`);
  validateTokenUsage(payload.tokenUsage, `${kind}.payload.tokenUsage`);
}
function validateDelegateFailedPayload(kind, payload) {
  validateIndexedPayload(kind, payload);
  requireNonNegativeNumber(payload.durationMs, `${kind}.payload.durationMs`);
  requireString(payload.message, `${kind}.payload.message`);
  optionalString(payload.code, `${kind}.payload.code`);
}
function validateTokenUsage(value, path) {
  const tokenUsage = requireRecord(value, path);
  requireNonNegativeNumber(tokenUsage.input, `${path}.input`);
  requireNonNegativeNumber(tokenUsage.output, `${path}.output`);
  if (tokenUsage.cached !== void 0) {
    requireNonNegativeNumber(tokenUsage.cached, `${path}.cached`);
  }
}
function requireRecord(value, path) {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    throw new ValidationError(`${path}: expected object`);
  }
  return value;
}
function optionalRecord(value, path) {
  if (value !== void 0) requireRecord(value, path);
}
function requireString(value, path) {
  if (typeof value !== "string" || value.length === 0) {
    throw new ValidationError(`${path}: expected non-empty string`);
  }
  return value;
}
function optionalString(value, path) {
  if (value !== void 0) requireString(value, path);
}
function requireNonNegativeNumber(value, path) {
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
    throw new ValidationError(`${path}: expected finite non-negative number`);
  }
  return value;
}
function requireInteger(value, path, options = {}) {
  if (typeof value !== "number" || !Number.isInteger(value)) {
    throw new ValidationError(`${path}: expected integer`);
  }
  if (options.min !== void 0 && value < options.min) {
    throw new ValidationError(`${path}: expected integer >= ${options.min}`);
  }
  return value;
}

// src/workflow/schema.ts
var TRACE_VERSION = "workflow-trace-v1";
function validateWorkflowTraceEvent(input) {
  const obj = expectRecord(input, "event");
  const kind = validateWorkflowTraceEventKind(expectString(obj.kind, "event.kind"));
  const runId = expectString(obj.runId, "event.runId");
  const timestamp = expectFinite(obj.timestamp, "event.timestamp");
  const payload = validateWorkflowTraceEventPayload(
    kind,
    expectRecord(obj.payload, "event.payload")
  );
  return { kind, runId, timestamp, payload };
}
function validateWorkflowTraceEnvelope(input) {
  const obj = expectRecord(input, "workflow trace envelope");
  if (obj.traceVersion !== TRACE_VERSION) {
    throw new ValidationError(`workflow traceVersion must be ${TRACE_VERSION}`);
  }
  const runId = expectString(obj.runId, "workflow trace runId");
  if (!Array.isArray(obj.events) || obj.events.length === 0) {
    throw new ValidationError("workflow trace envelope must include at least one event");
  }
  const events = obj.events.map(validateWorkflowTraceEvent);
  for (const event of events) {
    if (event.runId !== runId) {
      throw new ValidationError(`workflow trace event runId ${event.runId} does not match ${runId}`);
    }
  }
  validateWorkflowTraceLifecycle(events);
  return {
    traceVersion: TRACE_VERSION,
    runId,
    ...obj.topology !== void 0 ? { topology: obj.topology } : {},
    events,
    ...obj.artifacts !== void 0 ? { artifacts: validateArtifacts(obj.artifacts) } : {},
    ...obj.metadata !== void 0 ? { metadata: expectRecord(obj.metadata, "metadata") } : {}
  };
}
function validateWorkflowTraceLifecycle(events) {
  const first = events[0];
  if (first?.kind !== "workflow.started") {
    throw new ValidationError("workflow trace first event must be workflow.started");
  }
  for (let index = 1; index < events.length; index += 1) {
    if (events[index].timestamp < events[index - 1].timestamp) {
      throw new ValidationError(`workflow trace timestamps must be nondecreasing at event ${index}`);
    }
  }
  const terminalEvents = events.filter(
    (event) => event.kind === "workflow.ended" || event.kind === "workflow.failed"
  );
  if (terminalEvents.length !== 1) {
    throw new ValidationError(
      `workflow trace must include exactly one terminal event, got ${terminalEvents.length}`
    );
  }
  const last = events.at(-1);
  if (last?.kind !== terminalEvents[0]?.kind) {
    throw new ValidationError("workflow trace terminal event must be last");
  }
}
function summarizeWorkflowTrace(input) {
  const envelope = validateWorkflowTraceEnvelope(input);
  const started = envelope.events.find((e) => e.kind === "workflow.started");
  const ended = envelope.events.find((e) => e.kind === "workflow.ended");
  const failed = envelope.events.find((e) => e.kind === "workflow.failed");
  const endedPayload = ended?.payload ?? {};
  const tokenUsage = tokenUsageOf(endedPayload.tokenUsage);
  return {
    runId: envelope.runId,
    startedAt: started?.timestamp,
    endedAt: ended?.timestamp,
    durationMs: finiteOr(endedPayload.durationMs, durationFromEvents(envelope.events)),
    costUsd: finiteOr(endedPayload.costUsd, 0),
    tokenUsage,
    phaseCount: envelope.events.filter((e) => e.kind === "workflow.phase").length,
    branchCount: envelope.events.filter((e) => e.kind === "workflow.branch.ended").length,
    failedBranchCount: envelope.events.filter((e) => e.kind === "workflow.branch.failed").length,
    agentCalls: finiteOr(
      endedPayload.agentCalls,
      countEvents(envelope.events, "workflow.agent.ended", "workflow.agent.failed")
    ),
    loopCalls: finiteOr(
      endedPayload.loopCalls,
      countEvents(envelope.events, "workflow.loop.ended", "workflow.loop.failed")
    ),
    verifierCalls: countEvents(
      envelope.events,
      "workflow.verifier.ended",
      "workflow.verifier.failed"
    ),
    analystCalls: countEvents(envelope.events, "workflow.analyst.ended", "workflow.analyst.failed"),
    reviewerCalls: countEvents(
      envelope.events,
      "workflow.reviewer.ended",
      "workflow.reviewer.failed"
    ),
    agentFailures: countEvents(envelope.events, "workflow.agent.failed"),
    loopFailures: countEvents(envelope.events, "workflow.loop.failed"),
    verifierFailures: countEvents(envelope.events, "workflow.verifier.failed"),
    analystFailures: countEvents(envelope.events, "workflow.analyst.failed"),
    reviewerFailures: countEvents(envelope.events, "workflow.reviewer.failed"),
    eventCount: envelope.events.length,
    failed: failed !== void 0,
    failureMessage: typeof failed?.payload.message === "string" ? failed.payload.message : void 0
  };
}
function countEvents(events, ...kinds) {
  const allowed = new Set(kinds);
  return events.filter((event) => allowed.has(event.kind)).length;
}
function validateArtifacts(value) {
  if (!Array.isArray(value)) throw new ValidationError("workflow artifacts must be an array");
  return value.map((artifact, index) => {
    const obj = expectRecord(artifact, `artifacts[${index}]`);
    return {
      kind: expectString(obj.kind, `artifacts[${index}].kind`),
      uri: expectString(obj.uri, `artifacts[${index}].uri`),
      ...obj.contentType !== void 0 ? { contentType: expectString(obj.contentType, `artifacts[${index}].contentType`) } : {},
      ...obj.sha256 !== void 0 ? { sha256: expectString(obj.sha256, `artifacts[${index}].sha256`) } : {},
      ...obj.metadata !== void 0 ? { metadata: expectRecord(obj.metadata, `artifacts[${index}].metadata`) } : {}
    };
  });
}
function durationFromEvents(events) {
  const first = events[0]?.timestamp;
  const last = events.at(-1)?.timestamp;
  if (!Number.isFinite(first) || !Number.isFinite(last)) return 0;
  return Math.max(0, last - first);
}
function tokenUsageOf(value) {
  const obj = value && typeof value === "object" ? value : {};
  const cached = finiteOrUndefined(obj.cached);
  return {
    input: finiteOr(obj.input, 0),
    output: finiteOr(obj.output, 0),
    ...cached !== void 0 ? { cached } : {}
  };
}
function finiteOr(value, fallback) {
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
}
function finiteOrUndefined(value) {
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
}
function expectRecord(value, path) {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    throw new ValidationError(`${path}: expected object`);
  }
  return value;
}
function expectString(value, path) {
  if (typeof value !== "string" || value.length === 0) {
    throw new ValidationError(`${path}: expected non-empty string`);
  }
  return value;
}
function expectFinite(value, path) {
  if (typeof value !== "number" || !Number.isFinite(value)) {
    throw new ValidationError(`${path}: expected finite number`);
  }
  return value;
}

// src/workflow/feedback-pack.ts
var PACK_VERSION = "workflow-feedback-pack-v1";
var DEFAULT_LIMITS = {
  findings: 12,
  clusters: 8,
  layerFindings: 5,
  recommendations: 10,
  contextLines: 24
};
function buildWorkflowAnalystFeedbackPack(options) {
  const limits = { ...DEFAULT_LIMITS, ...options.limits ?? {} };
  const envelope = validateWorkflowTraceEnvelope(options.envelope);
  const summary = summarizeWorkflowTrace(envelope);
  const verifier = options.verifier ? summarizeVerifier(options.verifier, limits) : void 0;
  const toolUsage = summarizeToolUsage(envelope);
  const failureClusters = normalizeFailureClusters(options.failureClusters).sort((a, b) => b.share - a.share).slice(0, limits.clusters);
  const findings = summarizeFindings(options.analystFindings ?? []).sort(compareFindings).slice(0, limits.findings);
  const recommendations = uniqueStrings([
    ...recommendFromVerifier(verifier),
    ...failureClusters.flatMap((cluster) => cluster.suggestedFix ? [cluster.suggestedFix] : []),
    ...findings.flatMap(
      (finding) => finding.recommendedAction ? [finding.recommendedAction] : []
    ),
    ...summary.failed && summary.failureMessage ? [`Inspect workflow failure: ${summary.failureMessage}`] : []
  ]).slice(0, limits.recommendations);
  const pack = {
    schemaVersion: PACK_VERSION,
    runId: envelope.runId,
    generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
    summary,
    ...verifier ? { verifier } : {},
    toolUsage,
    failureClusters,
    findings,
    recommendations,
    driverContextLines: []
  };
  return {
    ...pack,
    driverContextLines: renderDriverContextLines(pack).slice(0, limits.contextLines)
  };
}
function renderWorkflowFeedbackPack(pack, options = {}) {
  const lines = [
    `Workflow feedback pack for ${pack.runId}`,
    `status=${pack.summary.failed ? "failed" : "completed"} durationMs=${pack.summary.durationMs} costUsd=${pack.summary.costUsd.toFixed(6)} tokens=${pack.summary.tokenUsage.input}/${pack.summary.tokenUsage.output} events=${pack.summary.eventCount}`,
    renderDelegateFailureCounts(pack.summary),
    pack.verifier ? `verifier=${pack.verifier.allPass ? "pass" : "fail"} blendedScore=${pack.verifier.blendedScore.toFixed(3)} failedLayers=${pack.verifier.failedLayers.join(",") || "none"}` : void 0,
    pack.toolUsage.totalCalls > 0 ? `tools=${pack.toolUsage.totalCalls} errors=${pack.toolUsage.erroredCalls} byTool=${formatToolUsage(pack.toolUsage)}` : void 0,
    pack.failureClusters.length > 0 ? "Failure clusters:" : void 0,
    ...pack.failureClusters.map(
      (cluster) => `- ${cluster.name} share=${cluster.share.toFixed(3)} exemplars=${cluster.exemplars.join(",") || "none"}${cluster.suggestedFix ? ` fix=${cluster.suggestedFix}` : ""}`
    ),
    pack.findings.length > 0 ? "Analyst findings:" : void 0,
    ...pack.findings.map(
      (finding) => `- ${finding.severity} ${finding.area}: ${finding.claim}${finding.recommendedAction ? ` action=${finding.recommendedAction}` : ""}`
    ),
    pack.recommendations.length > 0 ? "Recommended next moves:" : void 0,
    ...pack.recommendations.map((recommendation) => `- ${recommendation}`)
  ].filter((line) => Boolean(line));
  const rendered = lines.join("\n");
  const maxChars = options.maxChars;
  if (maxChars === void 0 || rendered.length <= maxChars) return rendered;
  if (maxChars <= 1) return rendered.slice(0, Math.max(0, maxChars));
  return `${rendered.slice(0, maxChars - 1)}\u2026`;
}
function renderDelegateFailureCounts(summary) {
  const entries = [
    ["agent", summary.agentFailures],
    ["loop", summary.loopFailures],
    ["verifier", summary.verifierFailures],
    ["analyst", summary.analystFailures],
    ["reviewer", summary.reviewerFailures]
  ];
  const failures = entries.filter((entry) => entry[1] > 0);
  if (failures.length === 0) return void 0;
  return `delegateFailures=${failures.map(([kind, count]) => `${kind}:${count}`).join(",")}`;
}
function summarizeVerifier(verifier, limits) {
  const layers = verifier.layers.map((layer) => ({
    layer: layer.layer,
    status: layer.status,
    ...layer.score !== void 0 ? { score: layer.score } : {},
    durationMs: layer.durationMs,
    ...layer.reason ? { reason: layer.reason } : {},
    findings: layer.findings.map((finding) => ({
      severity: verifierSeverity(finding.severity),
      message: finding.message,
      ...finding.evidence ? { evidence: finding.evidence } : {},
      ...finding.detail ? { detail: finding.detail } : {}
    })).slice(0, limits.layerFindings),
    ...layer.diagnostics ? { diagnostics: layer.diagnostics } : {}
  }));
  return {
    allPass: verifier.allPass,
    blendedScore: verifier.blendedScore,
    durationMs: verifier.durationMs,
    failedLayers: verifier.layers.filter(
      (layer) => layer.status === "fail" || layer.status === "error" || layer.status === "timeout"
    ).map((layer) => layer.layer),
    layers
  };
}
function summarizeToolUsage(envelope) {
  const summary = { totalCalls: 0, erroredCalls: 0, byTool: {} };
  for (const event of envelope.events) {
    collectToolUsagePayload(summary, event.payload.toolUsage);
    collectToolCalls(summary, event.payload.toolCalls);
    collectSingleTool(summary, event.payload);
  }
  return summary;
}
function collectToolUsagePayload(summary, value) {
  if (!isRecord(value)) return;
  if (!isRecord(value.byTool)) {
    summary.totalCalls += finiteNumber(value.totalCalls);
    summary.erroredCalls += finiteNumber(value.erroredCalls);
    return;
  }
  let addedByTool = false;
  for (const [tool, raw] of Object.entries(value.byTool)) {
    if (!isRecord(raw)) continue;
    const calls = finiteNumber(raw.calls);
    const errors = finiteNumber(raw.errors);
    addTool(summary, tool, calls, errors);
    addedByTool ||= calls > 0 || errors > 0;
  }
  if (!addedByTool) {
    summary.totalCalls += finiteNumber(value.totalCalls);
    summary.erroredCalls += finiteNumber(value.erroredCalls);
  }
}
function collectToolCalls(summary, value) {
  if (!Array.isArray(value)) return;
  for (const call of value) {
    if (!isRecord(call)) continue;
    const name = stringValue(call.toolName) ?? stringValue(call.name);
    if (!name) continue;
    const errored = call.status === "error" || call.error !== void 0 || call.ok === false || call.success === false;
    addTool(summary, name, 1, errored ? 1 : 0);
  }
}
function collectSingleTool(summary, payload) {
  const name = stringValue(payload.toolName);
  if (!name) return;
  const errored = payload.status === "error" || payload.error !== void 0 || payload.ok === false || payload.success === false;
  addTool(summary, name, 1, errored ? 1 : 0);
}
function addTool(summary, name, calls, errors) {
  if (calls === 0 && errors === 0) return;
  const current = summary.byTool[name] ?? { calls: 0, errors: 0 };
  current.calls += calls;
  current.errors += errors;
  summary.byTool[name] = current;
  summary.totalCalls += calls;
  summary.erroredCalls += errors;
}
function normalizeFailureClusters(input) {
  if (!input) return [];
  if (Array.isArray(input)) {
    return input.map((cluster) => ({
      id: cluster.id,
      name: cluster.name,
      share: clamp01(cluster.share ?? 0),
      ...cluster.runCount !== void 0 ? { runCount: cluster.runCount } : {},
      exemplars: [...cluster.exemplars ?? []],
      ...cluster.suggestedFix ? { suggestedFix: cluster.suggestedFix } : {},
      source: "custom",
      ...cluster.metadata ? { metadata: cluster.metadata } : {}
    }));
  }
  const report = input;
  const clusters = report.clusters ?? [];
  const first = clusters[0];
  if (isRecord(first) && typeof first.failureClass === "string") {
    const failureReport = report;
    return failureReport.clusters.map((cluster) => ({
      id: [
        cluster.failureClass,
        cluster.toolName ?? "",
        cluster.argPrefix ?? "",
        cluster.dimension ?? ""
      ].join("|"),
      name: [
        cluster.failureClass,
        cluster.toolName ? `tool:${cluster.toolName}` : void 0,
        cluster.dimension ? `dimension:${cluster.dimension}` : void 0
      ].filter(Boolean).join(" "),
      share: failureReport.totalFailures > 0 ? cluster.runCount / failureReport.totalFailures : 0,
      runCount: cluster.runCount,
      exemplars: [cluster.exampleRunId],
      source: "failure-cluster-view",
      metadata: {
        scenarioIds: cluster.scenarioIds,
        exampleError: cluster.exampleError,
        argPrefix: cluster.argPrefix
      }
    }));
  }
  const insight = report;
  return insight.clusters.map((cluster) => ({
    id: cluster.id,
    name: cluster.name,
    share: clamp01(cluster.share),
    exemplars: [...cluster.exemplars],
    ...cluster.suggestedFix ? { suggestedFix: cluster.suggestedFix } : {},
    source: "insight-report"
  }));
}
function summarizeFindings(findings) {
  return findings.map((finding) => ({
    findingId: finding.finding_id,
    analystId: finding.analyst_id,
    severity: finding.severity,
    area: finding.area,
    claim: finding.claim,
    confidence: clamp01(finding.confidence),
    ...finding.subject ? { subject: finding.subject } : {},
    ...finding.recommended_action ? { recommendedAction: finding.recommended_action } : {},
    evidenceRefs: finding.evidence_refs
  }));
}
function recommendFromVerifier(verifier) {
  if (!verifier || verifier.allPass) return [];
  return verifier.layers.filter((layer) => verifier.failedLayers.includes(layer.layer)).map((layer) => {
    const firstFinding = layer.findings[0]?.message;
    const detail = layer.reason ?? firstFinding ?? layer.status;
    return `Fix verifier layer "${layer.layer}": ${detail}`;
  });
}
function renderDriverContextLines(pack) {
  return renderWorkflowFeedbackPack(pack).split("\n").map((line) => line.trim()).filter(Boolean);
}
function compareFindings(left, right) {
  const severityDelta = severityRank(right.severity) - severityRank(left.severity);
  if (severityDelta !== 0) return severityDelta;
  return right.confidence - left.confidence;
}
function verifierSeverity(severity) {
  switch (severity) {
    case "critical":
      return "critical";
    case "major":
      return "high";
    case "minor":
      return "low";
    case "info":
      return "info";
    default:
      return "medium";
  }
}
function severityRank(severity) {
  switch (severity) {
    case "critical":
      return 5;
    case "high":
      return 4;
    case "medium":
      return 3;
    case "low":
      return 2;
    case "info":
      return 1;
  }
}
function uniqueStrings(values) {
  const out = [];
  const seen = /* @__PURE__ */ new Set();
  for (const value of values) {
    const trimmed = value.trim();
    if (trimmed.length === 0 || seen.has(trimmed)) continue;
    seen.add(trimmed);
    out.push(trimmed);
  }
  return out;
}
function formatToolUsage(summary) {
  return Object.entries(summary.byTool).sort(([a], [b]) => a.localeCompare(b)).map(([tool, usage]) => `${tool}:${usage.calls}/${usage.errors}`).join(",");
}
function finiteNumber(value) {
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
}
function clamp01(value) {
  if (!Number.isFinite(value)) return 0;
  return Math.max(0, Math.min(1, value));
}
function isRecord(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}
function stringValue(value) {
  return typeof value === "string" && value.length > 0 ? value : void 0;
}

// src/workflow/sanitize.ts
import { createHash } from "crypto";
var DEFAULT_MAX_STRING_LENGTH = 600;
var SECRET_KEY_RE = /^(authorization|cookie|set-cookie|x-api-key|api[-_]?key|token|access[-_]?token|refresh[-_]?token|secret|password|passwd|session|credential|credentials)$/i;
var ARG_KEY_RE = /^(args|arguments|rawargs|raw_args|toolargs|tool_args|inputargs|input_args)$/i;
var FILE_CONTENT_KEY_RE = /^(filecontent|filecontents|file_content|file_contents|contents)$/i;
var FILE_HINT_KEY_RE = /^(path|filepath|file_path|filename|file|uri)$/i;
function sanitizeWorkflowTraceEnvelope(input, options = {}) {
  const envelope = validateWorkflowTraceEnvelope(input);
  const report = emptyReport();
  const ctx = {
    rules: [...options.rules ?? DEFAULT_REDACTION_RULES],
    maxStringLength: options.maxStringLength ?? DEFAULT_MAX_STRING_LENGTH,
    hashSalt: options.hashSalt ?? "",
    approvedArtifactUris: new Set(options.approvedArtifactUris ?? []),
    approvedArtifactKinds: new Set(options.approvedArtifactKinds ?? []),
    report
  };
  return {
    envelope: {
      traceVersion: envelope.traceVersion,
      runId: envelope.runId,
      ...envelope.topology ? { topology: sanitizeValue(envelope.topology, ctx) } : {},
      events: envelope.events.map((event) => sanitizeWorkflowTraceEvent(event, ctx)),
      ...envelope.artifacts ? { artifacts: sanitizeArtifacts(envelope.artifacts, ctx) } : {},
      ...envelope.metadata ? { metadata: sanitizeRecord(envelope.metadata, ctx) } : {}
    },
    report
  };
}
function sanitizeWorkflowTraceEvent(event, ctx) {
  return {
    kind: event.kind,
    runId: event.runId,
    timestamp: event.timestamp,
    payload: sanitizeRecord(event.payload, ctx)
  };
}
function sanitizeArtifacts(artifacts, ctx) {
  return artifacts.map((artifact) => {
    const approved = ctx.approvedArtifactUris.has(artifact.uri) || ctx.approvedArtifactKinds.has(artifact.kind);
    const metadata = artifact.metadata ? sanitizeRecord(artifact.metadata, ctx, { artifactApproved: approved }) : void 0;
    return {
      kind: artifact.kind,
      uri: sanitizeString(artifact.uri, ctx),
      ...artifact.contentType ? { contentType: sanitizeString(artifact.contentType, ctx) } : {},
      ...artifact.sha256 ? { sha256: artifact.sha256 } : {},
      ...metadata ? { metadata } : {}
    };
  });
}
function sanitizeRecord(record, ctx, options = {}) {
  const out = {};
  const hasFileHint = Object.keys(record).some((key) => FILE_HINT_KEY_RE.test(key));
  for (const [key, value] of Object.entries(record)) {
    if (SECRET_KEY_RE.test(key)) {
      out[key] = `[redacted:${key}]`;
      increment(ctx.report.droppedPayloadKeys, key);
      continue;
    }
    if (ARG_KEY_RE.test(key)) {
      out[key] = hashedValue(value, ctx);
      ctx.report.hashedArgs += 1;
      continue;
    }
    if (!options.artifactApproved && isFileContentKey(key, hasFileHint)) {
      out[key] = hashedValue(value, ctx);
      ctx.report.droppedArtifactContents += 1;
      continue;
    }
    out[key] = sanitizeValue(value, ctx);
  }
  return out;
}
function sanitizeValue(value, ctx) {
  if (typeof value === "string") return sanitizeString(value, ctx);
  if (Array.isArray(value)) return value.map((item) => sanitizeValue(item, ctx));
  if (isRecord2(value)) return sanitizeRecord(value, ctx);
  return value;
}
function sanitizeString(value, ctx) {
  const redacted = redactString(value, ctx.rules);
  ctx.report.redactionCount += redacted.report.redactionCount;
  for (const [rule, count] of Object.entries(redacted.report.byRule)) {
    ctx.report.byRule[rule] = (ctx.report.byRule[rule] ?? 0) + count;
  }
  if (redacted.output.length <= ctx.maxStringLength) return redacted.output;
  ctx.report.truncatedStrings += 1;
  return `${redacted.output.slice(0, Math.max(0, ctx.maxStringLength - 1))}\u2026`;
}
function hashedValue(value, ctx) {
  return {
    redacted: true,
    sha256: sha256Stable(value, ctx.hashSalt),
    shape: valueShape(value)
  };
}
function sha256Stable(value, salt) {
  return createHash("sha256").update(salt).update(stableStringify(value)).digest("hex");
}
function stableStringify(value) {
  if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
  if (isRecord2(value)) {
    return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(",")}}`;
  }
  return JSON.stringify(value);
}
function valueShape(value) {
  if (Array.isArray(value)) return { type: "array", length: value.length };
  if (isRecord2(value)) {
    return {
      type: "object",
      keys: Object.keys(value).sort()
    };
  }
  return { type: typeof value };
}
function isFileContentKey(key, hasFileHint) {
  if (FILE_CONTENT_KEY_RE.test(key)) return true;
  return hasFileHint && /^(content|source|diff)$/i.test(key);
}
function emptyReport() {
  return {
    redactionCount: 0,
    byRule: {},
    hashedArgs: 0,
    truncatedStrings: 0,
    droppedPayloadKeys: {},
    droppedArtifactContents: 0
  };
}
function increment(record, key) {
  record[key] = (record[key] ?? 0) + 1;
}
function isRecord2(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

// src/workflow/trace-event-fields.ts
function objectRecord(value) {
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
}
function stringField(record, key) {
  const value = record[key];
  return typeof value === "string" ? value : null;
}
function numberField(record, key) {
  const value = record[key];
  return typeof value === "number" && Number.isFinite(value) ? value : null;
}
function tokenUsageField(value) {
  const record = objectRecord(value);
  if (!record) return null;
  const input = numberField(record, "input");
  const output = numberField(record, "output");
  if (input === null || output === null) return null;
  const cached = numberField(record, "cached");
  return {
    input,
    output,
    ...cached !== null ? { cached } : {}
  };
}

// src/workflow/phase-graph.ts
function workflowPhaseGraph(events) {
  const nodes = /* @__PURE__ */ new Map();
  const branches = [];
  for (const event of events) {
    const phaseTitle = phaseTitleForEvent(event);
    if (phaseTitle) observePhaseEvent(phaseNode(nodes, phaseTitle), event);
    if (event.kind === "workflow.branch.started") {
      branches.push(branchStarted(event, branches.length));
      continue;
    }
    if (event.kind === "workflow.branch.ended" || event.kind === "workflow.branch.failed") {
      const branch = openBranchFor(branches, event) ?? branchStarted(event, branches.length);
      if (!branches.includes(branch)) branches.push(branch);
      observeBranchTerminal(branch, event);
    }
  }
  return {
    nodes: Array.from(nodes.values()).map(readonlyPhaseNode),
    branches: branches.map(readonlyBranch)
  };
}
function phaseNode(nodes, title) {
  const existing = nodes.get(title);
  if (existing) return existing;
  const node = {
    id: `phase-${nodes.size}`,
    title,
    eventCount: 0,
    branchCount: 0,
    failedBranchCount: 0,
    agentCalls: 0,
    loopCalls: 0,
    verifierCalls: 0,
    analystCalls: 0,
    reviewerCalls: 0,
    agentFailures: 0,
    loopFailures: 0,
    verifierFailures: 0,
    analystFailures: 0,
    reviewerFailures: 0,
    costUsd: 0,
    tokenUsage: { input: 0, output: 0 }
  };
  nodes.set(title, node);
  return node;
}
function observePhaseEvent(node, event) {
  node.eventCount += 1;
  node.startedAt = minDefined(node.startedAt, event.timestamp);
  node.endedAt = maxDefined(node.endedAt, event.timestamp);
  switch (event.kind) {
    case "workflow.branch.ended":
      node.branchCount += 1;
      break;
    case "workflow.branch.failed":
      node.failedBranchCount += 1;
      break;
    case "workflow.agent.ended":
      node.agentCalls += 1;
      break;
    case "workflow.agent.failed":
      node.agentCalls += 1;
      node.agentFailures += 1;
      break;
    case "workflow.loop.ended":
      node.loopCalls += 1;
      break;
    case "workflow.loop.failed":
      node.loopCalls += 1;
      node.loopFailures += 1;
      break;
    case "workflow.verifier.ended":
      node.verifierCalls += 1;
      break;
    case "workflow.verifier.failed":
      node.verifierCalls += 1;
      node.verifierFailures += 1;
      break;
    case "workflow.analyst.ended":
      node.analystCalls += 1;
      break;
    case "workflow.analyst.failed":
      node.analystCalls += 1;
      node.analystFailures += 1;
      break;
    case "workflow.reviewer.ended":
      node.reviewerCalls += 1;
      break;
    case "workflow.reviewer.failed":
      node.reviewerCalls += 1;
      node.reviewerFailures += 1;
      break;
  }
  const costUsd = numberField(event.payload, "costUsd");
  if (costUsd !== null) node.costUsd += costUsd;
  const tokenUsage = tokenUsageField(event.payload.tokenUsage);
  if (tokenUsage) addTokenUsage(node.tokenUsage, tokenUsage);
}
function phaseTitleForEvent(event) {
  return event.kind === "workflow.phase" ? stringField(event.payload, "title") : stringField(event.payload, "phase");
}
function branchStarted(event, index) {
  const branch = {
    id: `branch-${index}`,
    operation: stringField(event.payload, "operation") ?? "unknown",
    branchIndex: numberField(event.payload, "branchIndex") ?? -1,
    phase: stringField(event.payload, "phase"),
    status: "started"
  };
  const stageCount = numberField(event.payload, "stageCount");
  if (stageCount !== null) branch.stageCount = stageCount;
  branch.startedAt = event.timestamp;
  return branch;
}
function openBranchFor(branches, event) {
  const operation = stringField(event.payload, "operation") ?? "unknown";
  const branchIndex = numberField(event.payload, "branchIndex") ?? -1;
  const phase = stringField(event.payload, "phase");
  for (let i = branches.length - 1; i >= 0; i -= 1) {
    const branch = branches[i];
    if (branch?.status === "started" && branch.operation === operation && branch.branchIndex === branchIndex && branch.phase === phase) {
      return branch;
    }
  }
  return null;
}
function observeBranchTerminal(branch, event) {
  branch.status = event.kind === "workflow.branch.failed" ? "failed" : "ended";
  branch.endedAt = event.timestamp;
  const durationMs = numberField(event.payload, "durationMs");
  if (durationMs !== null) {
    branch.durationMs = durationMs;
  } else if (branch.startedAt !== void 0) {
    branch.durationMs = Math.max(0, event.timestamp - branch.startedAt);
  }
  const stageCount = numberField(event.payload, "stageCount");
  if (stageCount !== null) branch.stageCount = stageCount;
  const stageIndex = numberField(event.payload, "stageIndex");
  if (stageIndex !== null) branch.stageIndex = stageIndex;
  const message = stringField(event.payload, "message");
  if (message) branch.message = message;
  const code = stringField(event.payload, "code");
  if (code) branch.code = code;
}
function readonlyPhaseNode(node) {
  const result = {
    id: node.id,
    title: node.title,
    eventCount: node.eventCount,
    branchCount: node.branchCount,
    failedBranchCount: node.failedBranchCount,
    agentCalls: node.agentCalls,
    loopCalls: node.loopCalls,
    verifierCalls: node.verifierCalls,
    analystCalls: node.analystCalls,
    reviewerCalls: node.reviewerCalls,
    agentFailures: node.agentFailures,
    loopFailures: node.loopFailures,
    verifierFailures: node.verifierFailures,
    analystFailures: node.analystFailures,
    reviewerFailures: node.reviewerFailures,
    costUsd: node.costUsd,
    tokenUsage: node.tokenUsage
  };
  if (node.startedAt !== void 0) result.startedAt = node.startedAt;
  if (node.endedAt !== void 0) result.endedAt = node.endedAt;
  return result;
}
function readonlyBranch(branch) {
  const result = {
    id: branch.id,
    operation: branch.operation,
    branchIndex: branch.branchIndex,
    phase: branch.phase,
    status: branch.status
  };
  if (branch.startedAt !== void 0) result.startedAt = branch.startedAt;
  if (branch.endedAt !== void 0) result.endedAt = branch.endedAt;
  if (branch.durationMs !== void 0) result.durationMs = branch.durationMs;
  if (branch.stageCount !== void 0) result.stageCount = branch.stageCount;
  if (branch.stageIndex !== void 0) result.stageIndex = branch.stageIndex;
  if (branch.message !== void 0) result.message = branch.message;
  if (branch.code !== void 0) result.code = branch.code;
  return result;
}
function minDefined(current, next) {
  return current === void 0 ? next : Math.min(current, next);
}
function maxDefined(current, next) {
  return current === void 0 ? next : Math.max(current, next);
}
function addTokenUsage(target, value) {
  target.input += value.input;
  target.output += value.output;
  if (value.cached !== void 0) target.cached = (target.cached ?? 0) + value.cached;
}

// src/workflow/summary.ts
function summarizeWorkflowExecution(input, options = {}) {
  const envelope = validateWorkflowTraceEnvelope(input);
  const base = summarizeWorkflowTrace(envelope);
  return {
    ...base,
    ...options.source !== void 0 ? { source: options.source } : {},
    eventKinds: workflowEventKinds(envelope.events),
    phases: workflowPhaseTitles(envelope.events),
    phaseGraph: workflowPhaseGraph(envelope.events),
    agentRuns: workflowDelegateTraceSummaries(envelope.events, "workflow.agent.ended"),
    loopRuns: workflowDelegateTraceSummaries(envelope.events, "workflow.loop.ended"),
    verifierOutputs: workflowCheckpointTraceSummaries(envelope.events, "workflow.verifier.ended"),
    analystOutputs: workflowCheckpointTraceSummaries(envelope.events, "workflow.analyst.ended"),
    reviewerOutputs: workflowCheckpointTraceSummaries(envelope.events, "workflow.reviewer.ended"),
    agentFailureDetails: workflowDelegateFailureSummaries(envelope.events, "workflow.agent.failed"),
    loopFailureDetails: workflowDelegateFailureSummaries(envelope.events, "workflow.loop.failed"),
    verifierFailureDetails: workflowDelegateFailureSummaries(
      envelope.events,
      "workflow.verifier.failed"
    ),
    analystFailureDetails: workflowDelegateFailureSummaries(
      envelope.events,
      "workflow.analyst.failed"
    ),
    reviewerFailureDetails: workflowDelegateFailureSummaries(
      envelope.events,
      "workflow.reviewer.failed"
    )
  };
}
function workflowEventKinds(events) {
  return events.reduce((acc, event) => {
    acc[event.kind] = (acc[event.kind] ?? 0) + 1;
    return acc;
  }, {});
}
function workflowPhaseTitles(events) {
  const titles = [];
  const seen = /* @__PURE__ */ new Set();
  for (const event of events) {
    const title = event.kind === "workflow.phase" ? stringField(event.payload, "title") : stringField(event.payload, "phase");
    if (!title || seen.has(title)) continue;
    seen.add(title);
    titles.push(title);
  }
  return titles;
}
function workflowDelegateTraceSummaries(events, endedKind) {
  return events.filter((event) => event.kind === endedKind).map((event) => ({
    index: numberField(event.payload, "index"),
    label: stringField(event.payload, "label"),
    phase: stringField(event.payload, "phase"),
    costUsd: numberField(event.payload, "costUsd"),
    tokenUsage: tokenUsageField(event.payload.tokenUsage),
    trace: event.payload.trace ?? null
  }));
}
function workflowCheckpointTraceSummaries(events, endedKind) {
  return workflowDelegateTraceSummaries(events, endedKind).map((summary) => ({
    ...summary,
    output: checkpointOutput(summary.trace)
  }));
}
function workflowDelegateFailureSummaries(events, failedKind) {
  return events.filter((event) => event.kind === failedKind).map((event) => ({
    index: numberField(event.payload, "index"),
    label: stringField(event.payload, "label"),
    phase: stringField(event.payload, "phase"),
    durationMs: numberField(event.payload, "durationMs"),
    message: stringField(event.payload, "message"),
    code: stringField(event.payload, "code")
  }));
}
function checkpointOutput(trace) {
  const record = objectRecord(trace);
  if (record && Object.hasOwn(record, "checkpointOutput")) {
    return record.checkpointOutput;
  }
  if (record && Object.hasOwn(record, "output")) return record.output;
  return trace;
}

// src/workflow/intelligence-export.ts
var ENVELOPE_VERSION = "workflow-trace-intelligence-envelope-v1";
var DEFAULT_DESTINATION = "intelligence.tangle.tools";
function buildWorkflowTraceIntelligenceEnvelope(options) {
  const productId = requireNonEmpty(options.productId, "productId");
  const partnerId = options.partnerId !== void 0 ? requireNonEmpty(options.partnerId, "partnerId") : void 0;
  const generatedAt = options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
  const grantIds = activeExportGrantIds({
    grants: options.grants,
    productId,
    partnerId,
    nowMs: Date.parse(generatedAt)
  });
  const base = validateWorkflowTraceEnvelope(options.envelope);
  const sourceEnvelope = options.metadata === void 0 ? base : {
    ...base,
    metadata: {
      ...base.metadata ?? {},
      intelligenceExport: options.metadata
    }
  };
  const sanitized = sanitizeWorkflowTraceEnvelope(sourceEnvelope, options.sanitize);
  const summary = summarizeWorkflowExecution(sanitized.envelope);
  return {
    schemaVersion: ENVELOPE_VERSION,
    destination: options.destination ?? DEFAULT_DESTINATION,
    generatedAt,
    productId,
    ...partnerId ? { partnerId } : {},
    runId: sanitized.envelope.runId,
    grantIds,
    traceEnvelope: sanitized.envelope,
    summary,
    compactEvidence: compactEvidence(sanitized.envelope, summary),
    sanitization: sanitized.report,
    ...options.links ? { links: options.links } : {}
  };
}
function validateWorkflowTraceIntelligenceEnvelope(input) {
  const obj = expectRecord2(input, "workflow intelligence envelope");
  if (obj.schemaVersion !== ENVELOPE_VERSION) {
    throw new ValidationError(`workflow intelligence schemaVersion must be ${ENVELOPE_VERSION}`);
  }
  const destination = expectString2(obj.destination, "destination");
  const generatedAt = expectString2(obj.generatedAt, "generatedAt");
  const productId = expectString2(obj.productId, "productId");
  const partnerId = obj.partnerId !== void 0 ? expectString2(obj.partnerId, "partnerId") : void 0;
  const runId = expectString2(obj.runId, "runId");
  const grantIds = expectStringArray(obj.grantIds, "grantIds");
  const traceEnvelope = validateWorkflowTraceEnvelope(obj.traceEnvelope);
  if (traceEnvelope.runId !== runId) {
    throw new ValidationError(`workflow intelligence runId ${runId} does not match trace envelope`);
  }
  const summary = summarizeWorkflowExecution(traceEnvelope);
  const compact = validateCompactEvidence(obj.compactEvidence);
  const expectedCompact = compactEvidence(traceEnvelope, summary);
  assertCompactEvidenceEqual(compact, expectedCompact);
  const sanitization = validateSanitizationReport(obj.sanitization);
  return {
    schemaVersion: ENVELOPE_VERSION,
    destination,
    generatedAt,
    productId,
    ...partnerId ? { partnerId } : {},
    runId,
    grantIds,
    traceEnvelope,
    summary,
    compactEvidence: expectedCompact,
    sanitization,
    ...obj.links !== void 0 ? { links: validateLinks(obj.links) } : {}
  };
}
function activeExportGrantIds(args) {
  if (!Array.isArray(args.grants) || args.grants.length === 0) {
    throw new ValidationError("workflow intelligence export requires at least one opt-in grant");
  }
  const nowMs = Number.isFinite(args.nowMs) ? args.nowMs : Date.now();
  const ids = args.grants.filter((grant) => grantMatchesSubject(grant, args.productId, args.partnerId)).filter((grant) => grant.scopes.includes("workflow-trace:export") || grant.scopes.includes("*")).filter((grant) => !grantExpired(grant, nowMs)).map((grant) => grant.grantId).filter((id) => id.length > 0);
  if (ids.length === 0) {
    throw new ValidationError(
      "workflow intelligence export requires an active workflow-trace:export grant for the product or partner"
    );
  }
  return ids;
}
function grantMatchesSubject(grant, productId, partnerId) {
  if (grant.subject === "product") return grant.subjectId === productId;
  if (grant.subject === "partner") return partnerId !== void 0 && grant.subjectId === partnerId;
  return grant.subjectId === productId || grant.subjectId === partnerId;
}
function grantExpired(grant, nowMs) {
  if (!grant.expiresAt) return false;
  const expiresAt = Date.parse(grant.expiresAt);
  return Number.isFinite(expiresAt) && expiresAt <= nowMs;
}
function compactEvidence(envelope, summary) {
  return {
    eventKinds: summary.eventKinds,
    phases: summary.phases,
    toolNames: toolNames(envelope.events),
    redactedHashes: redactedHashes(envelope),
    artifacts: (envelope.artifacts ?? []).map((artifact) => ({
      kind: artifact.kind,
      uri: artifact.uri,
      ...artifact.contentType ? { contentType: artifact.contentType } : {},
      ...artifact.sha256 ? { sha256: artifact.sha256 } : {}
    })),
    ...summary.failureMessage ? { failureMessage: summary.failureMessage } : {}
  };
}
function toolNames(events) {
  const names = /* @__PURE__ */ new Set();
  for (const event of events) collectToolNames(event.payload, names);
  return [...names].sort();
}
function collectToolNames(value, names) {
  if (Array.isArray(value)) {
    value.forEach((item) => {
      collectToolNames(item, names);
    });
    return;
  }
  if (!isRecord3(value)) return;
  const direct = stringValue2(value.toolName) ?? stringValue2(value.name);
  if (direct && looksLikeToolRecord(value)) names.add(direct);
  if (isRecord3(value.byTool)) {
    for (const key of Object.keys(value.byTool)) names.add(key);
  }
  for (const child of Object.values(value)) collectToolNames(child, names);
}
function looksLikeToolRecord(value) {
  return "toolName" in value || "toolArgs" in value || "args" in value || "status" in value || "error" in value || "success" in value;
}
function redactedHashes(envelope) {
  const out = [];
  envelope.events.forEach((event, index) => {
    collectHashEvidence(event.payload, `events[${index}].payload`, out);
  });
  const artifacts = envelope.artifacts ?? [];
  artifacts.forEach((artifact, index) => {
    collectHashEvidence(artifact.metadata, `artifacts[${index}].metadata`, out);
  });
  collectHashEvidence(envelope.metadata, "metadata", out);
  return out;
}
function collectHashEvidence(value, path, out) {
  if (Array.isArray(value)) {
    value.forEach((item, index) => {
      collectHashEvidence(item, `${path}[${index}]`, out);
    });
    return;
  }
  if (!isRecord3(value)) return;
  if (value.redacted === true && typeof value.sha256 === "string") {
    out.push({
      path,
      sha256: value.sha256,
      ...value.shape !== void 0 ? { shape: value.shape } : {}
    });
    return;
  }
  for (const [key, child] of Object.entries(value)) {
    collectHashEvidence(child, `${path}.${key}`, out);
  }
}
function validateCompactEvidence(value) {
  const obj = expectRecord2(value, "compactEvidence");
  return {
    eventKinds: expectNumberRecord(obj.eventKinds, "compactEvidence.eventKinds"),
    phases: expectStringArray(obj.phases, "compactEvidence.phases"),
    toolNames: expectStringArray(obj.toolNames, "compactEvidence.toolNames"),
    redactedHashes: expectArray(obj.redactedHashes, "compactEvidence.redactedHashes").map(
      (item, index) => {
        const record = expectRecord2(item, `compactEvidence.redactedHashes[${index}]`);
        return {
          path: expectString2(record.path, `compactEvidence.redactedHashes[${index}].path`),
          sha256: expectString2(record.sha256, `compactEvidence.redactedHashes[${index}].sha256`),
          ...record.shape !== void 0 ? { shape: record.shape } : {}
        };
      }
    ),
    artifacts: expectArray(obj.artifacts, "compactEvidence.artifacts").map((item, index) => {
      const record = expectRecord2(item, `compactEvidence.artifacts[${index}]`);
      return {
        kind: expectString2(record.kind, `compactEvidence.artifacts[${index}].kind`),
        uri: expectString2(record.uri, `compactEvidence.artifacts[${index}].uri`),
        ...record.contentType !== void 0 ? {
          contentType: expectString2(
            record.contentType,
            `compactEvidence.artifacts[${index}].contentType`
          )
        } : {},
        ...record.sha256 !== void 0 ? {
          sha256: expectString2(record.sha256, `compactEvidence.artifacts[${index}].sha256`)
        } : {}
      };
    }),
    ...obj.failureMessage !== void 0 ? { failureMessage: expectString2(obj.failureMessage, "compactEvidence.failureMessage") } : {}
  };
}
function assertCompactEvidenceEqual(actual, expected) {
  assertNumberRecordEqual(actual.eventKinds, expected.eventKinds, "compactEvidence.eventKinds");
  assertStringArrayEqual(actual.phases, expected.phases, "compactEvidence.phases");
  assertStringArrayEqual(actual.toolNames, expected.toolNames, "compactEvidence.toolNames");
  assertJsonArrayEqual(
    actual.redactedHashes,
    expected.redactedHashes,
    "compactEvidence.redactedHashes"
  );
  assertJsonArrayEqual(actual.artifacts, expected.artifacts, "compactEvidence.artifacts");
  if (actual.failureMessage !== expected.failureMessage) {
    throw new ValidationError("compactEvidence.failureMessage does not match trace envelope");
  }
}
function validateSanitizationReport(value) {
  const obj = expectRecord2(value, "sanitization");
  return {
    redactionCount: expectNonNegativeNumber(obj.redactionCount, "sanitization.redactionCount"),
    byRule: expectNumberRecord(obj.byRule, "sanitization.byRule"),
    hashedArgs: expectNonNegativeNumber(obj.hashedArgs, "sanitization.hashedArgs"),
    truncatedStrings: expectNonNegativeNumber(
      obj.truncatedStrings,
      "sanitization.truncatedStrings"
    ),
    droppedPayloadKeys: expectNumberRecord(
      obj.droppedPayloadKeys,
      "sanitization.droppedPayloadKeys"
    ),
    droppedArtifactContents: expectNonNegativeNumber(
      obj.droppedArtifactContents,
      "sanitization.droppedArtifactContents"
    )
  };
}
function validateLinks(value) {
  const obj = expectRecord2(value, "links");
  return {
    ...obj.traceArtifactUri !== void 0 ? { traceArtifactUri: expectString2(obj.traceArtifactUri, "links.traceArtifactUri") } : {},
    ...obj.exportBundleUri !== void 0 ? { exportBundleUri: expectString2(obj.exportBundleUri, "links.exportBundleUri") } : {},
    ...obj.partnerReportUri !== void 0 ? { partnerReportUri: expectString2(obj.partnerReportUri, "links.partnerReportUri") } : {},
    ...obj.intelligenceRunUri !== void 0 ? { intelligenceRunUri: expectString2(obj.intelligenceRunUri, "links.intelligenceRunUri") } : {}
  };
}
function requireNonEmpty(value, field) {
  if (typeof value !== "string" || value.length === 0) {
    throw new ValidationError(`workflow intelligence ${field} must be a non-empty string`);
  }
  return value;
}
function expectRecord2(value, path) {
  if (!isRecord3(value)) throw new ValidationError(`${path}: expected object`);
  return value;
}
function expectArray(value, path) {
  if (!Array.isArray(value)) throw new ValidationError(`${path}: expected array`);
  return value;
}
function expectStringArray(value, path) {
  return expectArray(value, path).map((item, index) => expectString2(item, `${path}[${index}]`));
}
function expectNumberRecord(value, path) {
  const record = expectRecord2(value, path);
  const out = {};
  for (const [key, item] of Object.entries(record)) {
    out[key] = expectNonNegativeNumber(item, `${path}.${key}`);
  }
  return out;
}
function expectString2(value, path) {
  if (typeof value !== "string" || value.length === 0) {
    throw new ValidationError(`${path}: expected non-empty string`);
  }
  return value;
}
function expectNonNegativeNumber(value, path) {
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
    throw new ValidationError(`${path}: expected non-negative number`);
  }
  return value;
}
function assertNumberRecordEqual(actual, expected, path) {
  const actualKeys = Object.keys(actual).sort();
  const expectedKeys = Object.keys(expected).sort();
  assertStringArrayEqual(actualKeys, expectedKeys, path);
  for (const key of expectedKeys) {
    if (actual[key] !== expected[key]) {
      throw new ValidationError(`${path}.${key} does not match trace envelope`);
    }
  }
}
function assertStringArrayEqual(actual, expected, path) {
  if (actual.length !== expected.length || actual.some((item, index) => item !== expected[index])) {
    throw new ValidationError(`${path} does not match trace envelope`);
  }
}
function assertJsonArrayEqual(actual, expected, path) {
  if (actual.length !== expected.length || actual.some((item, index) => JSON.stringify(item) !== JSON.stringify(expected[index]))) {
    throw new ValidationError(`${path} does not match trace envelope`);
  }
}
function stringValue2(value) {
  return typeof value === "string" && value.length > 0 ? value : void 0;
}
function isRecord3(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

// src/workflow/run-record.ts
function workflowTraceToRunRecord(input, options) {
  const envelope = validateWorkflowTraceEnvelope(input);
  const summary = summarizeWorkflowTrace(envelope);
  const score = clampScore(options.score ?? (summary.failed ? 0 : 1));
  const raw = {
    ...finiteOnly(options.raw ?? {}),
    score,
    workflow_failed: summary.failed ? 1 : 0,
    workflow_events: summary.eventCount,
    workflow_phases: summary.phaseCount,
    workflow_branches: summary.branchCount,
    workflow_branch_failures: summary.failedBranchCount,
    workflow_agent_calls: summary.agentCalls,
    workflow_loop_calls: summary.loopCalls,
    workflow_verifier_calls: summary.verifierCalls,
    workflow_analyst_calls: summary.analystCalls,
    workflow_reviewer_calls: summary.reviewerCalls,
    workflow_agent_failures: summary.agentFailures,
    workflow_loop_failures: summary.loopFailures,
    workflow_verifier_failures: summary.verifierFailures,
    workflow_analyst_failures: summary.analystFailures,
    workflow_reviewer_failures: summary.reviewerFailures
  };
  const outcome = options.splitTag === "holdout" ? { holdoutScore: score, raw } : { searchScore: score, raw };
  return validateRunRecord({
    runId: options.runId ?? envelope.runId,
    experimentId: options.experimentId,
    candidateId: options.candidateId,
    seed: options.seed,
    model: options.model,
    promptHash: options.promptHash,
    configHash: options.configHash,
    commitSha: options.commitSha,
    wallMs: summary.durationMs,
    costUsd: summary.costUsd,
    tokenUsage: summary.tokenUsage,
    ...options.judgeMetadata ? { judgeMetadata: options.judgeMetadata } : {},
    outcome,
    failureMode: options.failureMode ?? (summary.failed ? "workflow_failed" : void 0),
    splitTag: options.splitTag,
    ...options.scenarioId ? { scenarioId: options.scenarioId } : {},
    ...options.agentProfile ? { agentProfile: options.agentProfile } : {}
  });
}
function finiteOnly(values) {
  const out = {};
  for (const [key, value] of Object.entries(values)) {
    if (Number.isFinite(value)) out[key] = value;
  }
  return out;
}
function clampScore(value) {
  if (!Number.isFinite(value)) return 0;
  return Math.max(0, Math.min(1, value));
}

// src/workflow/trajectory.ts
function workflowTraceToFeedbackTrajectory(input, options) {
  const envelope = validateWorkflowTraceEnvelope(input);
  const summary = summarizeWorkflowTrace(envelope);
  const createdAt = iso(envelope.events[0]?.timestamp);
  const updatedAt = iso(envelope.events.at(-1)?.timestamp);
  return {
    id: envelope.runId,
    projectId: options.projectId,
    scenarioId: options.scenarioId,
    task: {
      intent: options.task,
      context: {
        topology: envelope.topology,
        metadata: envelope.metadata
      }
    },
    attempts: workflowEventsToAttempts(envelope.events),
    labels: [],
    outcome: {
      success: options.success ?? !summary.failed,
      score: options.score,
      costUsd: summary.costUsd,
      observedAt: updatedAt,
      detail: summary.failureMessage,
      metrics: {
        workflow_events: summary.eventCount,
        workflow_phases: summary.phaseCount,
        workflow_branches: summary.branchCount,
        workflow_branch_failures: summary.failedBranchCount,
        workflow_agent_calls: summary.agentCalls,
        workflow_loop_calls: summary.loopCalls,
        workflow_verifier_calls: summary.verifierCalls,
        workflow_analyst_calls: summary.analystCalls,
        workflow_reviewer_calls: summary.reviewerCalls,
        workflow_agent_failures: summary.agentFailures,
        workflow_loop_failures: summary.loopFailures,
        workflow_verifier_failures: summary.verifierFailures,
        workflow_analyst_failures: summary.analystFailures,
        workflow_reviewer_failures: summary.reviewerFailures,
        workflow_tokens_input: summary.tokenUsage.input,
        workflow_tokens_output: summary.tokenUsage.output
      },
      metadata: {
        durationMs: summary.durationMs,
        ...options.metadata ?? {}
      }
    },
    split: options.split,
    tags: options.tags,
    createdAt,
    updatedAt,
    metadata: {
      traceVersion: envelope.traceVersion,
      artifacts: envelope.artifacts
    }
  };
}
function workflowEventsToAttempts(events) {
  const attempts = [];
  for (const event of events) {
    const artifactType = artifactTypeForWorkflowEvent(event.kind);
    if (!artifactType) continue;
    const stepIndex = attempts.length;
    attempts.push({
      id: `${event.runId}:${stepIndex}`,
      stepIndex,
      artifactType,
      artifact: event.payload.trace ?? event.payload,
      createdAt: iso(event.timestamp),
      metadata: {
        eventKind: event.kind,
        label: event.payload.label,
        phase: event.payload.phase,
        costUsd: event.payload.costUsd,
        tokenUsage: event.payload.tokenUsage,
        ...event.kind.endsWith(".failed") ? { failed: true, message: event.payload.message, code: event.payload.code } : {}
      }
    });
  }
  return attempts;
}
function artifactTypeForWorkflowEvent(kind) {
  switch (kind) {
    case "workflow.agent.ended":
    case "workflow.agent.failed":
      return "action";
    case "workflow.analyst.ended":
    case "workflow.analyst.failed":
      return "data";
    case "workflow.loop.ended":
    case "workflow.verifier.ended":
    case "workflow.reviewer.ended":
    case "workflow.loop.failed":
    case "workflow.verifier.failed":
    case "workflow.reviewer.failed":
      return "decision";
    default:
      return null;
  }
}
function iso(timestamp) {
  return new Date(Number.isFinite(timestamp) ? timestamp : 0).toISOString();
}

// src/workflow/partner-report.ts
var REPORT_VERSION = "workflow-partner-report-v1";
function buildWorkflowPartnerReport(options) {
  const sanitized = sanitizeWorkflowTraceEnvelope(options.envelope, options.sanitize);
  const feedbackPack = buildWorkflowAnalystFeedbackPack({
    ...options,
    envelope: sanitized.envelope
  });
  const trajectory = workflowTraceToFeedbackTrajectory(sanitized.envelope, options.trajectory);
  const runRecord = options.runRecord ? workflowTraceToRunRecord(sanitized.envelope, {
    ...options.runRecord,
    runId: sanitized.envelope.runId
  }) : void 0;
  const analystFindings = feedbackPack.findings.map((finding) => ({
    source: "analyst",
    severity: finding.severity,
    area: finding.area,
    claim: finding.claim,
    evidence: finding.evidenceRefs,
    ...finding.recommendedAction ? { recommendedAction: finding.recommendedAction } : {},
    metadata: {
      findingId: finding.findingId,
      analystId: finding.analystId,
      confidence: finding.confidence,
      ...finding.subject ? { subject: finding.subject } : {}
    }
  }));
  const verifierFindings = (feedbackPack.verifier?.layers ?? []).flatMap(
    (layer) => layer.findings.map((finding) => ({
      source: "verifier",
      severity: finding.severity,
      area: layer.layer,
      claim: finding.message,
      evidence: finding.evidence ? [{ kind: "artifact", uri: finding.evidence }] : [],
      ...layer.reason ? { recommendedAction: `Fix verifier layer "${layer.layer}": ${layer.reason}` } : {},
      metadata: {
        status: layer.status,
        score: layer.score
      }
    }))
  );
  const clusterFindings = feedbackPack.failureClusters.map((cluster) => ({
    source: "failure-cluster",
    severity: "medium",
    area: "failure-cluster",
    claim: `${cluster.name} affects ${(cluster.share * 100).toFixed(1)}% of failed workflow runs`,
    evidence: cluster.exemplars.map((runId) => ({
      kind: "artifact",
      uri: `run://${runId}`
    })),
    ...cluster.suggestedFix ? { recommendedAction: cluster.suggestedFix } : {},
    metadata: {
      clusterId: cluster.id,
      runCount: cluster.runCount,
      source: cluster.source
    }
  }));
  const allFindings = [...analystFindings, ...verifierFindings, ...clusterFindings].sort(
    comparePartnerFindings
  );
  return {
    schemaVersion: REPORT_VERSION,
    runId: sanitized.envelope.runId,
    generatedAt: options.generatedAt ?? feedbackPack.generatedAt,
    summary: feedbackPack.summary,
    docsApiGaps: allFindings.filter(isDocsApiGap),
    prReadyFindings: allFindings.filter(isPrReadyFinding),
    failureClusters: feedbackPack.failureClusters,
    recommendations: feedbackPack.recommendations,
    traceArtifacts: sanitized.envelope.artifacts,
    ...options.links ? { links: options.links } : {},
    exportBundle: {
      traceEnvelope: sanitized.envelope,
      sanitization: sanitized.report,
      feedbackPack,
      trajectory,
      ...runRecord ? { runRecord } : {}
    }
  };
}
function validateWorkflowPartnerReport(input) {
  const obj = expectRecord3(input, "workflow partner report");
  if (obj.schemaVersion !== REPORT_VERSION) {
    throw new ValidationError(`workflow partner report schemaVersion must be ${REPORT_VERSION}`);
  }
  const runId = expectString3(obj.runId, "runId");
  const generatedAt = expectString3(obj.generatedAt, "generatedAt");
  const exportBundle = validateExportBundle(obj.exportBundle, runId);
  const expectedSummary = summarizeWorkflowTrace(exportBundle.traceEnvelope);
  assertJsonEqual(expectRecord3(obj.summary, "summary"), expectedSummary, "summary");
  assertJsonEqual(
    exportBundle.feedbackPack.summary,
    expectedSummary,
    "exportBundle.feedbackPack.summary"
  );
  const traceArtifacts = validateOptionalArtifacts(obj.traceArtifacts, "traceArtifacts");
  assertJsonEqual(
    traceArtifacts ?? [],
    exportBundle.traceEnvelope.artifacts ?? [],
    "traceArtifacts"
  );
  return {
    schemaVersion: REPORT_VERSION,
    runId,
    generatedAt,
    summary: expectedSummary,
    docsApiGaps: expectArray2(obj.docsApiGaps, "docsApiGaps"),
    prReadyFindings: expectArray2(
      obj.prReadyFindings,
      "prReadyFindings"
    ),
    failureClusters: expectArray2(
      obj.failureClusters,
      "failureClusters"
    ),
    recommendations: expectStringArray2(obj.recommendations, "recommendations"),
    traceArtifacts,
    ...obj.links !== void 0 ? { links: validateLinks2(obj.links) } : {},
    exportBundle
  };
}
function renderWorkflowPartnerReport(report, options = {}) {
  const maxFindings = options.maxFindings ?? 8;
  const lines = [
    `Workflow partner report for ${report.runId}`,
    `status=${report.summary.failed ? "failed" : "completed"} scoreEvidence events=${report.summary.eventCount} agents=${report.summary.agentCalls} verifier=${report.summary.verifierCalls} analyst=${report.summary.analystCalls} reviewer=${report.summary.reviewerCalls} costUsd=${report.summary.costUsd.toFixed(6)}`,
    report.failureClusters.length > 0 ? "Failure clusters:" : void 0,
    ...report.failureClusters.slice(0, maxFindings).map(
      (cluster) => `- ${cluster.name} share=${cluster.share.toFixed(3)} exemplars=${cluster.exemplars.join(",")}`
    ),
    report.docsApiGaps.length > 0 ? "Docs/API gaps:" : void 0,
    ...report.docsApiGaps.slice(0, maxFindings).map((finding) => `- ${finding.severity} ${finding.area}: ${finding.claim}`),
    report.prReadyFindings.length > 0 ? "PR-ready findings:" : void 0,
    ...report.prReadyFindings.slice(0, maxFindings).map((finding) => `- ${finding.severity} ${finding.area}: ${finding.claim}`),
    report.recommendations.length > 0 ? "Recommendations:" : void 0,
    ...report.recommendations.slice(0, maxFindings).map((recommendation) => `- ${recommendation}`)
  ].filter((line) => Boolean(line));
  return lines.join("\n");
}
function validateExportBundle(value, runId) {
  const obj = expectRecord3(value, "exportBundle");
  const traceEnvelope = validateWorkflowTraceEnvelope(obj.traceEnvelope);
  if (traceEnvelope.runId !== runId) {
    throw new ValidationError("exportBundle.traceEnvelope.runId must match report runId");
  }
  const feedbackPack = expectRecord3(obj.feedbackPack, "exportBundle.feedbackPack");
  if (feedbackPack.schemaVersion !== "workflow-feedback-pack-v1") {
    throw new ValidationError(
      "exportBundle.feedbackPack.schemaVersion must be workflow-feedback-pack-v1"
    );
  }
  if (feedbackPack.runId !== runId) {
    throw new ValidationError("exportBundle.feedbackPack.runId must match report runId");
  }
  expectRecord3(feedbackPack.toolUsage, "exportBundle.feedbackPack.toolUsage");
  expectArray2(feedbackPack.failureClusters, "exportBundle.feedbackPack.failureClusters");
  expectArray2(feedbackPack.findings, "exportBundle.feedbackPack.findings");
  expectStringArray2(feedbackPack.recommendations, "exportBundle.feedbackPack.recommendations");
  expectStringArray2(feedbackPack.driverContextLines, "exportBundle.feedbackPack.driverContextLines");
  const trajectory = expectRecord3(obj.trajectory, "exportBundle.trajectory");
  if (trajectory.id !== runId) {
    throw new ValidationError("exportBundle.trajectory.id must match report runId");
  }
  expectArray2(trajectory.attempts, "exportBundle.trajectory.attempts");
  expectArray2(trajectory.labels, "exportBundle.trajectory.labels");
  const runRecord = obj.runRecord === void 0 ? void 0 : validateWorkflowRunRecord(obj.runRecord, traceEnvelope);
  expectRecord3(obj.sanitization, "exportBundle.sanitization");
  return {
    traceEnvelope,
    sanitization: obj.sanitization,
    feedbackPack: obj.feedbackPack,
    trajectory: obj.trajectory,
    ...runRecord ? { runRecord } : {}
  };
}
function validateWorkflowRunRecord(value, envelope) {
  const record = validateRunRecord(value);
  const summary = summarizeWorkflowTrace(envelope);
  if (record.runId !== envelope.runId) {
    throw new ValidationError("exportBundle.runRecord.runId must match trace envelope runId");
  }
  if (record.outcome.raw.workflow_events !== summary.eventCount) {
    throw new ValidationError("exportBundle.runRecord outcome does not match trace event count");
  }
  return record;
}
function validateLinks2(value) {
  const obj = expectRecord3(value, "links");
  return {
    ...obj.traceArtifactUri !== void 0 ? { traceArtifactUri: expectString3(obj.traceArtifactUri, "links.traceArtifactUri") } : {},
    ...obj.exportBundleUri !== void 0 ? { exportBundleUri: expectString3(obj.exportBundleUri, "links.exportBundleUri") } : {},
    ...obj.partnerReportUri !== void 0 ? { partnerReportUri: expectString3(obj.partnerReportUri, "links.partnerReportUri") } : {},
    ...obj.intelligenceRunUri !== void 0 ? { intelligenceRunUri: expectString3(obj.intelligenceRunUri, "links.intelligenceRunUri") } : {}
  };
}
function validateOptionalArtifacts(value, path) {
  if (value === void 0) return void 0;
  return expectArray2(value, path).map((item, index) => {
    const itemPath = `${path}[${index}]`;
    const obj = expectRecord3(item, itemPath);
    return {
      kind: expectString3(obj.kind, `${itemPath}.kind`),
      uri: expectString3(obj.uri, `${itemPath}.uri`),
      ...obj.contentType !== void 0 ? { contentType: expectString3(obj.contentType, `${itemPath}.contentType`) } : {},
      ...obj.sha256 !== void 0 ? { sha256: expectString3(obj.sha256, `${itemPath}.sha256`) } : {},
      ...obj.metadata !== void 0 ? { metadata: expectRecord3(obj.metadata, `${itemPath}.metadata`) } : {}
    };
  });
}
function expectRecord3(value, path) {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    throw new ValidationError(`${path}: expected object`);
  }
  return value;
}
function expectArray2(value, path) {
  if (!Array.isArray(value)) throw new ValidationError(`${path}: expected array`);
  return value;
}
function expectString3(value, path) {
  if (typeof value !== "string" || value.length === 0) {
    throw new ValidationError(`${path}: expected non-empty string`);
  }
  return value;
}
function expectStringArray2(value, path) {
  return expectArray2(value, path).map((item, index) => expectString3(item, `${path}[${index}]`));
}
function assertJsonEqual(actual, expected, path) {
  if (JSON.stringify(stableJson(actual)) !== JSON.stringify(stableJson(expected))) {
    throw new ValidationError(`${path} does not match trace envelope`);
  }
}
function stableJson(value) {
  if (Array.isArray(value)) return value.map(stableJson);
  if (!value || typeof value !== "object") return value;
  return Object.fromEntries(
    Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => [key, stableJson(child)])
  );
}
function isDocsApiGap(finding) {
  const haystack = [
    finding.area,
    finding.claim,
    finding.recommendedAction,
    typeof finding.metadata?.subject === "string" ? finding.metadata.subject : void 0
  ].filter(Boolean).join(" ").toLowerCase();
  return /\b(api|sdk|docs?|documentation|reference|integration|example|quickstart)\b/.test(haystack);
}
function isPrReadyFinding(finding) {
  return finding.recommendedAction !== void 0 || finding.severity === "critical" || finding.severity === "high";
}
function comparePartnerFindings(left, right) {
  const severityDelta = severityRank2(right.severity) - severityRank2(left.severity);
  if (severityDelta !== 0) return severityDelta;
  return left.area.localeCompare(right.area);
}
function severityRank2(severity) {
  switch (severity) {
    case "critical":
      return 5;
    case "high":
      return 4;
    case "medium":
      return 3;
    case "low":
      return 2;
    case "info":
      return 1;
  }
}

// src/workflow/promotion-gate.ts
var DECISION_VERSION = "workflow-driver-promotion-v1";
var DEFAULT_BASELINE_STRATEGY = "reviewer-loop-v1";
var DEFAULT_CANDIDATE_STRATEGY = "workflow-driver-v1";
function decideWorkflowDriverPromotion(options) {
  const records = options.records.map(validateRunRecord);
  const baselineStrategyId = options.baselineStrategyId ?? DEFAULT_BASELINE_STRATEGY;
  const candidateStrategyId = options.candidateStrategyId ?? DEFAULT_CANDIDATE_STRATEGY;
  const confidence = options.confidence ?? 0.95;
  const resamples = options.resamples ?? 2e3;
  const statistic = options.statistic ?? "mean";
  const deltaThreshold = options.deltaThreshold ?? 0;
  const minPairedHoldoutRuns = options.minPairedHoldoutRuns ?? 3;
  validateOptions({ confidence, resamples, deltaThreshold, minPairedHoldoutRuns }, options);
  const baseline = records.filter((record) => record.candidateId === baselineStrategyId);
  const candidate = records.filter((record) => record.candidateId === candidateStrategyId);
  const baselineHoldout = baseline.filter(isScoredHoldout);
  const candidateHoldout = candidate.filter(isScoredHoldout);
  const expectedScenarioIds = expectedScenarios(options.expectedScenarioIds, [
    ...baselineHoldout,
    ...candidateHoldout
  ]);
  const expectedScenarioIdSet = new Set(expectedScenarioIds);
  const pairs = pairHoldoutRuns(baselineHoldout, candidateHoldout).filter(
    (pair) => expectedScenarioIdSet.size === 0 || expectedScenarioIdSet.has(pair.scenarioId)
  );
  const pairedScenarioIds = [...new Set(pairs.map((pair) => pair.scenarioId))].sort();
  const missingScenarioIds = expectedScenarioIds.filter((id) => !pairedScenarioIds.includes(id));
  const evidence = buildEvidence({
    pairs,
    expectedScenarioIds,
    pairedScenarioIds,
    missingScenarioIds,
    baseline,
    candidate,
    confidence,
    resamples,
    statistic,
    deltaThreshold,
    seed: options.seed
  });
  if (baselineHoldout.length === 0) {
    return decision({
      options,
      baselineStrategyId,
      candidateStrategyId,
      evidence,
      promote: false,
      rejectionCode: "missing_baseline_records",
      reason: `missing_baseline_records: no holdout RunRecords for baseline "${baselineStrategyId}"`
    });
  }
  if (candidateHoldout.length === 0) {
    return decision({
      options,
      baselineStrategyId,
      candidateStrategyId,
      evidence,
      promote: false,
      rejectionCode: "missing_candidate_records",
      reason: `missing_candidate_records: no holdout RunRecords for candidate "${candidateStrategyId}"`
    });
  }
  if (missingScenarioIds.length > 0) {
    return decision({
      options,
      baselineStrategyId,
      candidateStrategyId,
      evidence,
      promote: false,
      rejectionCode: "missing_holdout_pairs",
      reason: `missing_holdout_pairs: no paired baseline/candidate holdout record for scenario(s) [${missingScenarioIds.join(", ")}]`
    });
  }
  if (pairs.length < minPairedHoldoutRuns) {
    return decision({
      options,
      baselineStrategyId,
      candidateStrategyId,
      evidence,
      promote: false,
      rejectionCode: "few_pairs",
      reason: `few_pairs: ${pairs.length} paired holdout run(s) < min ${minPairedHoldoutRuns}`
    });
  }
  if (!(evidence.liftCi.low > deltaThreshold)) {
    return decision({
      options,
      baselineStrategyId,
      candidateStrategyId,
      evidence,
      promote: false,
      rejectionCode: "insufficient_lift",
      reason: `insufficient_lift: heldout ${statistic} lift=${fmt(evidence.lift)} CI=[${fmt(evidence.liftCi.low)}, ${fmt(evidence.liftCi.high)}] does not clear threshold ${fmt(deltaThreshold)}`
    });
  }
  if (options.costPerRunCeiling !== void 0 && Number.isFinite(evidence.candidateMedianCostUsd) && evidence.candidateMedianCostUsd > options.costPerRunCeiling) {
    return decision({
      options,
      baselineStrategyId,
      candidateStrategyId,
      evidence,
      promote: false,
      rejectionCode: "cost_ceiling",
      reason: `cost_ceiling: candidate median cost $${fmt(evidence.candidateMedianCostUsd)} exceeds ceiling $${fmt(options.costPerRunCeiling)}`
    });
  }
  return decision({
    options,
    baselineStrategyId,
    candidateStrategyId,
    evidence,
    promote: true,
    rejectionCode: null,
    reason: `promote: ${candidateStrategyId} beats ${baselineStrategyId} on paired heldout workflows lift=${fmt(evidence.lift)} CI=[${fmt(evidence.liftCi.low)}, ${fmt(evidence.liftCi.high)}] over ${pairs.length} pair(s)`
  });
}
function validateOptions(normalized, options) {
  if (options.records.length === 0) {
    throw new ValidationError("workflow promotion gate requires at least one RunRecord");
  }
  if (normalized.confidence <= 0 || normalized.confidence >= 1) {
    throw new ValidationError("workflow promotion gate confidence must be in (0,1)");
  }
  if (!Number.isInteger(normalized.resamples) || normalized.resamples <= 0) {
    throw new ValidationError("workflow promotion gate resamples must be a positive integer");
  }
  if (!Number.isFinite(normalized.deltaThreshold)) {
    throw new ValidationError("workflow promotion gate deltaThreshold must be finite");
  }
  if (!Number.isInteger(normalized.minPairedHoldoutRuns) || normalized.minPairedHoldoutRuns < 1) {
    throw new ValidationError(
      "workflow promotion gate minPairedHoldoutRuns must be a positive integer"
    );
  }
  if (options.costPerRunCeiling !== void 0 && (!Number.isFinite(options.costPerRunCeiling) || options.costPerRunCeiling <= 0)) {
    throw new ValidationError("workflow promotion gate costPerRunCeiling must be positive");
  }
}
function isScoredHoldout(record) {
  return record.splitTag === "holdout" && typeof record.outcome.holdoutScore === "number";
}
function expectedScenarios(requested, records) {
  const values = (requested ?? records.map((record) => record.scenarioId)).filter(isString);
  return [...new Set(values)].sort();
}
function pairHoldoutRuns(baseline, candidate) {
  const baselineByKey = indexByPairKey(baseline, "baseline");
  const out = [];
  for (const candidateRun of candidate) {
    const key = holdoutPairKey(candidateRun, "candidate");
    const baselineRun = baselineByKey.get(key);
    if (!baselineRun) continue;
    const baselineScore = baselineRun.outcome.holdoutScore;
    const candidateScore = candidateRun.outcome.holdoutScore;
    out.push({
      key,
      scenarioId: candidateRun.scenarioId,
      seed: candidateRun.seed,
      baselineRunId: baselineRun.runId,
      candidateRunId: candidateRun.runId,
      baselineScore,
      candidateScore,
      delta: candidateScore - baselineScore
    });
  }
  return out.sort((a, b) => a.key.localeCompare(b.key));
}
function indexByPairKey(records, side) {
  const out = /* @__PURE__ */ new Map();
  for (const record of records) {
    const key = holdoutPairKey(record, side);
    if (out.has(key)) {
      throw new ValidationError(
        `workflow promotion gate duplicate ${side} holdout pair key: ${key}`
      );
    }
    out.set(key, record);
  }
  return out;
}
function holdoutPairKey(record, side) {
  if (!record.scenarioId) {
    throw new ValidationError(
      `workflow promotion gate ${side} holdout RunRecord ${record.runId} is missing scenarioId`
    );
  }
  return `${record.scenarioId}::${record.seed}`;
}
function buildEvidence(args) {
  const before = args.pairs.map((pair) => pair.baselineScore);
  const after = args.pairs.map((pair) => pair.candidateScore);
  const bootstrap = pairedBootstrap(before, after, {
    confidence: args.confidence,
    resamples: args.resamples,
    statistic: args.statistic,
    ...args.seed !== void 0 ? { seed: args.seed } : {}
  });
  return {
    pairedRuns: args.pairs.length,
    expectedScenarioIds: args.expectedScenarioIds,
    pairedScenarioIds: args.pairedScenarioIds,
    missingScenarioIds: args.missingScenarioIds,
    baselineMean: mean(before),
    candidateMean: mean(after),
    lift: args.statistic === "mean" ? bootstrap.mean : bootstrap.median,
    liftCi: { low: bootstrap.low, high: bootstrap.high },
    bootstrap,
    confidence: args.confidence,
    resamples: args.resamples,
    statistic: args.statistic,
    deltaThreshold: args.deltaThreshold,
    baselineMedianCostUsd: medianFinite(args.baseline.map((record) => record.costUsd)),
    candidateMedianCostUsd: medianFinite(args.candidate.map((record) => record.costUsd)),
    pairs: [...args.pairs]
  };
}
function decision(args) {
  return {
    schemaVersion: DECISION_VERSION,
    generatedAt: args.options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
    baselineStrategyId: args.baselineStrategyId,
    candidateStrategyId: args.candidateStrategyId,
    promote: args.promote,
    rejectionCode: args.rejectionCode,
    reason: args.reason,
    evidence: args.evidence
  };
}
function mean(values) {
  if (values.length === 0) return Number.NaN;
  return values.reduce((sum, value) => sum + value, 0) / values.length;
}
function medianFinite(values) {
  const finite = values.filter(Number.isFinite).sort((a, b) => a - b);
  if (finite.length === 0) return Number.NaN;
  const mid = Math.floor(finite.length / 2);
  return finite.length % 2 === 0 ? (finite[mid - 1] + finite[mid]) / 2 : finite[mid];
}
function fmt(value) {
  if (!Number.isFinite(value)) return String(value);
  return value.toFixed(4);
}
function isString(value) {
  return typeof value === "string" && value.length > 0;
}

// src/workflow/runtime-adapter.ts
function workflowEventsToTraceEnvelope(events, options = {}) {
  if (!Array.isArray(events) || events.length === 0) {
    throw new ValidationError("workflow trace events must be a non-empty array");
  }
  const first = validateWorkflowTraceEvent(events[0]);
  const runId = options.runId ?? first.runId;
  return validateWorkflowTraceEnvelope({
    traceVersion: "workflow-trace-v1",
    runId,
    ...options.topology ? { topology: options.topology } : {},
    events,
    ...options.artifacts ? { artifacts: options.artifacts } : {},
    ...options.metadata ? { metadata: options.metadata } : {}
  });
}
function workflowRuntimeResultToTraceEnvelope(result, options = {}) {
  if (!result || typeof result !== "object") {
    throw new ValidationError("workflow runtime result must be an object");
  }
  const metadata = runtimeResultMetadata(result, options);
  return workflowEventsToTraceEnvelope(result.events, {
    runId: options.runId ?? result.runId,
    ...options.topology ? { topology: options.topology } : {},
    ...options.artifacts ? { artifacts: options.artifacts } : {},
    ...metadata ? { metadata } : {}
  });
}
function runtimeResultMetadata(result, options) {
  const runtimeResult = {};
  if (result.meta !== void 0) runtimeResult.meta = result.meta;
  if (options.includeOutputInMetadata && result.output !== void 0) {
    runtimeResult.output = result.output;
  }
  const hasRuntimeMetadata = Object.keys(runtimeResult).length > 0;
  if (!hasRuntimeMetadata && !options.metadata) return void 0;
  return {
    ...options.metadata ?? {},
    ...hasRuntimeMetadata ? { runtimeResult } : {}
  };
}
export {
  WORKFLOW_TRACE_EVENT_KINDS,
  buildWorkflowAnalystFeedbackPack,
  buildWorkflowPartnerReport,
  buildWorkflowTraceIntelligenceEnvelope,
  decideWorkflowDriverPromotion,
  renderWorkflowFeedbackPack,
  renderWorkflowPartnerReport,
  sanitizeWorkflowTraceEnvelope,
  summarizeWorkflowExecution,
  summarizeWorkflowTrace,
  validateWorkflowPartnerReport,
  validateWorkflowTraceEnvelope,
  validateWorkflowTraceEvent,
  validateWorkflowTraceEventKind,
  validateWorkflowTraceEventPayload,
  validateWorkflowTraceIntelligenceEnvelope,
  workflowEventsToTraceEnvelope,
  workflowPhaseGraph,
  workflowRuntimeResultToTraceEnvelope,
  workflowTraceToFeedbackTrajectory,
  workflowTraceToRunRecord
};
//# sourceMappingURL=index.js.map