{"version":3,"sources":["../src/logs/tree-builder.ts"],"names":[],"mappings":"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","file":"chunk-AK5EN4U2.mjs","sourcesContent":["import type {\n  InspectEvent,\n  InspectNode,\n  InspectRunTree,\n  RelationshipSummary,\n} from \"../types/inspect-event.js\";\nimport type { LogIngestConfig } from \"../types/log-config.js\";\n\nexport interface TreeBuilderOptions {\n  config?: LogIngestConfig;\n}\n\nfunction inc<T extends string>(map: Record<T, number>, key: T): void {\n  map[key] = (map[key] ?? 0) + 1;\n}\n\nfunction confidenceRank(confidence: InspectEvent[\"confidence\"]): number {\n  switch (confidence) {\n    case \"unknown\":\n      return 0;\n    case \"heuristic\":\n      return 1;\n    case \"correlated\":\n      return 2;\n    case \"explicit\":\n      return 3;\n    default:\n      return 0;\n  }\n}\n\nfunction computeRunStatus(events: InspectEvent[]): InspectRunTree[\"status\"] {\n  // Derive the run status from the RUN node lifecycle, matching\n  // manualTraceEventsToRunTree and extractMetadata: a run is \"running\" only\n  // until its RUN completion is recorded. The v0.1 bridge writes each node as a\n  // \"started\" event (status \"running\") followed by a \"completed\" event, so a\n  // finished run still carries \"running\" started rows; those must not force the\n  // whole run back to \"running\". Events arrive timestamp-sorted, so the last\n  // terminal RUN status wins.\n  let runTerminal: \"ok\" | \"error\" | undefined;\n  let sawRunEvent = false;\n  for (const e of events) {\n    if (e.kind !== \"RUN\") continue;\n    sawRunEvent = true;\n    if (e.status === \"ok\" || e.status === \"error\") {\n      runTerminal = e.status;\n    }\n  }\n  if (sawRunEvent) {\n    return runTerminal ?? \"running\";\n  }\n\n  // Fallback for traces with no RUN node (e.g. log-only ingestion).\n  let hasRunning = false;\n  for (const e of events) {\n    if (e.status === \"error\") return \"error\";\n    if (e.status === \"running\") hasRunning = true;\n  }\n  return hasRunning ? \"running\" : \"ok\";\n}\n\ninterface PendingEdge {\n  childId: string;\n  parentId: string;\n  childTimestamp: number;\n  childConfidence: InspectEvent[\"confidence\"];\n}\n\n/**\n * Link children to parents without self-edges or cycles. Broken edges become roots.\n */\nexport function linkNodesVisibilityFirst(\n  nodes: Map<string, InspectNode>,\n): { roots: InspectNode[]; summary: RelationshipSummary } {\n  let selfParentCount = 0;\n  let unresolvedParentCount = 0;\n  let normalizedEdgeCount = 0;\n  let cycleCount = 0;\n\n  const pending: PendingEdge[] = [];\n  for (const node of nodes.values()) {\n    const parentId = node.event.parentId;\n    if (!parentId) continue;\n    if (parentId === node.event.eventId) {\n      selfParentCount += 1;\n      normalizedEdgeCount += 1;\n      continue;\n    }\n    if (!nodes.has(parentId)) {\n      unresolvedParentCount += 1;\n      continue;\n    }\n    pending.push({\n      childId: node.event.eventId,\n      parentId,\n      childTimestamp: node.event.timestamp,\n      childConfidence: node.event.confidence,\n    });\n  }\n\n  // Prefer keeping higher-confidence / earlier edges; break the weakest last edge in a cycle.\n  pending.sort((a, b) => {\n    const conf = confidenceRank(b.childConfidence) - confidenceRank(a.childConfidence);\n    if (conf !== 0) return conf;\n    return a.childTimestamp - b.childTimestamp;\n  });\n\n  const parentOf = new Map<string, string>();\n  for (const edge of pending) {\n    parentOf.set(edge.childId, edge.parentId);\n    // Detect if accepting this edge creates a cycle (walk from parent toward roots).\n    let cursor: string | undefined = edge.parentId;\n    const seen = new Set<string>([edge.childId]);\n    let cyclic = false;\n    while (cursor) {\n      if (seen.has(cursor)) {\n        cyclic = true;\n        break;\n      }\n      seen.add(cursor);\n      cursor = parentOf.get(cursor);\n    }\n    if (cyclic) {\n      parentOf.delete(edge.childId);\n      cycleCount += 1;\n      normalizedEdgeCount += 1;\n    }\n  }\n\n  for (const [childId, parentId] of parentOf) {\n    nodes.get(parentId)!.children.push(nodes.get(childId)!);\n  }\n\n  const roots: InspectNode[] = [];\n  for (const node of nodes.values()) {\n    if (!parentOf.has(node.event.eventId)) {\n      roots.push(node);\n    }\n  }\n\n  const assignDepth = (n: InspectNode, depth: number, stack: Set<string>) => {\n    if (stack.has(n.event.eventId)) return;\n    n.depth = depth;\n    stack.add(n.event.eventId);\n    for (const c of n.children) assignDepth(c, depth + 1, stack);\n    stack.delete(n.event.eventId);\n  };\n  for (const r of roots) assignDepth(r, 0, new Set());\n\n  return {\n    roots,\n    summary: {\n      rootCount: roots.length,\n      selfParentCount,\n      cycleCount,\n      unresolvedParentCount,\n      normalizedEdgeCount,\n    },\n  };\n}\n\nexport class TreeBuilder {\n  constructor(options?: TreeBuilderOptions) {\n    void options?.config;\n  }\n\n  build(events: InspectEvent[]): InspectRunTree[] {\n    const byRun = new Map<string, InspectEvent[]>();\n    for (const e of events) {\n      if (!byRun.has(e.runId)) byRun.set(e.runId, []);\n      byRun.get(e.runId)!.push(e);\n    }\n\n    const out: InspectRunTree[] = [];\n    for (const [runId, runEvents] of byRun.entries()) {\n      const sorted = [...runEvents].sort((a, b) => a.timestamp - b.timestamp);\n\n      const nodes = new Map<string, InspectNode>();\n      for (const e of sorted) {\n        nodes.set(e.eventId, { event: e, children: [], depth: 0 });\n      }\n\n      const { roots, summary } = linkNodesVisibilityFirst(nodes);\n\n      // metadata\n      const confidenceBreakdown = {\n        explicit: 0,\n        correlated: 0,\n        heuristic: 0,\n        unknown: 0,\n      } as Record<InspectEvent[\"confidence\"], number>;\n      const kinds = {} as Record<InspectEvent[\"kind\"], number>;\n      for (const e of sorted) {\n        inc(confidenceBreakdown, e.confidence);\n        (kinds as any)[e.kind] = ((kinds as any)[e.kind] ?? 0) + 1;\n      }\n\n      const startedAt = sorted.length > 0 ? sorted[0]!.timestamp : undefined;\n      const endedAt = sorted.length > 0 ? sorted[sorted.length - 1]!.timestamp : undefined;\n      const status = computeRunStatus(sorted);\n      const durationMs =\n        startedAt !== undefined &&\n        endedAt !== undefined &&\n        Number.isFinite(startedAt) &&\n        Number.isFinite(endedAt) &&\n        endedAt >= startedAt &&\n        status !== \"running\"\n          ? endedAt - startedAt\n          : undefined;\n\n      const name = sorted.find((e) => e.kind === \"RUN\")?.name;\n\n      out.push({\n        runId,\n        name,\n        status,\n        startedAt,\n        endedAt: status === \"running\" ? undefined : endedAt,\n        durationMs,\n        children: roots,\n        metadata: {\n          totalEvents: sorted.length,\n          confidenceBreakdown,\n          kinds,\n          relationshipSummary: summary,\n        },\n      });\n    }\n\n    // newest first for stable display\n    out.sort((a, b) => (b.startedAt ?? 0) - (a.startedAt ?? 0));\n    return out;\n  }\n}\n"]}