{"version":3,"sources":["../src/outcomes/types.ts","../src/outcomes/validate.ts","../src/outcomes/extract.ts","../src/outcomes/render.ts"],"names":["parseMethod"],"mappings":"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","file":"chunk-N5PZAI6Q.mjs","sourcesContent":["export type ObservedOutcomeStatus = \"passed\" | \"failed\" | \"unknown\" | \"skipped\";\n\nexport type ObservedOutcomeMethod =\n  | \"dom\"\n  | \"accessibility\"\n  | \"snapshot\"\n  | \"network\"\n  | \"storage\"\n  | \"filesystem\"\n  | \"database\"\n  | \"queue\"\n  | \"custom\";\n\nexport interface ObservedOutcome {\n  outcomeId: string;\n  runId: string;\n  parentId?: string;\n  name: string;\n  expectation: string;\n  status: ObservedOutcomeStatus;\n  method?: ObservedOutcomeMethod;\n  actual?: unknown;\n  evidence?: unknown;\n  observedAt: number;\n}\n\nexport interface ObserveOutcomeOptions {\n  expectation: string;\n  status: ObservedOutcomeStatus;\n  method?: ObservedOutcomeMethod;\n  actual?: unknown;\n  evidence?: unknown;\n  observedAt?: number | string;\n}\n\nexport interface ObservedOutcomeSummary {\n  total: number;\n  passed: number;\n  failed: number;\n  unknown: number;\n  skipped: number;\n  outcomes: ObservedOutcome[];\n}\n\nexport const OBSERVED_OUTCOME_STATUSES: readonly ObservedOutcomeStatus[] = [\n  \"passed\",\n  \"failed\",\n  \"unknown\",\n  \"skipped\",\n];\n\nexport const OBSERVED_OUTCOME_METHODS: readonly ObservedOutcomeMethod[] = [\n  \"dom\",\n  \"accessibility\",\n  \"snapshot\",\n  \"network\",\n  \"storage\",\n  \"filesystem\",\n  \"database\",\n  \"queue\",\n  \"custom\",\n];\n\nexport const OUTCOME_ATTRIBUTE_STATUS_KEY = \"outcomeStatus\";\nexport const OUTCOME_ATTRIBUTE_EXPECTATION_KEY = \"expectation\";\nexport const OUTCOME_ATTRIBUTE_METHOD_KEY = \"method\";\nexport const OUTCOME_ATTRIBUTE_OBSERVED_AT_KEY = \"observedAt\";\nexport const OUTCOME_LEGACY_EVENT = \"outcome_observed\";\n","import type { TraceSafetyOptions } from \"../trace-event-safety.js\";\nimport { prepareMetadataForDisk } from \"../trace-event-safety.js\";\nimport type { OutcomeObservedEvent } from \"../types.js\";\nimport {\n  OBSERVED_OUTCOME_METHODS,\n  OBSERVED_OUTCOME_STATUSES,\n  type ObserveOutcomeOptions,\n  type ObservedOutcomeMethod,\n  type ObservedOutcomeStatus,\n} from \"./types.js\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeName(name: string): string {\n  const trimmed = name.trim();\n  if (trimmed === \"\") {\n    throw new Error(\"observeOutcome requires a non-empty name.\");\n  }\n  return trimmed.slice(0, 100);\n}\n\nfunction normalizeExpectation(value: string): string {\n  const trimmed = value.trim();\n  if (trimmed === \"\") {\n    throw new Error(\"observeOutcome requires a non-empty expectation.\");\n  }\n  return trimmed.slice(0, 500);\n}\n\nexport function parseObservedOutcomeStatus(value: string): ObservedOutcomeStatus {\n  const trimmed = value.trim().toLowerCase();\n  if ((OBSERVED_OUTCOME_STATUSES as readonly string[]).includes(trimmed)) {\n    return trimmed as ObservedOutcomeStatus;\n  }\n  throw new Error(\n    `Unsupported observation status \"${value}\". Use passed, failed, unknown, or skipped.`,\n  );\n}\n\nfunction parseMethod(value: string | undefined): ObservedOutcomeMethod | undefined {\n  if (value === undefined || value.trim() === \"\") return undefined;\n  const trimmed = value.trim().toLowerCase();\n  if ((OBSERVED_OUTCOME_METHODS as readonly string[]).includes(trimmed)) {\n    return trimmed as ObservedOutcomeMethod;\n  }\n  throw new Error(`Unsupported observation method \"${value}\".`);\n}\n\nfunction parseObservedAt(value: number | string | undefined, fallback: number): number {\n  if (value === undefined) return fallback;\n  if (typeof value === \"number\" && Number.isFinite(value)) return value;\n  if (typeof value === \"string\") {\n    const parsed = Date.parse(value);\n    if (Number.isFinite(parsed)) return parsed;\n  }\n  return fallback;\n}\n\nexport function normalizeObserveOutcomeInput(\n  name: string,\n  options: ObserveOutcomeOptions,\n  nowMs: number = Date.now(),\n): {\n  name: string;\n  expectation: string;\n  status: ObservedOutcomeStatus;\n  method?: ObservedOutcomeMethod;\n  actual?: unknown;\n  evidence?: unknown;\n  observedAt: number;\n} {\n  return {\n    name: normalizeName(name),\n    expectation: normalizeExpectation(options.expectation),\n    status: options.status,\n    ...(options.method !== undefined ? { method: parseMethod(options.method) } : {}),\n    ...(options.actual !== undefined ? { actual: options.actual } : {}),\n    ...(options.evidence !== undefined ? { evidence: options.evidence } : {}),\n    observedAt: parseObservedAt(options.observedAt, nowMs),\n  };\n}\n\nfunction boundPayload(\n  value: unknown,\n  opts: TraceSafetyOptions,\n): unknown {\n  if (value === undefined) return undefined;\n  if (!isRecord(value) && !Array.isArray(value)) {\n    if (typeof value === \"string\") {\n      return value.length > opts.maxMetadataValueLength\n        ? `${value.slice(0, opts.maxMetadataValueLength)}…`\n        : value;\n    }\n    return value;\n  }\n  return prepareMetadataForDisk(\n    isRecord(value) ? value : { items: value },\n    opts,\n  );\n}\n\nexport function prepareOutcomeEventForDisk(\n  event: OutcomeObservedEvent,\n  opts: TraceSafetyOptions,\n): OutcomeObservedEvent {\n  const actual = boundPayload(event.actual, opts);\n  const evidence = boundPayload(event.evidence, opts);\n  const next: OutcomeObservedEvent = {\n    ...event,\n    ...(actual !== undefined ? { actual } : {}),\n    ...(evidence !== undefined ? { evidence } : {}),\n  };\n  if (\"actual\" in event && actual === undefined) {\n    const { actual: _a, ...rest } = next;\n    return rest;\n  }\n  if (\"evidence\" in event && evidence === undefined) {\n    const { evidence: _e, ...rest } = next;\n    return rest;\n  }\n  return next;\n}\n","import type { PersistedInspectEvent } from \"../types/persisted-inspect-event.js\";\nimport type { TraceEvent } from \"../types.js\";\nimport {\n  OUTCOME_ATTRIBUTE_EXPECTATION_KEY,\n  OUTCOME_ATTRIBUTE_METHOD_KEY,\n  OUTCOME_ATTRIBUTE_OBSERVED_AT_KEY,\n  OUTCOME_ATTRIBUTE_STATUS_KEY,\n  OUTCOME_LEGACY_EVENT,\n  type ObservedOutcome,\n  type ObservedOutcomeMethod,\n  type ObservedOutcomeStatus,\n  type ObservedOutcomeSummary,\n} from \"./types.js\";\nimport { parseObservedOutcomeStatus } from \"./validate.js\";\n\nfunction isOutcomeStatus(value: unknown): value is ObservedOutcomeStatus {\n  return (\n    value === \"passed\" ||\n    value === \"failed\" ||\n    value === \"unknown\" ||\n    value === \"skipped\"\n  );\n}\n\nfunction parseMethod(value: unknown): ObservedOutcomeMethod | undefined {\n  if (typeof value !== \"string\" || value.trim() === \"\") return undefined;\n  return value as ObservedOutcomeMethod;\n}\n\nfunction fromOutcomeObservedEvent(event: Extract<TraceEvent, { event: \"outcome_observed\" }>): ObservedOutcome {\n  return {\n    outcomeId: event.outcomeId,\n    runId: event.runId,\n    ...(event.parentId !== undefined ? { parentId: event.parentId } : {}),\n    name: event.name,\n    expectation: event.expectation,\n    status: event.status,\n    ...(event.method !== undefined ? { method: event.method } : {}),\n    ...(event.actual !== undefined ? { actual: event.actual } : {}),\n    ...(event.evidence !== undefined ? { evidence: event.evidence } : {}),\n    observedAt: event.observedAt,\n  };\n}\n\nfunction fromPersistedOutcome(event: PersistedInspectEvent): ObservedOutcome | undefined {\n  if (event.kind !== \"OUTCOME\") return undefined;\n  const attrs = event.attributes ?? {};\n  const statusRaw = attrs[OUTCOME_ATTRIBUTE_STATUS_KEY];\n  if (!isOutcomeStatus(statusRaw)) return undefined;\n  const expectation =\n    typeof attrs[OUTCOME_ATTRIBUTE_EXPECTATION_KEY] === \"string\"\n      ? attrs[OUTCOME_ATTRIBUTE_EXPECTATION_KEY]\n      : event.name;\n  const observedAtRaw = attrs[OUTCOME_ATTRIBUTE_OBSERVED_AT_KEY];\n  const observedAt =\n    typeof observedAtRaw === \"string\"\n      ? Date.parse(observedAtRaw)\n      : typeof observedAtRaw === \"number\" && Number.isFinite(observedAtRaw)\n        ? observedAtRaw\n        : Date.parse(event.timestamp);\n  return {\n    outcomeId: event.eventId,\n    runId: event.runId,\n    ...(event.parentId !== undefined ? { parentId: event.parentId } : {}),\n    name: event.name,\n    expectation,\n    status: statusRaw,\n    ...(parseMethod(attrs[OUTCOME_ATTRIBUTE_METHOD_KEY]) !== undefined\n      ? { method: parseMethod(attrs[OUTCOME_ATTRIBUTE_METHOD_KEY]) }\n      : {}),\n    ...(event.outputSummary !== undefined ? { actual: event.outputSummary } : {}),\n    ...(attrs.evidence !== undefined ? { evidence: attrs.evidence } : {}),\n    observedAt: Number.isFinite(observedAt) ? observedAt : Date.parse(event.timestamp),\n  };\n}\n\nexport function extractOutcomesFromTraceEvents(events: readonly TraceEvent[]): ObservedOutcome[] {\n  const out: ObservedOutcome[] = [];\n  for (const event of events) {\n    if (event.event === OUTCOME_LEGACY_EVENT) {\n      out.push(fromOutcomeObservedEvent(event as Extract<TraceEvent, { event: \"outcome_observed\" }>));\n    }\n  }\n  return out.sort((a, b) => a.observedAt - b.observedAt || a.name.localeCompare(b.name));\n}\n\nexport function extractOutcomesFromPersistedEvents(\n  events: readonly PersistedInspectEvent[],\n): ObservedOutcome[] {\n  const out: ObservedOutcome[] = [];\n  for (const event of events) {\n    const outcome = fromPersistedOutcome(event);\n    if (outcome) out.push(outcome);\n  }\n  return out.sort((a, b) => a.observedAt - b.observedAt || a.name.localeCompare(b.name));\n}\n\nexport function summarizeObservedOutcomes(outcomes: readonly ObservedOutcome[]): ObservedOutcomeSummary {\n  const summary: ObservedOutcomeSummary = {\n    total: outcomes.length,\n    passed: 0,\n    failed: 0,\n    unknown: 0,\n    skipped: 0,\n    outcomes: [...outcomes],\n  };\n  for (const outcome of outcomes) {\n    summary[outcome.status] += 1;\n  }\n  return summary;\n}\n\nexport function outcomesMatchingStatus(\n  outcomes: readonly ObservedOutcome[],\n  statuses: readonly ObservedOutcomeStatus[],\n): ObservedOutcome[] {\n  const set = new Set(statuses);\n  return outcomes.filter((outcome) => set.has(outcome.status));\n}\n\nexport function parseObservationFilter(value: string | undefined): ObservedOutcomeStatus | undefined {\n  if (value === undefined || value.trim() === \"\") return undefined;\n  return parseObservedOutcomeStatus(value);\n}\n","import type { ObservedOutcome, ObservedOutcomeSummary } from \"./types.js\";\n\nfunction formatPayload(value: unknown): string {\n  if (value === undefined) return \"\";\n  try {\n    return JSON.stringify(value);\n  } catch {\n    return String(value);\n  }\n}\n\nexport function renderObservedOutcomesMarkdown(summary: ObservedOutcomeSummary): string {\n  if (summary.total === 0) {\n    return \"No observed outcomes recorded for this run.\";\n  }\n  const lines = [\n    `Total: ${summary.total} (passed ${summary.passed}, failed ${summary.failed}, unknown ${summary.unknown}, skipped ${summary.skipped})`,\n    \"\",\n    \"| Name | Status | Expectation | Method |\",\n    \"| --- | --- | --- | --- |\",\n  ];\n  for (const outcome of summary.outcomes) {\n    lines.push(\n      `| ${outcome.name} | ${outcome.status} | ${outcome.expectation.replace(/\\|/g, \"\\\\|\")} | ${outcome.method ?? \"-\"} |`,\n    );\n  }\n  return lines.join(\"\\n\");\n}\n\nexport function renderObservedOutcomesText(summary: ObservedOutcomeSummary): string {\n  if (summary.total === 0) {\n    return \"No observed outcomes recorded for this run.\";\n  }\n  const lines = [\n    `Observed outcomes: ${summary.total} (passed ${summary.passed}, failed ${summary.failed}, unknown ${summary.unknown}, skipped ${summary.skipped})`,\n  ];\n  for (const outcome of summary.outcomes) {\n    const evidence = formatPayload(outcome.evidence);\n    const suffix = evidence ? ` evidence=${evidence}` : \"\";\n    lines.push(\n      `- ${outcome.name} [${outcome.status}] ${outcome.expectation}${suffix}`,\n    );\n  }\n  return lines.join(\"\\n\");\n}\n\nexport function renderObservedOutcomesHtml(summary: ObservedOutcomeSummary): string {\n  if (summary.total === 0) {\n    return \"<p>No observed outcomes recorded for this run.</p>\";\n  }\n  const rows = summary.outcomes\n    .map((outcome: ObservedOutcome) => {\n      const esc = (v: string) =>\n        v.replaceAll(\"&\", \"&amp;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\");\n      return `<tr><td>${esc(outcome.name)}</td><td>${esc(outcome.status)}</td><td>${esc(outcome.expectation)}</td><td>${esc(outcome.method ?? \"-\")}</td></tr>`;\n    })\n    .join(\"\");\n  return `<p>Total: ${summary.total} (passed ${summary.passed}, failed ${summary.failed}, unknown ${summary.unknown}, skipped ${summary.skipped})</p><table><thead><tr><th>Name</th><th>Status</th><th>Expectation</th><th>Method</th></tr></thead><tbody>${rows}</tbody></table>`;\n}\n"]}