{"version":3,"sources":["../src/incidents-render.ts"],"sourcesContent":["import {\n  ObservedDeployContextSchema,\n  type DeployContext,\n  type ErrorEvent,\n  type FlagMismatchDivergence,\n} from '@neat.is/types'\n\n// The OBSERVED deploy/process/config context of a faulted workload (ADR-237/240),\n// fused onto its node at ingest (ADR-243): the deploy fault, the faulted\n// container's redacted env/args, and its boot-time stdout tail. Rendered compactly\n// so the incident surfaces the wrong host / bad flag / crash traceback inline\n// instead of leaving it to the card.\n//\n// One renderer, every text reader: the CLI `neat incidents` output (cli-client.ts)\n// and the MCP get_incident_history / incident-card tools (packages/mcp) all call\n// this, so they never drift (core #1373 — atomic, no feature mirrors another's\n// fields). Returns [] when there is no context, so those lines read exactly as\n// before.\nexport function deployHintLines(ctx: DeployContext | undefined): string[] {\n  if (!ctx) return []\n  const env = ctx.containerEnv ?? []\n  const args = ctx.containerArgs ?? []\n  const log = ctx.processLog\n  if (!ctx.fault && env.length === 0 && args.length === 0 && !log) return []\n  const out: string[] = []\n  if (ctx.fault) {\n    const bits = [ctx.fault]\n    if (ctx.waitingReason) bits.push(ctx.waitingReason)\n    if (ctx.restartCount !== undefined) bits.push(`restarts=${ctx.restartCount}`)\n    if (ctx.exitCode !== undefined) bits.push(`exit=${ctx.exitCode}`)\n    if (ctx.terminatedReason) bits.push(ctx.terminatedReason)\n    out.push(`deploy: ${bits.join(' ')}`)\n  }\n  const cap = (xs: string[], max: number): string => {\n    const joined = xs.join('  ')\n    return joined.length > max ? `${joined.slice(0, max)}…(+${xs.length} entries)` : joined\n  }\n  if (env.length > 0) out.push(`env: ${cap(env, 700)}`)\n  if (args.length > 0) out.push(`args: ${cap(args, 300)}`)\n  if (log) {\n    const tail = log.split('\\n').filter((l) => l.trim().length > 0).slice(-4)\n    if (tail.length > 0) out.push(`log: ${tail.join(' ⏎ ')}`)\n  }\n  return out\n}\n\n// The deploy context on each incident's workload node, keyed by the incident it\n// was observed with (ADR-243). `readNode` is the caller's own GET /graph/node/:id;\n// it runs once per distinct affected node, and a node that can't be read just\n// shows no context.\nexport async function deployContextsFor(\n  events: ErrorEvent[],\n  readNode: (nodeId: string) => Promise<{ observedDeployContext?: unknown } | undefined>,\n): Promise<Map<string, DeployContext>> {\n  const byIncident = new Map<string, DeployContext>()\n  for (const nodeId of new Set(events.map((e) => e.affectedNode))) {\n    try {\n      const parsed = ObservedDeployContextSchema.safeParse((await readNode(nodeId))?.observedDeployContext)\n      if (!parsed.success) continue\n      const { incidentId, observedAt: _observedAt, ...ctx } = parsed.data\n      byIncident.set(incidentId, ctx)\n    } catch {\n      // The incident list still renders without the context.\n    }\n  }\n  return byIncident\n}\n\n// A flag-grain divergence (ADR-242) in one phrase, the same on every surface that\n// names one: the card's divergence summary, `neat divergences`, MCP\n// get_divergences and the monitor stream. Names the flag, the committed and the\n// running variant, and where the code reads it.\nexport function flagMismatchPhrase(d: FlagMismatchDivergence): string {\n  const q = (v: string | null | undefined): string => (v === null || v === undefined ? 'none' : v)\n  const what = d.changed.includes('defaultVariant')\n    ? `committed ${q(d.declaredVariant)}, running ${q(d.observedVariant)}`\n    : `${d.changed.join(', ')} changed from the committed definition`\n  const at = d.readers && d.readers.length > 0 ? ` (read at ${d.readers.join(', ')})` : ''\n  return `flag ${d.flagKey}: ${what}${at}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKO;AAaA,SAAS,gBAAgB,KAA0C;AACxE,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,QAAM,MAAM,IAAI,gBAAgB,CAAC;AACjC,QAAM,OAAO,IAAI,iBAAiB,CAAC;AACnC,QAAM,MAAM,IAAI;AAChB,MAAI,CAAC,IAAI,SAAS,IAAI,WAAW,KAAK,KAAK,WAAW,KAAK,CAAC,IAAK,QAAO,CAAC;AACzE,QAAM,MAAgB,CAAC;AACvB,MAAI,IAAI,OAAO;AACb,UAAM,OAAO,CAAC,IAAI,KAAK;AACvB,QAAI,IAAI,cAAe,MAAK,KAAK,IAAI,aAAa;AAClD,QAAI,IAAI,iBAAiB,OAAW,MAAK,KAAK,YAAY,IAAI,YAAY,EAAE;AAC5E,QAAI,IAAI,aAAa,OAAW,MAAK,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAChE,QAAI,IAAI,iBAAkB,MAAK,KAAK,IAAI,gBAAgB;AACxD,QAAI,KAAK,WAAW,KAAK,KAAK,GAAG,CAAC,EAAE;AAAA,EACtC;AACA,QAAM,MAAM,CAAC,IAAc,QAAwB;AACjD,UAAM,SAAS,GAAG,KAAK,IAAI;AAC3B,WAAO,OAAO,SAAS,MAAM,GAAG,OAAO,MAAM,GAAG,GAAG,CAAC,WAAM,GAAG,MAAM,cAAc;AAAA,EACnF;AACA,MAAI,IAAI,SAAS,EAAG,KAAI,KAAK,QAAQ,IAAI,KAAK,GAAG,CAAC,EAAE;AACpD,MAAI,KAAK,SAAS,EAAG,KAAI,KAAK,SAAS,IAAI,MAAM,GAAG,CAAC,EAAE;AACvD,MAAI,KAAK;AACP,UAAM,OAAO,IAAI,MAAM,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE;AACxE,QAAI,KAAK,SAAS,EAAG,KAAI,KAAK,QAAQ,KAAK,KAAK,UAAK,CAAC,EAAE;AAAA,EAC1D;AACA,SAAO;AACT;AAMA,eAAsB,kBACpB,QACA,UACqC;AACrC,QAAM,aAAa,oBAAI,IAA2B;AAClD,aAAW,UAAU,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG;AAC/D,QAAI;AACF,YAAM,SAAS,yCAA4B,WAAW,MAAM,SAAS,MAAM,IAAI,qBAAqB;AACpG,UAAI,CAAC,OAAO,QAAS;AACrB,YAAM,EAAE,YAAY,YAAY,aAAa,GAAG,IAAI,IAAI,OAAO;AAC/D,iBAAW,IAAI,YAAY,GAAG;AAAA,IAChC,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,mBAAmB,GAAmC;AACpE,QAAM,IAAI,CAAC,MAA0C,MAAM,QAAQ,MAAM,SAAY,SAAS;AAC9F,QAAM,OAAO,EAAE,QAAQ,SAAS,gBAAgB,IAC5C,aAAa,EAAE,EAAE,eAAe,CAAC,aAAa,EAAE,EAAE,eAAe,CAAC,KAClE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;AAC3B,QAAM,KAAK,EAAE,WAAW,EAAE,QAAQ,SAAS,IAAI,aAAa,EAAE,QAAQ,KAAK,IAAI,CAAC,MAAM;AACtF,SAAO,QAAQ,EAAE,OAAO,KAAK,IAAI,GAAG,EAAE;AACxC;","names":[]}