import {
  statePathsForRunState
} from "./chunk-4FOHZ7JG.js";
import {
  compactRecord,
  isTerminalStatus,
  nonEmptyString,
  recordValue
} from "./chunk-VY4Y5U57.js";

// src/run-card.ts
var RIDDLE_PROOF_RUN_CARD_VERSION = "riddle-proof.run-card.v1";
function elapsedMs(start, end) {
  const startMs = start ? Date.parse(start) : NaN;
  const endMs = end ? Date.parse(end) : NaN;
  if (!Number.isFinite(startMs) || !Number.isFinite(endMs)) return void 0;
  return Math.max(0, endMs - startMs);
}
function jsonCloneRecord(value) {
  const record = recordValue(value);
  if (!record) return void 0;
  try {
    return JSON.parse(JSON.stringify(record));
  } catch {
    return { ...record };
  }
}
function compactText(value, limit = 600) {
  const text = nonEmptyString(value);
  if (!text) return void 0;
  return text.length <= limit ? text : `${text.slice(0, limit - 20).trimEnd()}...`;
}
function numericValue(value) {
  const number = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
  return Number.isFinite(number) ? number : void 0;
}
function eventDetails(event) {
  return recordValue(recordValue(event)?.details) || {};
}
function collectRunnerMetrics(details) {
  const metrics = [];
  const adapterDetails = recordValue(details.adapter_details);
  const direct = recordValue(adapterDetails?.runner_metrics);
  if (direct) metrics.push(direct);
  const attempts = Array.isArray(adapterDetails?.attempt_summaries) ? adapterDetails.attempt_summaries : [];
  for (const attempt of attempts) {
    const attemptMetrics = recordValue(recordValue(attempt)?.runner_metrics);
    if (attemptMetrics) metrics.push(attemptMetrics);
  }
  return metrics;
}
function observabilityFrom(state) {
  const engineEvents = state.events.filter((event) => event.kind === "engine.result").map((event) => ({ event, details: eventDetails(event) }));
  const agentEvents = state.events.filter((event) => event.kind.startsWith("agent.")).map((event) => ({ event, details: eventDetails(event) })).filter(({ details }) => numericValue(details.duration_ms) !== void 0);
  const retryEvents = state.events.filter((event) => /retry|recovery/i.test(event.kind) || /retry|recovery/i.test(event.summary || "")).slice(-8);
  const runnerMetrics = agentEvents.flatMap(({ details }) => collectRunnerMetrics(details));
  const promptChars = runnerMetrics.map((metrics) => numericValue(metrics.prompt_chars)).filter((value) => value !== void 0);
  const sum = (values) => values.reduce((total, value) => total + (value ?? 0), 0);
  const recentEngineTimings = engineEvents.slice(-8).map(({ event, details }) => compactRecord({
    checkpoint: event.checkpoint || null,
    stage: event.stage || null,
    duration_ms: numericValue(details.duration_ms),
    ok: details.ok ?? null
  }));
  const recentAgentTimings = agentEvents.slice(-8).map(({ event, details }) => {
    const metrics = collectRunnerMetrics(details);
    const localPromptChars = metrics.map((item) => numericValue(item.prompt_chars)).filter((value) => value !== void 0);
    return compactRecord({
      kind: event.kind,
      checkpoint: event.checkpoint || null,
      stage: event.stage || null,
      duration_ms: numericValue(details.duration_ms),
      prompt_chars: localPromptChars.length ? Math.max(...localPromptChars) : void 0,
      attempt_count: numericValue(recordValue(details.adapter_details)?.attempt_count)
    });
  });
  return compactRecord({
    engine_call_count: engineEvents.length,
    agent_call_count: agentEvents.length,
    engine_total_ms: sum(engineEvents.map(({ details }) => numericValue(details.duration_ms))),
    agent_total_ms: sum(agentEvents.map(({ details }) => numericValue(details.duration_ms))),
    max_agent_prompt_chars: promptChars.length ? Math.max(...promptChars) : void 0,
    total_agent_prompt_chars: promptChars.length ? sum(promptChars) : void 0,
    recent_engine_timings: recentEngineTimings.length ? recentEngineTimings : void 0,
    recent_agent_timings: recentAgentTimings.length ? recentAgentTimings : void 0,
    retry_event_count: retryEvents.length,
    recent_retry_reasons: retryEvents.length ? retryEvents.map((event) => compactRecord({
      kind: event.kind,
      checkpoint: event.checkpoint || null,
      stage: event.stage || null,
      summary: compactText(event.summary, 240)
    })) : void 0
  });
}
function visualDeltaFrom(input) {
  const fullState = input.fullRiddleState || {};
  const bundle = recordValue(fullState.evidence_bundle);
  const after = recordValue(bundle?.after);
  const afterDelta = recordValue(after?.visual_delta);
  if (afterDelta && Object.keys(afterDelta).length) return afterDelta;
  const requestDelta = recordValue(recordValue(fullState.proof_assessment_request)?.visual_delta);
  if (requestDelta && Object.keys(requestDelta).length) return requestDelta;
  const packetDelta = recordValue(input.runState.checkpoint_packet?.evidence_excerpt?.visual_delta);
  return packetDelta && Object.keys(packetDelta).length ? packetDelta : void 0;
}
function artifactsFrom(input) {
  const packetArtifacts = input.runState.checkpoint_packet?.artifacts;
  if (packetArtifacts?.length) return packetArtifacts.slice(0, 12);
  const fullState = input.fullRiddleState || {};
  const artifacts = [];
  for (const role of ["before", "prod", "after"]) {
    const url = nonEmptyString(fullState[`${role}_cdn`]) || nonEmptyString(input.runState[`${role}_artifact_url`]);
    if (url) artifacts.push({ role, url, name: `${role}.png`, mime_type: "image/png" });
  }
  return artifacts.length ? artifacts : void 0;
}
function viewportMatrixFrom(input) {
  const fullState = input.fullRiddleState || {};
  const bundle = recordValue(fullState.evidence_bundle);
  const fromBundle = recordValue(bundle?.viewport_matrix);
  if (fromBundle && Object.keys(fromBundle).length) return jsonCloneRecord(fromBundle);
  const fromRequest = recordValue(recordValue(fullState.proof_assessment_request)?.viewport_matrix);
  if (fromRequest && Object.keys(fromRequest).length) return jsonCloneRecord(fromRequest);
  const fromState = recordValue(fullState.viewport_matrix_status) || recordValue(input.runState.viewport_matrix_status);
  return fromState && Object.keys(fromState).length ? jsonCloneRecord(fromState) : void 0;
}
function ownerFor(state) {
  if (state.status === "awaiting_checkpoint") {
    const role = nonEmptyString(state.checkpoint_packet?.routing_hint?.suggested_role);
    return role || "supervising_agent";
  }
  if (state.status === "running") return "engine";
  if (state.status === "blocked" || state.status === "failed") return "human_or_operator";
  return "none";
}
function actionFor(state) {
  if (state.status === "awaiting_checkpoint") return state.checkpoint_packet?.question || "Answer the pending checkpoint.";
  if (state.status === "running") return "Continue the current Riddle Proof stage.";
  if (state.status === "blocked" || state.status === "failed") return state.blocker?.message || "Inspect the blocker and decide whether a new run or infrastructure repair is needed.";
  if (state.status === "ready_to_ship") return "Ship is held by policy; review PR/ship policy before advancing.";
  return "No next action; run is terminal.";
}
function evidenceIssueCode(input) {
  const packetIssue = nonEmptyString(input.runState.checkpoint_packet?.evidence_excerpt?.evidence_issue_code);
  if (packetIssue) return packetIssue;
  const assessmentIssue = nonEmptyString(recordValue(input.fullRiddleState?.proof_assessment)?.evidence_issue_code);
  if (assessmentIssue) return assessmentIssue;
  const delta = visualDeltaFrom(input);
  const status = nonEmptyString(delta?.status);
  if (status === "unmeasured") {
    const reason = `${nonEmptyString(delta?.reason) || ""}
${input.runState.blocker?.message || ""}`.toLowerCase();
    return reason.includes("fetch") || reason.includes("allowlist") || reason.includes("registered domain") || reason.includes("high risk") || reason.includes("comparator") ? "comparator_fetch_blocked" : "visual_delta_unmeasured";
  }
  if (status === "measured" && delta?.passed === false) return "semantic_proof_failed";
  return void 0;
}
function createRiddleProofRunCard(state, input = {}) {
  const at = input.at || (/* @__PURE__ */ new Date()).toISOString();
  const fullState = input.fullRiddleState || {};
  const packet = state.checkpoint_packet;
  const latestEvent = state.events[state.events.length - 1];
  const bundle = recordValue(fullState.evidence_bundle);
  const artifactContract = jsonCloneRecord(packet?.artifact_contract) || jsonCloneRecord(recordValue(fullState.proof_assessment_request)?.artifact_contract) || jsonCloneRecord(recordValue(bundle?.artifact_contract)) || jsonCloneRecord(state.proof_contract?.artifact_contract);
  const required = jsonCloneRecord(recordValue(artifactContract)?.required);
  const statePaths = input.state_paths || state.state_paths || statePathsForRunState(state);
  const visualDelta = visualDeltaFrom({ fullRiddleState: fullState, runState: state });
  const artifacts = artifactsFrom({ fullRiddleState: fullState, runState: state });
  const viewportMatrix = viewportMatrixFrom({ fullRiddleState: fullState, runState: state });
  return {
    version: RIDDLE_PROOF_RUN_CARD_VERSION,
    run_id: state.run_id || "unknown",
    status: state.status,
    goal: compactRecord({
      repo: state.request.repo || nonEmptyString(fullState.repo),
      branch: state.request.branch || nonEmptyString(fullState.branch),
      change_request: state.request.change_request || nonEmptyString(fullState.change_request),
      verification_mode: state.request.verification_mode || nonEmptyString(fullState.verification_mode),
      success_criteria: state.request.success_criteria
    }),
    durable_state: compactRecord({
      ...statePaths,
      worktree_path: state.worktree_path || nonEmptyString(fullState.after_worktree) || null,
      branch: state.branch || nonEmptyString(fullState.branch) || null
    }),
    current_phase: compactRecord({
      stage: state.current_stage ?? null,
      checkpoint: state.last_checkpoint ?? packet?.checkpoint ?? null,
      latest_event: latestEvent?.kind ?? null,
      elapsed_ms: elapsedMs(state.created_at, at),
      stage_elapsed_ms: elapsedMs(state.stage_started_at, at),
      iterations: state.iterations
    }),
    owner_next_action: compactRecord({
      owner: ownerFor(state),
      action: actionFor(state),
      checkpoint_kind: packet?.kind || null,
      allowed_decisions: packet?.allowed_decisions,
      retryable: state.status === "running" || state.status === "awaiting_checkpoint",
      reason: state.blocker?.code || packet?.summary || latestEvent?.summary || null
    }),
    evidence_contract: compactRecord({
      verification_mode: state.request.verification_mode || nonEmptyString(fullState.verification_mode),
      required,
      artifact_contract: artifactContract,
      proof_plan: compactText(state.proof_contract?.proof_plan || fullState.proof_plan, 600),
      stop_condition: compactText(state.proof_contract?.stop_condition, 400)
    }),
    latest_evidence: compactRecord({
      before_url: nonEmptyString(fullState.before_cdn) || state.before_artifact_url || null,
      prod_url: nonEmptyString(fullState.prod_cdn) || state.prod_artifact_url || null,
      after_url: nonEmptyString(fullState.after_cdn) || state.after_artifact_url || null,
      visual_delta: visualDelta || null,
      evidence_issue_code: evidenceIssueCode({ fullRiddleState: fullState, runState: state }) || null,
      proof_evidence_present: fullState.proof_evidence_present === true || Boolean(bundle?.proof_evidence || bundle?.proof_evidence_sample),
      viewport_matrix: viewportMatrix,
      artifacts
    }),
    observability: observabilityFrom(state),
    stop_condition: compactRecord({
      status: state.status,
      terminal: isTerminalStatus(state.status),
      blocker_code: state.blocker?.code || null,
      blocker_message: state.blocker?.message || null,
      proof_decision: state.proof_decision,
      merge_recommendation: state.merge_recommendation,
      monitor_should_continue: !isTerminalStatus(state.status)
    }),
    updated_at: state.updated_at
  };
}

export {
  RIDDLE_PROOF_RUN_CARD_VERSION,
  createRiddleProofRunCard
};
