import {
  DEFAULT_OPENCODE_DB,
  findOpencodeSessionsByDirectory,
  openOpencodeDb,
  parseClaudeEntries,
  transcriptFromEntries
} from "./chunk-VBQ3CRKH.js";
import {
  ROLLOUT_SCHEMA,
  isRolloutLine
} from "./chunk-MAX3TN3C.js";

// src/supervisor-run/types.ts
function unavailable(reason) {
  return { unavailable: reason };
}
function isUnavailable(v) {
  return typeof v === "object" && v !== null && typeof v.unavailable === "string";
}
function showMeasured(v) {
  if (isUnavailable(v)) return `unavailable \u2014 ${v.unavailable}`;
  if (v === null) return "null";
  return String(v);
}
var NO_SOURCE_LIMITS = {
  spendUsd: null,
  workerVerdicts: null,
  deliverables: null
};
var SUPERVISOR_RUN_SCHEMA = "tangle.supervisor-run@1";
var SUPERVISOR_RUN_ROLLUP_SCHEMA = "tangle.supervisor-run-rollup@1";

// src/supervisor-run/analyze.ts
function asRecord(v) {
  return typeof v === "object" && v !== null ? v : {};
}
function num(v) {
  return typeof v === "number" && Number.isFinite(v) ? v : 0;
}
function readSpend(v) {
  const rec = asRecord(v);
  const tok = asRecord(rec.tokens);
  const cacheRead = tok.cacheRead ?? tok.cache_read;
  const cacheWrite = tok.cacheWrite ?? tok.cache_write;
  return {
    tokens: {
      input: num(tok.input),
      output: num(tok.output),
      cacheRead: num(cacheRead),
      cacheWrite: num(cacheWrite),
      hasCache: cacheRead !== void 0 || cacheWrite !== void 0
    },
    usd: num(rec.usd)
  };
}
var NO_CACHE_COUNTERS = "the journal carries no cache-token counters for this role";
function parseJsonl(text) {
  if (text === null) return [];
  const out = [];
  for (const line2 of text.split("\n")) {
    const trimmed = line2.trim();
    if (!trimmed) continue;
    try {
      const parsed = JSON.parse(trimmed);
      if (typeof parsed === "object" && parsed !== null) out.push(parsed);
    } catch {
    }
  }
  return out;
}
function parseJson(text) {
  if (text === null) return null;
  try {
    const parsed = JSON.parse(text);
    return typeof parsed === "object" && parsed !== null ? parsed : null;
  } catch {
    return null;
  }
}
function ms(at) {
  if (typeof at !== "string") return null;
  const t = Date.parse(at);
  return Number.isFinite(t) ? t : null;
}
function parseSupervisorTree(src) {
  const events = parseJsonl(src.journal);
  const state = parseJson(src.state);
  const spawns = [];
  const closes = [];
  let brainIn = 0;
  let brainOut = 0;
  let brainCacheRead = 0;
  let brainCacheWrite = 0;
  let brainHasCache = false;
  let brainUsd = 0;
  let meteredCount = 0;
  let rootId = null;
  for (const ev of events) {
    const kind = typeof ev.kind === "string" ? ev.kind : "";
    const id = typeof ev.id === "string" ? ev.id : "";
    if (kind === "spawned") {
      const parent = typeof ev.parent === "string" ? ev.parent : null;
      const label = typeof ev.label === "string" ? ev.label : "";
      if (parent === null && rootId === null) rootId = id;
      spawns.push({ id, parent, label, at: ms(ev.at) });
    } else if (kind === "settled") {
      closes.push({
        id,
        kind: "settled",
        status: typeof ev.status === "string" ? ev.status : null,
        verdict: typeof ev.verdict === "string" ? ev.verdict : null,
        at: ms(ev.at),
        spend: readSpend(ev.spent),
        hasSpend: asRecord(ev.spent).tokens !== void 0
      });
    } else if (kind === "cancelled") {
      closes.push({
        id,
        kind: "cancelled",
        status: "cancelled",
        verdict: typeof ev.reason === "string" ? ev.reason : null,
        at: ms(ev.at),
        spend: {
          tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, hasCache: false },
          usd: 0
        },
        hasSpend: false
      });
    } else if (kind === "metered") {
      const s = readSpend(ev.spend);
      brainIn += s.tokens.input;
      brainOut += s.tokens.output;
      brainCacheRead += s.tokens.cacheRead;
      brainCacheWrite += s.tokens.cacheWrite;
      brainHasCache = brainHasCache || s.tokens.hasCache;
      brainUsd += s.usd;
      meteredCount += 1;
    }
  }
  const workerSpawns = spawns.filter((s) => s.id !== rootId);
  const workerIds = new Set(workerSpawns.map((s) => s.id));
  const workerCloses = closes.filter((c) => workerIds.has(c.id));
  const workerLogs = /* @__PURE__ */ new Map();
  for (const w of src.workers ?? []) {
    const facts = {
      started: null,
      finished: false,
      finishedAt: null,
      passed: null,
      finishedPatchBytes: null,
      evidenceBytes: 0,
      steersQueued: 0,
      steersDelivered: 0,
      questions: 0
    };
    for (const req of parseJsonl(w.inbox)) {
      if (typeof req.message === "string" && req.message.trim().length > 0) facts.steersQueued += 1;
    }
    for (const ev of parseJsonl(w.events)) {
      const kind = ev.kind;
      if (kind === "message") {
        if (ev.direction === "up") {
          facts.questions += 1;
          continue;
        }
        if (typeof ev.requestId !== "string") facts.steersQueued += 1;
        if (ev.delivered === true) facts.steersDelivered += 1;
      } else if (kind === "started") {
        facts.started = ms(ev.at);
      } else if (kind === "finished") {
        facts.finished = true;
        facts.finishedAt = ms(ev.at);
        facts.passed = typeof ev.passed === "boolean" ? ev.passed : null;
        facts.finishedPatchBytes = typeof ev.patchBytes === "number" ? ev.patchBytes : null;
        facts.evidenceBytes = typeof ev.evidence === "string" ? ev.evidence.length : 0;
      }
    }
    workerLogs.set(w.label, facts);
  }
  const startedAt = ms(state?.startedAt) ?? spawns[0]?.at ?? null;
  const completedAt = ms(state?.completedAt) ?? [...spawns.map((s) => s.at), ...closes.map((c) => c.at)].reduce(
    (acc, t) => t === null ? acc : acc === null ? t : Math.max(acc, t),
    null
  );
  return {
    rootId,
    spawns,
    closes,
    workerSpawns,
    workerCloses,
    brain: {
      tokensIn: brainIn,
      tokensOut: brainOut,
      cacheRead: brainCacheRead,
      cacheWrite: brainCacheWrite,
      hasCache: brainHasCache,
      usd: brainUsd,
      meteredCount
    },
    workerLogs,
    startedAt,
    completedAt
  };
}
function analyzeSupervisorRunSources(src, now = Date.now) {
  const gaps = [];
  const gap = (what, reason) => {
    gaps.push(`${what}: ${reason}`);
    return unavailable(reason);
  };
  const journalMissing = src.supRunDir === null ? "no supervisor run dir under <ws>/.loops/supervisor" : "journal.jsonl absent";
  const haveJournal = src.journal !== null;
  const state = parseJson(src.state);
  const result = parseJson(src.result);
  const judge = parseJson(src.judge);
  const tree = parseSupervisorTree(src);
  const { rootId, workerSpawns, workerCloses, startedAt, completedAt } = tree;
  const supervisorWallMs = startedAt !== null && completedAt !== null && completedAt >= startedAt ? completedAt - startedAt : !haveJournal ? gap("supervisorWallMs", journalMissing) : gap("supervisorWallMs", "no parseable start/complete timestamps in state.json or journal");
  const steerRows = [];
  let steerQueuedTotal = 0;
  let steerDeliveredTotal = 0;
  let upLegMessages = 0;
  if (src.workers !== null) {
    for (const w of src.workers) {
      const facts = tree.workerLogs.get(w.label);
      const queued = facts?.steersQueued ?? 0;
      const delivered = facts?.steersDelivered ?? 0;
      upLegMessages += facts?.questions ?? 0;
      steerRows.push({ worker: w.label, queued, delivered });
      steerQueuedTotal += queued;
      steerDeliveredTotal += delivered;
    }
  }
  const workersGapReason = src.workersMissingReason ?? "workers/ directory absent";
  const steers = src.workers === null ? gap("steers", workersGapReason) : steerQueuedTotal;
  const steersDelivered = src.workers === null ? unavailable(workersGapReason) : steerDeliveredTotal;
  const steersByWorker = src.workers === null ? unavailable(workersGapReason) : steerRows;
  const driverSteerCalls = src.driverLog === null ? gap("driverSteerCalls", "driver.log absent") : Math.max(
    0,
    (src.driverLog.match(/supervisor_steer/g) ?? []).length - registrationMentions(src.driverLog)
  );
  const timeline = [];
  for (const s of workerSpawns) if (s.at !== null) timeline.push({ at: s.at, delta: 1 });
  for (const c of workerCloses) if (c.at !== null) timeline.push({ at: c.at, delta: -1 });
  timeline.sort((a, b) => a.at - b.at || a.delta - b.delta);
  let waves = 0;
  const waveSizes = [];
  let closedSinceWaveStart = true;
  for (const step of timeline) {
    if (step.delta === 1) {
      if (closedSinceWaveStart) {
        waves += 1;
        waveSizes.push(0);
        closedSinceWaveStart = false;
      }
      waveSizes[waveSizes.length - 1] = (waveSizes[waveSizes.length - 1] ?? 0) + 1;
    } else {
      closedSinceWaveStart = true;
    }
  }
  let live = 0;
  let maxConcurrency = 0;
  let idleMs = 0;
  let sumWorkerWallMs = 0;
  let prev = startedAt;
  for (const step of timeline) {
    if (prev !== null && step.at >= prev) {
      const span = step.at - prev;
      if (live === 0) idleMs += span;
      sumWorkerWallMs += span * live;
    }
    live += step.delta;
    if (live > maxConcurrency) maxConcurrency = live;
    prev = step.at;
  }
  if (prev !== null && completedAt !== null && completedAt >= prev) {
    const span = completedAt - prev;
    if (live === 0) idleMs += span;
    sumWorkerWallMs += span * live;
  }
  const firstWorkerSpawnAt = workerSpawns.reduce(
    (acc, s) => s.at === null ? acc : acc === null ? s.at : Math.min(acc, s.at),
    null
  );
  const firstSettleAt = workerCloses.reduce(
    (acc, c) => c.at === null ? acc : acc === null ? c.at : Math.min(acc, c.at),
    null
  );
  const respawns = firstSettleAt === null ? 0 : workerSpawns.filter((s) => s.at !== null && s.at > firstSettleAt).length;
  const labelCounts = /* @__PURE__ */ new Map();
  for (const s of workerSpawns) labelCounts.set(s.label, (labelCounts.get(s.label) ?? 0) + 1);
  const repeatedLabels = [...labelCounts.entries()].filter(([, n]) => n > 1).map(([l]) => l);
  const parentOf = new Map(tree.spawns.map((s) => [s.id, s.parent]));
  let delegationDepth = 0;
  for (const s of workerSpawns) {
    let d = 0;
    let cur = s.id;
    const seen = /* @__PURE__ */ new Set();
    while (cur !== null && cur !== rootId && !seen.has(cur)) {
      seen.add(cur);
      d += 1;
      cur = parentOf.get(cur) ?? null;
    }
    if (d > delegationDepth) delegationDepth = d;
  }
  const orchestration = {
    workersSpawned: haveJournal ? workerSpawns.length : gap("workersSpawned", journalMissing),
    workersSettled: haveJournal ? workerCloses.filter((c) => c.kind === "settled").length : unavailable(journalMissing),
    workersCancelled: haveJournal ? workerCloses.filter((c) => c.kind === "cancelled").length : unavailable(journalMissing),
    steers,
    steersDelivered,
    steersByWorker,
    driverSteerCalls,
    waves: haveJournal ? waves : unavailable(journalMissing),
    waveSizes: haveJournal ? waveSizes : unavailable(journalMissing),
    maxConcurrency: haveJournal ? maxConcurrency : unavailable(journalMissing),
    respawns: haveJournal ? respawns : unavailable(journalMissing),
    repeatedLabels: haveJournal ? repeatedLabels : unavailable(journalMissing),
    delegationDepth: haveJournal ? delegationDepth : unavailable(journalMissing),
    timeToFirstSpawnMs: startedAt !== null && firstWorkerSpawnAt !== null ? firstWorkerSpawnAt - startedAt : haveJournal ? unavailable("no worker spawn timestamps") : unavailable(journalMissing),
    supervisorWallMs,
    idleMs: isUnavailable(supervisorWallMs) ? unavailable(supervisorWallMs.unavailable) : idleMs,
    idlePct: isUnavailable(supervisorWallMs) || supervisorWallMs === 0 ? isUnavailable(supervisorWallMs) ? unavailable(supervisorWallMs.unavailable) : unavailable("supervisor wall is 0ms") : round(idleMs / supervisorWallMs * 100, 1),
    workerUtilization: isUnavailable(supervisorWallMs) || supervisorWallMs === 0 ? isUnavailable(supervisorWallMs) ? unavailable(supervisorWallMs.unavailable) : unavailable("supervisor wall is 0ms") : round(sumWorkerWallMs / supervisorWallMs, 3)
  };
  const settledByStatus = {};
  const settledVerdicts = {};
  for (const c of workerCloses) {
    const key = c.status ?? "unknown";
    settledByStatus[key] = (settledByStatus[key] ?? 0) + 1;
    if (c.verdict !== null) settledVerdicts[c.verdict] = (settledVerdicts[c.verdict] ?? 0) + 1;
  }
  const verdictLimit = src.limits.workerVerdicts;
  let accepted = 0;
  let rejected = 0;
  let emptyPass = 0;
  let evidenceBytes = 0;
  for (const w of src.workers ?? []) {
    const f = tree.workerLogs.get(w.label);
    if (f === void 0 || !f.finished) continue;
    evidenceBytes += f.evidenceBytes;
    if (f.passed === true) {
      if ((f.finishedPatchBytes ?? 0) > 0) accepted += 1;
      else emptyPass += 1;
    } else if (f.passed === false) rejected += 1;
  }
  let observeThenRespawn = 0;
  let respawnWithoutEvidence = 0;
  const spawnTimes = workerSpawns.map((s) => s.at).filter((t) => t !== null).sort((a, b) => a - b);
  const closeTimes = workerCloses.map((c) => c.at).filter((t) => t !== null).sort((a, b) => a - b);
  for (let i = 1; i < spawnTimes.length; i += 1) {
    const prevSpawn = spawnTimes[i - 1];
    const thisSpawn = spawnTimes[i];
    const sawEvidence = closeTimes.some((t) => t >= prevSpawn && t <= thisSpawn);
    if (firstSettleAt !== null && thisSpawn > firstSettleAt) {
      if (sawEvidence) observeThenRespawn += 1;
      else respawnWithoutEvidence += 1;
    }
  }
  const decision = {
    settledByStatus: haveJournal ? settledByStatus : gap("settledByStatus", journalMissing),
    settledVerdicts: verdictLimit !== null ? unavailable(verdictLimit) : haveJournal ? settledVerdicts : unavailable(journalMissing),
    accepted: verdictLimit !== null ? gap("accepted", verdictLimit) : src.workers === null ? unavailable(workersGapReason) : accepted,
    rejected: verdictLimit !== null ? unavailable(verdictLimit) : src.workers === null ? unavailable(workersGapReason) : rejected,
    emptyPass: verdictLimit !== null || src.limits.deliverables !== null ? unavailable(verdictLimit ?? src.limits.deliverables) : src.workers === null ? unavailable(workersGapReason) : emptyPass,
    observeThenRespawn: haveJournal ? observeThenRespawn : unavailable(journalMissing),
    respawnWithoutEvidence: haveJournal ? respawnWithoutEvidence : unavailable(journalMissing),
    reviewActions: src.workers === null ? unavailable(workersGapReason) : steerQueuedTotal + upLegMessages,
    workerEvidenceBytes: src.workers === null ? unavailable(workersGapReason) : evidenceBytes
  };
  const journalWorkerIn = workerCloses.reduce((a, c) => a + c.spend.tokens.input, 0);
  const journalWorkerOut = workerCloses.reduce((a, c) => a + c.spend.tokens.output, 0);
  const journalWorkerUsd = workerCloses.reduce((a, c) => a + c.spend.usd, 0);
  const labelById = new Map(tree.workerSpawns.map((s) => [s.id, s.label]));
  const workerUsdByLabel = /* @__PURE__ */ new Map();
  for (const c of workerCloses) {
    const label = labelById.get(c.id);
    if (label === void 0) continue;
    workerUsdByLabel.set(label, (workerUsdByLabel.get(label) ?? 0) + c.spend.usd);
  }
  const sq = src.harnessWorkerTokens;
  const harnessGapReason = src.harnessMissingReason ?? "harness session store unavailable and journal settled spend is 0";
  const workerIn = sq !== null ? journalWorkerIn + sq.input : journalWorkerIn > 0 ? journalWorkerIn : gap("workers.tokensIn", harnessGapReason);
  const workerOut = sq !== null ? journalWorkerOut + sq.output : journalWorkerOut > 0 ? journalWorkerOut : unavailable(harnessGapReason);
  const stateResult = asRecord(state?.result);
  const stateUsd = typeof stateResult.spentUsd === "number" ? stateResult.spentUsd : null;
  const usdLimit = src.limits.spendUsd;
  const totalUsd = usdLimit !== null ? gap("totalUsd", usdLimit) : stateUsd !== null ? round(stateUsd, 6) : haveJournal ? round(tree.brain.usd + journalWorkerUsd, 6) : gap("totalUsd", journalMissing);
  const perWorker = (src.workers ?? []).map((w) => {
    const f = tree.workerLogs.get(w.label);
    return {
      worker: w.label,
      wallMs: f?.started != null && f.finishedAt != null ? f.finishedAt - f.started : null,
      tokensIn: w.tokensIn ?? null,
      tokensOut: w.tokensOut ?? null,
      usd: usdLimit !== null ? null : workerUsdByLabel.get(w.label) ?? null,
      patchBytes: w.patchBytes ?? f?.finishedPatchBytes ?? null,
      passed: f?.passed ?? null
    };
  });
  const walls = perWorker.map((w) => w.wallMs).filter((w) => w !== null).sort((a, b) => a - b);
  const brainCalls = parseJsonl(src.brainLog);
  const economics = {
    brain: {
      tokensIn: haveJournal ? tree.brain.tokensIn : gap("brain.tokensIn", journalMissing),
      tokensOut: haveJournal ? tree.brain.tokensOut : unavailable(journalMissing),
      usd: usdLimit !== null ? unavailable(usdLimit) : haveJournal ? round(tree.brain.usd, 6) : unavailable(journalMissing),
      cacheRead: !haveJournal ? unavailable(journalMissing) : tree.brain.hasCache ? tree.brain.cacheRead : unavailable(NO_CACHE_COUNTERS),
      cacheWrite: !haveJournal ? unavailable(journalMissing) : tree.brain.hasCache ? tree.brain.cacheWrite : unavailable(NO_CACHE_COUNTERS),
      source: haveJournal ? `journal metered events (n=${tree.brain.meteredCount})` : journalMissing
    },
    brainTruncations: src.brainLog === null ? gap(
      "brain.brainTruncations",
      src.supRunDir === null ? "no supervisor run dir under <ws>/.loops/supervisor" : "brain.jsonl absent \u2014 loops predates the brain-call tap, so truncation cannot be ruled out"
    ) : brainCalls.filter((c) => c.finish_reason === "length").length,
    workers: {
      tokensIn: workerIn,
      tokensOut: workerOut,
      cacheRead: sq?.cacheRead !== void 0 ? sq.cacheRead : unavailable(NO_CACHE_COUNTERS),
      cacheWrite: sq?.cacheWrite !== void 0 ? sq.cacheWrite : unavailable(NO_CACHE_COUNTERS),
      usd: usdLimit !== null ? unavailable(usdLimit) : haveJournal ? round(journalWorkerUsd, 6) : unavailable(journalMissing),
      source: sq !== null ? `journal settled spend + ${sq.store} sessions (n=${sq.sessions})` : `journal settled spend only \u2014 ${src.harnessMissingReason ?? "harness session store unavailable"}`
    },
    totalUsd,
    totalUsdSource: usdLimit !== null ? usdLimit : stateUsd !== null ? `state.json result.spentUsd${journalWorkerUsd === 0 ? " \u2014 brain-priced only; worker CLI inference is unpriced (see worker token counts)" : ""}` : haveJournal ? "journal metered + settled usd" : journalMissing,
    costPerAcceptedPatchUsd: isUnavailable(totalUsd) ? unavailable(totalUsd.unavailable) : isUnavailable(decision.accepted) ? unavailable(decision.accepted.unavailable) : decision.accepted === 0 ? unavailable("no accepted worker patch (cost has no denominator)") : round(totalUsd / decision.accepted, 6),
    workerWallMsDistribution: walls.length === 0 ? unavailable(
      src.workers === null ? workersGapReason : "no worker start/finish pairs captured"
    ) : {
      n: walls.length,
      min: walls[0],
      p50: quantile(walls, 0.5),
      p90: quantile(walls, 0.9),
      max: walls[walls.length - 1],
      sum: walls.reduce((a, b) => a + b, 0)
    },
    perWorker: src.workers === null ? unavailable(workersGapReason) : perWorker
  };
  const patchStats = src.patch === null ? gap("patch", src.limits.deliverables ?? "delivered patch file absent") : parsePatch(src.patch);
  const outcome = {
    supStatus: pickString(state, "status") ?? pickString(result, "sup_status") ?? gap("supStatus", "no state.json / result.json status"),
    supVerdict: pickString(state, "verdict") ?? pickString(result, "sup_verdict") ?? unavailable("no state.json / result.json verdict"),
    delivered: typeof stateResult.delivered === "boolean" ? stateResult.delivered : typeof result?.delivered === "boolean" ? result.delivered : unavailable("no delivered flag in state.json or result.json"),
    judgeResolved: judge === null ? gap("judge", "judge.json absent") : typeof judge.resolved === "boolean" ? judge.resolved : null,
    judgeScore: judge === null ? unavailable("judge.json absent") : typeof judge.score === "number" ? judge.score : null,
    judgePassed: judge === null ? unavailable("judge.json absent") : typeof judge.passed === "number" ? judge.passed : null,
    judgeTotal: judge === null ? unavailable("judge.json absent") : typeof judge.total === "number" ? judge.total : null,
    verifyPass: typeof result?.verify_pass === "boolean" ? result.verify_pass : gap("verifyPass", "result.json absent or has no verify_pass"),
    verifyRc: typeof result?.verify_rc === "number" ? result.verify_rc : unavailable("result.json absent or has no verify_rc"),
    patch: patchStats,
    judgeSource: src.judgeSource
  };
  return {
    schema: SUPERVISOR_RUN_SCHEMA,
    runRef: src.runRef,
    instanceId: src.instanceId,
    arm: src.arm,
    supervisorId: rootId !== null ? rootId : unavailable(journalMissing),
    generatedAt: new Date(now()).toISOString(),
    orchestration,
    decision,
    economics,
    outcome,
    gaps,
    traceCommand: src.traceCommand ?? "npx --yes @tangle-network/traces@latest analyze --harness opencode --cwd <worker-clone-cwd>"
  };
}
function registrationMentions(driverLog) {
  let n = 0;
  for (const line2 of driverLog.split("\n")) {
    if (line2.includes("registered tools:") && line2.includes("supervisor_steer")) n += 1;
  }
  return n;
}
function pickString(rec, key) {
  const v = rec?.[key];
  return typeof v === "string" ? v : null;
}
function round(v, digits) {
  const f = 10 ** digits;
  return Math.round(v * f) / f;
}
function quantile(sorted, q) {
  if (sorted.length === 0) return 0;
  const idx = Math.min(sorted.length - 1, Math.max(0, Math.ceil(q * sorted.length) - 1));
  return sorted[idx];
}
function parsePatch(text) {
  const files = /* @__PURE__ */ new Set();
  const testFiles = /* @__PURE__ */ new Set();
  let added = 0;
  let removed = 0;
  for (const line2 of text.split("\n")) {
    if (line2.startsWith("+++ ")) {
      const p = line2.slice(4).trim().replace(/^b\//, "");
      if (p !== "/dev/null") {
        files.add(p);
        if (isTestPath(p)) testFiles.add(p);
      }
      continue;
    }
    if (line2.startsWith("--- ") || line2.startsWith("diff --git") || line2.startsWith("index ")) {
      continue;
    }
    if (line2.startsWith("+")) added += 1;
    else if (line2.startsWith("-")) removed += 1;
  }
  return {
    files: files.size,
    linesAdded: added,
    linesRemoved: removed,
    testFilesTouched: [...testFiles].sort()
  };
}
function isTestPath(p) {
  const base = p.split("/").pop() ?? p;
  return /(^|\/)(tests?|__tests__|testing|spec)(\/|$)/.test(p) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(base) || /^test_.*\.py$/.test(base) || /_test\.py$/.test(base);
}
function rollupSupervisorRuns(reports) {
  const known = (vals) => vals.filter((v) => !isUnavailable(v));
  const steerVals = known(reports.map((r) => r.orchestration.steers));
  const waveVals = known(reports.map((r) => r.orchestration.waves));
  const concVals = known(reports.map((r) => r.orchestration.maxConcurrency));
  const utilVals = known(reports.map((r) => r.orchestration.workerUtilization));
  const idleVals = known(reports.map((r) => r.orchestration.idlePct));
  const spawnVals = known(reports.map((r) => r.orchestration.workersSpawned));
  const acceptVals = known(reports.map((r) => r.decision.accepted));
  const usdVals = known(reports.map((r) => r.economics.totalUsd));
  const resolvedVals = known(reports.map((r) => r.outcome.judgeResolved));
  const sum = (xs) => xs.reduce((a, b) => a + b, 0);
  const mean = (xs) => xs.length === 0 ? unavailable("no cell reported this metric") : round(sum(xs) / xs.length, 3);
  const perCell = reports.map((r) => ({
    instanceId: r.instanceId,
    arm: r.arm,
    steers: r.orchestration.steers,
    waves: r.orchestration.waves,
    utilization: r.orchestration.workerUtilization,
    idlePct: r.orchestration.idlePct,
    resolved: r.outcome.judgeResolved,
    usd: r.economics.totalUsd
  }));
  return {
    schema: SUPERVISOR_RUN_ROLLUP_SCHEMA,
    cells: reports.length,
    steersTotal: steerVals.length === 0 ? unavailable("no cell reported a steer count") : sum(steerVals),
    cellsWithSteers: steerVals.length === 0 ? unavailable("no cell reported a steer count") : steerVals.filter((n) => n > 0).length,
    cellsWithUnavailableSteers: reports.filter((r) => isUnavailable(r.orchestration.steers)).length,
    wavesMean: mean(waveVals),
    maxConcurrencyMax: concVals.length === 0 ? unavailable("no cell reported concurrency") : Math.max(...concVals),
    utilizationMean: mean(utilVals),
    idlePctMean: mean(idleVals),
    workersSpawnedTotal: spawnVals.length === 0 ? unavailable("no cell reported spawns") : sum(spawnVals),
    acceptedTotal: acceptVals.length === 0 ? unavailable("no cell reported acceptance") : sum(acceptVals),
    usdTotal: usdVals.length === 0 ? unavailable("no cell reported spend") : round(sum(usdVals), 6),
    resolvedCount: resolvedVals.length === 0 ? unavailable("no cell reported a judge verdict") : resolvedVals.filter((v) => v === true).length,
    perCell
  };
}

// src/supervisor-run/claude-code-reader.ts
import { readdir, readFile } from "fs/promises";
import { basename, dirname, join } from "path";
var DEFAULT_SPAWN_TOOLS = ["Agent", "Task"];
var DEFAULT_STEER_TOOLS = ["SendMessage"];
var DEFAULT_CANCEL_TOOLS = ["TaskStop", "KillAgent"];
var SPEND_UNPRICED = "Claude Code transcripts record token usage but never a price \u2014 usd is not in the store";
var NO_VERDICTS = "Claude Code runs no per-worker verify step \u2014 a subagent reports prose, not pass/fail";
var NO_DELIVERABLES = "Claude Code retains no per-worker patch \u2014 subagents commit to git, they do not hand back a diff";
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
var str = (v) => typeof v === "string" ? v : null;
function blockText(content) {
  if (typeof content === "string") return content;
  if (!Array.isArray(content)) return "";
  const parts = [];
  for (const b of content) {
    if (isRecord(b) && b.type === "text" && typeof b.text === "string") parts.push(b.text);
  }
  return parts.join("\n");
}
var tag = (xml, name) => {
  const m = xml.match(new RegExp(`<${name}>([\\s\\S]*?)</${name}>`));
  return m === null ? null : m[1];
};
function parseNotifications(text, at) {
  const out = [];
  for (const m of text.matchAll(/<task-notification>[\s\S]*?<\/task-notification>/g)) {
    const xml = m[0];
    const taskId = tag(xml, "task-id");
    if (taskId === null) continue;
    out.push({
      taskId: taskId.trim(),
      toolUseId: tag(xml, "tool-use-id")?.trim() ?? null,
      status: tag(xml, "status")?.trim() ?? "unknown",
      summary: tag(xml, "summary")?.trim() ?? null,
      at
    });
  }
  return out;
}
function threadCalls(entries) {
  const uses = [];
  const results = /* @__PURE__ */ new Map();
  const notifications = [];
  let firstAt = null;
  let lastAt = null;
  for (const entry of entries) {
    if (entry.timestamp !== null) {
      if (firstAt === null) firstAt = entry.timestamp;
      lastAt = entry.timestamp;
    }
    const content = entry.message.content;
    if (entry.type === "assistant") {
      if (!Array.isArray(content)) continue;
      for (const block of content) {
        if (!isRecord(block) || block.type !== "tool_use") continue;
        const id = str(block.id);
        const name = str(block.name);
        if (id === null || name === null) continue;
        uses.push({
          id,
          name,
          input: isRecord(block.input) ? block.input : {},
          at: entry.timestamp
        });
      }
      continue;
    }
    if (typeof content === "string") {
      notifications.push(...parseNotifications(content, entry.timestamp));
      continue;
    }
    if (!Array.isArray(content)) continue;
    for (const block of content) {
      if (!isRecord(block)) continue;
      if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
        results.set(block.tool_use_id, {
          id: block.tool_use_id,
          at: entry.timestamp,
          structured: entry.toolUseResult,
          text: blockText(block.content)
        });
      } else if (block.type === "text" && typeof block.text === "string") {
        notifications.push(...parseNotifications(block.text, entry.timestamp));
      }
    }
  }
  return { uses, results, notifications, firstAt, lastAt };
}
function spawnedAgentId(result) {
  if (result === void 0) return null;
  if (isRecord(result.structured)) {
    const id = str(result.structured.agentId);
    if (id !== null) return id;
  }
  return result.text.match(/agentId:\s*([A-Za-z0-9_-]+)/)?.[1] ?? null;
}
async function readChildren(dir) {
  const names = await readdir(dir).catch(() => null);
  if (names === null) return [];
  const out = [];
  for (const name of names.filter((n) => n.endsWith(".jsonl")).sort()) {
    const path = join(dir, name);
    const raw = await readFile(path, "utf8").catch(() => null);
    if (raw === null) continue;
    const entries = parseClaudeEntries(raw);
    const projected = transcriptFromEntries(entries, { includeSidechain: true });
    const metaRaw = await readFile(path.replace(/\.jsonl$/, ".meta.json"), "utf8").catch(() => null);
    let meta = {};
    if (metaRaw !== null) {
      try {
        const parsed = JSON.parse(metaRaw);
        if (isRecord(parsed)) meta = parsed;
      } catch {
        meta = {};
      }
    }
    const agentId = entries.find((e) => e.agentId !== null)?.agentId ?? name.replace(/^agent-/, "").replace(/\.jsonl$/, "");
    out.push({
      agentId,
      path,
      description: str(meta.description),
      spawnToolUseId: str(meta.toolUseId),
      spawnDepth: typeof meta.spawnDepth === "number" ? meta.spawnDepth : null,
      entries,
      tokensIn: projected.usage.tokensIn,
      tokensOut: projected.usage.tokensOut,
      cacheRead: projected.usage.cacheRead,
      cacheWrite: projected.usage.cacheWrite,
      firstAt: projected.startedAt,
      lastAt: projected.endedAt,
      model: projected.model,
      finalReport: [...projected.messages].reverse().find((m) => m.role === "assistant" && typeof m.content === "string")?.content ?? null
    });
  }
  return out;
}
var line = (obj) => JSON.stringify(obj);
async function readClaudeCodeSupervisorRun(opts) {
  const spawnTools = new Set(opts.spawnTools ?? DEFAULT_SPAWN_TOOLS);
  const steerTools = new Set(opts.steerTools ?? DEFAULT_STEER_TOOLS);
  const cancelTools = new Set(opts.cancelTools ?? DEFAULT_CANCEL_TOOLS);
  const raw = await readFile(opts.transcriptPath, "utf8").catch(() => null);
  const sessionId = basename(opts.transcriptPath).replace(/\.jsonl$/, "");
  const runRef = opts.runRef ?? opts.transcriptPath;
  const limits = { spendUsd: SPEND_UNPRICED, workerVerdicts: NO_VERDICTS, deliverables: null };
  const traceCommand = `npx --yes @tangle-network/traces@latest analyze --harness claude-code --session ${sessionId}`;
  if (raw === null) {
    return {
      runRef,
      instanceId: opts.instanceId ?? sessionId,
      arm: opts.arm ?? null,
      supRunDir: null,
      journal: null,
      brainLog: null,
      state: null,
      progress: null,
      workers: null,
      workersMissingReason: `session transcript unreadable at ${opts.transcriptPath}`,
      result: null,
      judge: null,
      judgeSource: null,
      patch: null,
      driverLog: null,
      harnessWorkerTokens: null,
      harnessMissingReason: `session transcript unreadable at ${opts.transcriptPath}`,
      limits: { ...limits, deliverables: NO_DELIVERABLES },
      traceCommand
    };
  }
  const allEntries = parseClaudeEntries(raw);
  const main = threadCalls(allEntries.filter((e) => !e.isSidechain));
  const mainTranscript = transcriptFromEntries(allEntries);
  const subagentsDir = opts.subagentsDir === void 0 ? join(dirname(opts.transcriptPath), sessionId, "subagents") : opts.subagentsDir;
  const children = subagentsDir === null ? [] : await readChildren(subagentsDir);
  const childByAgentId = new Map(children.map((c) => [c.agentId, c]));
  const childBySpawnToolUseId = new Map(
    children.filter((c) => c.spawnToolUseId !== null).map((c) => [c.spawnToolUseId, c])
  );
  const threads = [{ id: sessionId, calls: main }];
  for (const child of children) {
    threads.push({ id: child.agentId, calls: threadCalls(child.entries) });
  }
  const spawns = [];
  const steersByTarget = /* @__PURE__ */ new Map();
  const cancels = [];
  const settles = [];
  for (const thread of threads) {
    for (const use of thread.calls.uses) {
      if (spawnTools.has(use.name)) {
        const result = thread.calls.results.get(use.id);
        const agentId = spawnedAgentId(result) ?? childBySpawnToolUseId.get(use.id)?.agentId ?? null;
        if (agentId === null) continue;
        const label = str(use.input.description) ?? childByAgentId.get(agentId)?.description ?? agentId;
        spawns.push({
          agentId,
          parentId: thread.id,
          label,
          // The spawn is complete when the launch call is answered; the tool_use
          // instant is the fallback for a call that never got a result line.
          at: result?.at ?? use.at,
          model: isRecord(result?.structured) ? str(result.structured.resolvedModel) : null
        });
        continue;
      }
      if (steerTools.has(use.name)) {
        const target = str(use.input.to) ?? str(use.input.recipient);
        if (target === null) continue;
        const result = thread.calls.results.get(use.id);
        const structured = isRecord(result?.structured) ? result.structured : null;
        const delivered = structured?.success === true || str(structured?.resumedAgentId) === target;
        const rows = steersByTarget.get(target) ?? [];
        rows.push({ at: use.at, delivered });
        steersByTarget.set(target, rows);
        continue;
      }
      if (cancelTools.has(use.name)) {
        const target = str(use.input.agentId) ?? str(use.input.to) ?? str(use.input.taskId);
        if (target !== null) cancels.push({ agentId: target, at: use.at });
      }
    }
    settles.push(...thread.calls.notifications);
  }
  const spawnedIds = new Set(spawns.map((s) => s.agentId));
  const cancelledIds = new Set(
    cancels.filter((c) => spawnedIds.has(c.agentId)).map((c) => c.agentId)
  );
  const startedAt = main.firstAt;
  const completedAt = main.lastAt;
  const journalLines = [
    line({
      kind: "spawned",
      id: sessionId,
      parent: null,
      label: `session:${sessionId}`,
      at: startedAt
    })
  ];
  for (const s of spawns) {
    journalLines.push(
      line({ kind: "spawned", id: s.agentId, parent: s.parentId, label: s.label, at: s.at })
    );
  }
  const lastNotification = /* @__PURE__ */ new Map();
  for (const n of settles) {
    if (!spawnedIds.has(n.taskId)) continue;
    lastNotification.set(n.taskId, n);
  }
  for (const [agentId, n] of lastNotification) {
    if (cancelledIds.has(agentId)) continue;
    journalLines.push(
      line({
        kind: "settled",
        id: agentId,
        status: n.status,
        verdict: n.summary,
        at: n.at
        // No `spent` key: Claude Code prices nothing, and a zeroed spend object
        // would read as a $0 worker. `limits.spendUsd` carries the reason.
      })
    );
  }
  const lastCancel = /* @__PURE__ */ new Map();
  for (const c of cancels) {
    if (!spawnedIds.has(c.agentId)) continue;
    lastCancel.set(c.agentId, c);
  }
  for (const c of lastCancel.values()) {
    journalLines.push(
      line({ kind: "cancelled", id: c.agentId, reason: "stopped by supervisor", at: c.at })
    );
  }
  journalLines.push(
    line({
      kind: "metered",
      id: sessionId,
      spend: {
        tokens: {
          input: mainTranscript.usage.tokensIn,
          output: mainTranscript.usage.tokensOut,
          cacheRead: mainTranscript.usage.cacheRead,
          cacheWrite: mainTranscript.usage.cacheWrite
        }
      },
      at: completedAt
    })
  );
  const settleAtByAgent = new Map(
    [...lastNotification.entries()].map(([id, n]) => [id, n.at])
  );
  const spawnAtByAgent = new Map(spawns.map((s) => [s.agentId, s.at]));
  const byLabel = /* @__PURE__ */ new Map();
  for (const s of spawns) {
    const ids = byLabel.get(s.label) ?? [];
    ids.push(s.agentId);
    byLabel.set(s.label, ids);
  }
  const workers = [];
  for (const [label, agentIds] of byLabel) {
    const events = [];
    const inbox = [];
    let tokensIn = null;
    let tokensOut = null;
    let cacheRead = null;
    let cacheWrite = null;
    let transcriptRef = null;
    for (const agentId of agentIds) {
      const child = childByAgentId.get(agentId) ?? null;
      const startAt = child?.firstAt ?? spawnAtByAgent.get(agentId) ?? null;
      const endAt = settleAtByAgent.get(agentId) ?? child?.lastAt ?? null;
      if (startAt !== null) events.push(line({ kind: "started", label, at: startAt, agentId }));
      for (const steer of steersByTarget.get(agentId) ?? []) {
        inbox.push(
          line({ id: `${agentId}:${steer.at}`, at: steer.at, worker: label, message: "steer" })
        );
        events.push(
          line({
            kind: "message",
            label,
            direction: "down",
            at: steer.at,
            requestId: `${agentId}:${steer.at}`,
            delivered: steer.delivered
          })
        );
      }
      if (endAt !== null) {
        events.push(
          line({
            kind: "finished",
            label,
            at: endAt,
            agentId,
            // No `passed` / `patchBytes`: this harness has neither. Emitting
            // `passed: false` here would invent a failed worker.
            // `evidence` is the child's closing message — what it handed back.
            ...child?.finalReport === null || child?.finalReport === void 0 ? {} : { evidence: child.finalReport }
          })
        );
      }
      if (child !== null) {
        tokensIn = (tokensIn ?? 0) + child.tokensIn;
        tokensOut = (tokensOut ?? 0) + child.tokensOut;
        cacheRead = (cacheRead ?? 0) + child.cacheRead;
        cacheWrite = (cacheWrite ?? 0) + child.cacheWrite;
        transcriptRef = child.path;
      }
    }
    workers.push({
      label,
      events: events.length === 0 ? null : `${events.join("\n")}
`,
      inbox: inbox.length === 0 ? null : `${inbox.join("\n")}
`,
      patchBytes: null,
      transcriptRef,
      patchPath: null,
      tokensIn,
      tokensOut,
      cacheRead,
      cacheWrite
    });
  }
  const joined = children.length;
  const harnessWorkerTokens = joined === 0 ? null : {
    store: "claude-code subagent transcripts",
    sessions: joined,
    input: children.reduce((a, c) => a + c.tokensIn, 0),
    output: children.reduce((a, c) => a + c.tokensOut, 0),
    cacheRead: children.reduce((a, c) => a + c.cacheRead, 0),
    cacheWrite: children.reduce((a, c) => a + c.cacheWrite, 0)
  };
  const missingChildren = spawns.filter((s) => !childByAgentId.has(s.agentId)).length;
  const harnessMissingReason = subagentsDir === null ? "subagent transcript join disabled" : joined === 0 ? `no subagent transcripts under ${subagentsDir}` : missingChildren === 0 ? null : `${missingChildren}/${spawns.length} spawned agents have no retained transcript under ${subagentsDir} (Claude Code prunes them; their tokens are unrecoverable)`;
  const liveWorkers = spawns.filter(
    (s) => !lastNotification.has(s.agentId) && !cancelledIds.has(s.agentId)
  ).length;
  const state = JSON.stringify({
    id: sessionId,
    // Derived, not asserted: a spawned agent with no notification and no stop
    // is still running, which is exactly what a live transcript looks like.
    status: liveWorkers > 0 ? "running" : "idle",
    startedAt,
    completedAt,
    result: { delivered: null }
  });
  return {
    runRef,
    instanceId: opts.instanceId ?? sessionId,
    arm: opts.arm ?? null,
    supRunDir: subagentsDir,
    journal: `${journalLines.join("\n")}
`,
    brainLog: null,
    state,
    progress: null,
    workers,
    workersMissingReason: null,
    result: null,
    judge: null,
    judgeSource: null,
    patch: null,
    driverLog: null,
    harnessWorkerTokens,
    harnessMissingReason,
    limits: { ...limits, deliverables: NO_DELIVERABLES },
    rootTranscriptRef: opts.transcriptPath,
    traceCommand
  };
}
function claudeCodeSupervisorRunReader(opts) {
  return {
    runRef: opts.runRef ?? opts.transcriptPath,
    read: () => readClaudeCodeSupervisorRun(opts)
  };
}

// src/supervisor-run/loops-reader.ts
import { appendFile, mkdir, readdir as readdir2, readFile as readFile2, writeFile } from "fs/promises";
import { basename as basename2, join as join2 } from "path";

// src/supervisor-run/render.ts
function renderSupervisorRunHeadline(r) {
  const o = r.orchestration;
  const steerNote = isUnavailable(o.steers) ? `unavailable \u2014 ${o.steers.unavailable}` : o.steers === 0 ? "0 (spawn\u2192wait\u2192respawn only; no mid-task steering)" : `${o.steers} queued / ${showMeasured(o.steersDelivered)} delivered`;
  return [
    `RUN-REPORT ${r.instanceId ?? "?"} [${r.arm ?? "?"}]`,
    `  steers=${steerNote}`,
    `  waves=${showMeasured(o.waves)} sizes=${isUnavailable(o.waveSizes) ? `unavailable \u2014 ${o.waveSizes.unavailable}` : `[${o.waveSizes.join(",")}]`} workers=${showMeasured(o.workersSpawned)} settled=${showMeasured(o.workersSettled)} cancelled=${showMeasured(o.workersCancelled)}`,
    `  concurrency max=${showMeasured(o.maxConcurrency)} utilization=${showMeasured(o.workerUtilization)} idle=${fmtMs(o.idleMs)} (${showMeasured(o.idlePct)}%) wall=${fmtMs(o.supervisorWallMs)}`,
    `  respawns=${showMeasured(o.respawns)} evidence\u2192respawn=${showMeasured(r.decision.observeThenRespawn)} blind-respawn=${showMeasured(r.decision.respawnWithoutEvidence)} depth=${showMeasured(o.delegationDepth)}`,
    `  accepted=${showMeasured(r.decision.accepted)} rejected=${showMeasured(r.decision.rejected)} empty-pass=${showMeasured(r.decision.emptyPass)}`,
    `  brain=$${showMeasured(r.economics.brain.usd)} total=$${showMeasured(r.economics.totalUsd)} judge.resolved=${showMeasured(r.outcome.judgeResolved)} score=${showMeasured(r.outcome.judgeScore)} verify=${showMeasured(r.outcome.verifyPass)}`,
    r.gaps.length > 0 ? `  gaps(${r.gaps.length}): ${r.gaps.join("; ")}` : "  gaps: none"
  ].join("\n");
}
function fmtMs(v) {
  if (isUnavailable(v)) return `unavailable \u2014 ${v.unavailable}`;
  if (v < 1e3) return `${v}ms`;
  const s = v / 1e3;
  if (s < 120) return `${round(s, 1)}s`;
  return `${round(s / 60, 1)}min`;
}
function renderSupervisorRunMarkdown(r) {
  const o = r.orchestration;
  const d = r.decision;
  const e = r.economics;
  const out = [];
  out.push(`# Run report \u2014 ${r.instanceId ?? "unknown instance"} [${r.arm ?? "unknown arm"}]`);
  out.push("");
  out.push("```");
  out.push(renderSupervisorRunHeadline(r));
  out.push("```");
  out.push("");
  out.push(`- Run: \`${r.runRef}\``);
  out.push(`- Supervisor: \`${showMeasured(r.supervisorId)}\``);
  out.push(`- Generated: ${r.generatedAt}`);
  out.push("");
  out.push("## Orchestration");
  out.push("");
  out.push("| Metric | Value |");
  out.push("|---|---|");
  out.push(`| Workers spawned | ${showMeasured(o.workersSpawned)} |`);
  out.push(`| Workers settled | ${showMeasured(o.workersSettled)} |`);
  out.push(`| Workers cancelled | ${showMeasured(o.workersCancelled)} |`);
  out.push(`| **Steers (mid-task messages to live workers)** | **${showMeasured(o.steers)}** |`);
  out.push(`| Steers delivered | ${showMeasured(o.steersDelivered)} |`);
  out.push(`| Outer-driver \`supervisor_steer\` calls | ${showMeasured(o.driverSteerCalls)} |`);
  out.push(`| Spawn waves | ${showMeasured(o.waves)} |`);
  out.push(
    `| Wave sizes | ${isUnavailable(o.waveSizes) ? showMeasured(o.waveSizes) : `[${o.waveSizes.join(", ")}]`} |`
  );
  out.push(`| Max concurrency | ${showMeasured(o.maxConcurrency)} |`);
  out.push(`| Respawns (spawns after first settle) | ${showMeasured(o.respawns)} |`);
  out.push(
    `| Repeated labels | ${isUnavailable(o.repeatedLabels) ? showMeasured(o.repeatedLabels) : o.repeatedLabels.length === 0 ? "none" : o.repeatedLabels.join(", ")} |`
  );
  out.push(`| Delegation depth | ${showMeasured(o.delegationDepth)} |`);
  out.push(`| Time to first spawn | ${fmtMs(o.timeToFirstSpawnMs)} |`);
  out.push(`| Supervisor wall | ${fmtMs(o.supervisorWallMs)} |`);
  out.push(`| Idle (zero live workers) | ${fmtMs(o.idleMs)} (${showMeasured(o.idlePct)}%) |`);
  out.push(
    `| Worker utilization (\u03A3 worker wall \xF7 supervisor wall) | ${showMeasured(o.workerUtilization)} |`
  );
  out.push("");
  if (!isUnavailable(o.steersByWorker) && o.steersByWorker.length > 0) {
    out.push("### Steers per worker");
    out.push("");
    out.push("| Worker | Queued | Delivered |");
    out.push("|---|---:|---:|");
    for (const s of o.steersByWorker) out.push(`| \`${s.worker}\` | ${s.queued} | ${s.delivered} |`);
    out.push("");
  } else if (isUnavailable(o.steersByWorker)) {
    out.push(`### Steers per worker

unavailable \u2014 ${o.steersByWorker.unavailable}
`);
  }
  out.push("## Decision quality");
  out.push("");
  out.push("| Metric | Value |");
  out.push("|---|---|");
  out.push(`| Settled by status | ${fmtCounts(d.settledByStatus)} |`);
  out.push(`| Settled verdicts | ${fmtCounts(d.settledVerdicts)} |`);
  out.push(`| Accepted (verify green + patch bytes) | ${showMeasured(d.accepted)} |`);
  out.push(`| Rejected (verify red) | ${showMeasured(d.rejected)} |`);
  out.push(`| Empty pass (green, no patch) | ${showMeasured(d.emptyPass)} |`);
  out.push(`| Evidence \u2192 respawn sequences | ${showMeasured(d.observeThenRespawn)} |`);
  out.push(
    `| Respawn with no settled evidence in front | ${showMeasured(d.respawnWithoutEvidence)} |`
  );
  out.push(`| Review actions (steers + worker questions) | ${showMeasured(d.reviewActions)} |`);
  out.push(
    `| Worker evidence returned | ${isUnavailable(d.workerEvidenceBytes) ? showMeasured(d.workerEvidenceBytes) : `${d.workerEvidenceBytes} bytes`} |`
  );
  out.push("");
  out.push("## Economics");
  out.push("");
  out.push("| Role | Tokens in | Tokens out | Cache read | Cache write | USD | Source |");
  out.push("|---|---:|---:|---:|---:|---:|---|");
  out.push(
    `| brain | ${showMeasured(e.brain.tokensIn)} | ${showMeasured(e.brain.tokensOut)} | ${showMeasured(e.brain.cacheRead)} | ${showMeasured(e.brain.cacheWrite)} | ${showMeasured(e.brain.usd)} | ${e.brain.source} |`
  );
  out.push(
    `| workers | ${showMeasured(e.workers.tokensIn)} | ${showMeasured(e.workers.tokensOut)} | ${showMeasured(e.workers.cacheRead)} | ${showMeasured(e.workers.cacheWrite)} | ${showMeasured(e.workers.usd)} | ${e.workers.source} |`
  );
  out.push("");
  if (!isUnavailable(e.brainTruncations) && e.brainTruncations > 0) {
    out.push(
      `- **BRAIN OUTPUT TRUNCATED: ${e.brainTruncations} completion(s) hit \`finish_reason: "length"\`** \u2014 the supervisor acted on a half-written plan. Its output ceiling is too low; see \`brain.jsonl\` for the per-call \`req_max_tokens\`.`
    );
  } else {
    out.push(
      `- Brain completions truncated (finish_reason=length): ${showMeasured(e.brainTruncations)}`
    );
  }
  out.push(`- Total USD: ${showMeasured(e.totalUsd)} (source: ${e.totalUsdSource})`);
  out.push(`- Cost per accepted patch: ${showMeasured(e.costPerAcceptedPatchUsd)}`);
  if (isUnavailable(e.workerWallMsDistribution)) {
    out.push(`- Worker wall distribution: unavailable \u2014 ${e.workerWallMsDistribution.unavailable}`);
  } else {
    const w = e.workerWallMsDistribution;
    out.push(
      `- Worker wall (n=${w.n}): min ${fmtMs(w.min)} / p50 ${fmtMs(w.p50)} / p90 ${fmtMs(w.p90)} / max ${fmtMs(w.max)} / \u03A3 ${fmtMs(w.sum)}`
    );
  }
  out.push("");
  if (!isUnavailable(e.perWorker) && e.perWorker.length > 0) {
    out.push("| Worker | Wall | Tokens in | Tokens out | Patch bytes | Verify passed |");
    out.push("|---|---:|---:|---:|---:|---|");
    for (const w of e.perWorker) {
      out.push(
        `| \`${w.worker}\` | ${w.wallMs === null ? "unavailable \u2014 no start/finish pair" : fmtMs(w.wallMs)} | ${w.tokensIn ?? "unavailable \u2014 store does not attribute tokens per worker"} | ${w.tokensOut ?? "unavailable \u2014 store does not attribute tokens per worker"} | ${w.patchBytes ?? "unavailable \u2014 no worker patch file"} | ${w.passed === null ? "unavailable \u2014 no finished event" : String(w.passed)} |`
      );
    }
    out.push("");
  }
  out.push("## Outcome");
  out.push("");
  out.push("| Metric | Value |");
  out.push("|---|---|");
  out.push(`| Supervisor status | ${showMeasured(r.outcome.supStatus)} |`);
  out.push(`| Supervisor verdict | ${showMeasured(r.outcome.supVerdict)} |`);
  out.push(`| Delivered | ${showMeasured(r.outcome.delivered)} |`);
  out.push(`| Judge resolved | ${showMeasured(r.outcome.judgeResolved)} |`);
  out.push(`| Judge score | ${showMeasured(r.outcome.judgeScore)} |`);
  out.push(
    `| Judge passed / total | ${showMeasured(r.outcome.judgePassed)} / ${showMeasured(r.outcome.judgeTotal)} |`
  );
  out.push(
    `| Judge source | ${r.outcome.judgeSource ?? "unavailable \u2014 no judge.json and no ledger row"} |`
  );
  out.push(
    `| Verify gate | pass=${showMeasured(r.outcome.verifyPass)} rc=${showMeasured(r.outcome.verifyRc)} |`
  );
  if (isUnavailable(r.outcome.patch)) {
    out.push(`| Patch | unavailable \u2014 ${r.outcome.patch.unavailable} |`);
  } else {
    const p = r.outcome.patch;
    out.push(
      `| Patch | ${p.files} file(s), +${p.linesAdded}/-${p.linesRemoved}, test files touched: ${p.testFilesTouched.length === 0 ? "none" : p.testFilesTouched.join(", ")} |`
    );
  }
  out.push("");
  out.push("## Gaps");
  out.push("");
  if (r.gaps.length === 0) out.push("None \u2014 every metric above is backed by a present artifact.");
  else for (const g of r.gaps) out.push(`- ${g}`);
  out.push("");
  out.push(
    `> Harness-session view of the same run (model calls, stuck loops, tool errors): \`${r.traceCommand}\``
  );
  out.push("");
  return out.join("\n");
}
function fmtCounts(v) {
  if (isUnavailable(v)) return showMeasured(v);
  const entries = Object.entries(v);
  return entries.length === 0 ? "none" : entries.map(([k, n]) => `${k}=${n}`).join(", ");
}
function renderSupervisorRollupMarkdown(rollup, title = "Round rollup") {
  const out = [];
  out.push(`# ${title}`);
  out.push("");
  out.push(`- Cells: ${rollup.cells}`);
  out.push(
    `- **Steers across all cells: ${showMeasured(rollup.steersTotal)}** (cells with \u22651 steer: ${showMeasured(rollup.cellsWithSteers)}; cells where the steer count is unavailable: ${rollup.cellsWithUnavailableSteers})`
  );
  out.push(`- Waves per cell (mean): ${showMeasured(rollup.wavesMean)}`);
  out.push(`- Max concurrency observed: ${showMeasured(rollup.maxConcurrencyMax)}`);
  out.push(`- Worker utilization (mean): ${showMeasured(rollup.utilizationMean)}`);
  out.push(`- Idle share (mean): ${showMeasured(rollup.idlePctMean)}%`);
  out.push(
    `- Workers spawned: ${showMeasured(rollup.workersSpawnedTotal)} \xB7 accepted: ${showMeasured(rollup.acceptedTotal)}`
  );
  out.push(
    `- Spend: $${showMeasured(rollup.usdTotal)} \xB7 judged resolved: ${showMeasured(rollup.resolvedCount)}/${rollup.cells}`
  );
  out.push("");
  out.push("| Instance | Arm | Steers | Waves | Utilization | Idle % | Resolved | USD |");
  out.push("|---|---|---:|---:|---:|---:|---|---:|");
  for (const c of rollup.perCell) {
    out.push(
      `| ${c.instanceId ?? "?"} | ${c.arm ?? "?"} | ${showMeasured(c.steers)} | ${showMeasured(c.waves)} | ${showMeasured(c.utilization)} | ${showMeasured(c.idlePct)} | ${showMeasured(c.resolved)} | ${showMeasured(c.usd)} |`
    );
  }
  out.push("");
  return out.join("\n");
}

// src/supervisor-run/loops-reader.ts
async function readMaybe(path) {
  return readFile2(path, "utf8").catch(() => null);
}
async function findSupervisorRunDirIn(ws) {
  const root = join2(ws, ".loops", "supervisor");
  const entries = await readdir2(root, { withFileTypes: true }).catch(() => []);
  const dirs = entries.filter((e) => e.isDirectory()).map((e) => join2(root, e.name));
  return dirs[0] ?? null;
}
async function readLoopsSupervisorRun(runDir, opts = {}) {
  const ws = opts.ws ?? join2(runDir, "ws");
  const supRunDir = await findSupervisorRunDirIn(ws);
  const result = await readMaybe(join2(runDir, "result.json"));
  const resultObj = parseJson(result);
  let workers = null;
  let workersMissingReason = null;
  const workerCwds = [];
  if (supRunDir === null) {
    workersMissingReason = `no supervisor run dir under ${join2(ws, ".loops", "supervisor")}`;
  } else {
    const workersDir = join2(supRunDir, "workers");
    const entries = await readdir2(workersDir).catch(() => null);
    if (entries === null) {
      workersMissingReason = `workers/ directory absent under ${supRunDir}`;
    } else {
      const labels = [
        ...new Set(
          entries.filter((f) => f.endsWith(".ndjson")).map((f) => f.replace(/\.inbox\.ndjson$/, "").replace(/\.ndjson$/, ""))
        )
      ].sort();
      workers = [];
      for (const label of labels) {
        const events = await readMaybe(join2(workersDir, `${label}.ndjson`));
        const inbox = await readMaybe(join2(workersDir, `${label}.inbox.ndjson`));
        const patch = await readMaybe(join2(workersDir, `${label}.patch`));
        workers.push({
          label,
          events,
          inbox,
          patchBytes: patch === null ? null : Buffer.byteLength(patch)
        });
        for (const ev of parseJsonl(events)) {
          if (ev.kind === "started" && typeof ev.cwd === "string") workerCwds.push(ev.cwd);
        }
      }
    }
  }
  let harnessWorkerTokens = null;
  let harnessMissingReason = null;
  if (opts.opencodeDb === null) {
    harnessMissingReason = "opencode join disabled";
  } else if (workerCwds.length === 0) {
    harnessMissingReason = "no worker clone cwds in workers/*.ndjson (nothing to join)";
  } else {
    const db = await openOpencodeDb(opts.opencodeDb ?? DEFAULT_OPENCODE_DB);
    if (db === null) {
      harnessMissingReason = `opencode session store unreadable at ${opts.opencodeDb ?? DEFAULT_OPENCODE_DB}`;
    } else {
      try {
        const seen = /* @__PURE__ */ new Set();
        let sessions = 0;
        let input = 0;
        let output = 0;
        for (const cwd of new Set(workerCwds)) {
          for (const row of findOpencodeSessionsByDirectory(db, cwd)) {
            if (seen.has(row.id)) continue;
            seen.add(row.id);
            sessions += 1;
            input += row.tokensInput;
            output += row.tokensOutput + row.tokensReasoning;
          }
        }
        harnessWorkerTokens = { store: "opencode", sessions, input, output };
      } finally {
        db.close();
      }
    }
  }
  const patchPath = opts.patchPath ?? (typeof resultObj?.patchPath === "string" ? resultObj.patchPath : null);
  let judge = await readMaybe(join2(runDir, "judge.json"));
  let judgeSource = judge === null ? null : join2(runDir, "judge.json");
  if (judge === null && opts.ledgerPath !== void 0) {
    const row = await findLedgerRow(opts.ledgerPath, runDir);
    if (row !== null) {
      judge = JSON.stringify(row);
      judgeSource = `${opts.ledgerPath} (ledger row)`;
    }
  }
  return {
    runRef: runDir,
    instanceId: typeof resultObj?.iid === "string" ? resultObj.iid : instanceIdFromPath(runDir),
    arm: typeof resultObj?.arm === "string" ? resultObj.arm : basename2(runDir),
    supRunDir,
    journal: supRunDir === null ? null : await readMaybe(join2(supRunDir, "journal.jsonl")),
    brainLog: supRunDir === null ? null : await readMaybe(join2(supRunDir, "brain.jsonl")),
    state: supRunDir === null ? null : await readMaybe(join2(supRunDir, "state.json")),
    progress: supRunDir === null ? null : await readMaybe(join2(supRunDir, "progress.ndjson")),
    workers,
    workersMissingReason,
    result,
    judge,
    judgeSource,
    patch: patchPath === null ? null : await readMaybe(patchPath),
    driverLog: await readMaybe(join2(runDir, "driver.log")),
    harnessWorkerTokens,
    harnessMissingReason,
    // loops prices its own inference, runs a verify per worker, and keeps each
    // worker's patch — every fact the analyzer can use is expressible here.
    limits: NO_SOURCE_LIMITS,
    traceCommand: null
  };
}
function loopsSupervisorRunReader(runDir, opts = {}) {
  return { runRef: runDir, read: () => readLoopsSupervisorRun(runDir, opts) };
}
async function findLedgerRow(ledgerPath, runDir) {
  const rows = parseJsonl(await readMaybe(ledgerPath));
  const exact = rows.find((r) => r.runDir === runDir);
  if (exact !== void 0) return exact;
  const iid = instanceIdFromPath(runDir);
  const arm = basename2(runDir);
  return rows.find((r) => r.iid === iid && r.arm === arm) ?? null;
}
function instanceIdFromPath(runDir) {
  const parts = runDir.split("/").filter(Boolean);
  const armIdx = parts.length - 1;
  const iid = parts[armIdx - 1];
  return parts[armIdx - 2] === "runs" && iid !== void 0 ? iid : null;
}
async function analyzeSupervisorRun(input, opts = {}) {
  if (typeof input === "string") {
    return analyzeSupervisorRunSources(await readLoopsSupervisorRun(input, opts));
  }
  if (isReader(input)) return analyzeSupervisorRunSources(await input.read());
  return analyzeSupervisorRunSources(input);
}
function isReader(input) {
  return typeof input.read === "function";
}
async function writeSupervisorRunReport(runDir, opts = {}) {
  const sources = await readLoopsSupervisorRun(runDir, opts);
  const report = analyzeSupervisorRunSources(sources);
  const md = renderSupervisorRunMarkdown(report);
  const dest = opts.reportDir ?? runDir;
  const stem = opts.reportDir === void 0 ? "run-report" : supervisorReportStem(runDir);
  if (opts.reportDir !== void 0) await mkdir(opts.reportDir, { recursive: true }).catch(() => {
  });
  await writeFile(join2(dest, `${stem}.json`), JSON.stringify(report, null, 1)).catch(() => {
  });
  await writeFile(join2(dest, `${stem}.md`), md).catch(() => {
  });
  const headline = renderSupervisorRunHeadline(report);
  if (opts.appendHeadlineTo !== void 0) {
    await appendFile(opts.appendHeadlineTo, `${headline}
`).catch(() => {
    });
  }
  if (opts.echo !== false) console.log(headline);
  return report;
}
function supervisorReportStem(runDir) {
  const parts = runDir.split("/").filter(Boolean);
  const arm = parts[parts.length - 1] ?? "cell";
  const iid = parts[parts.length - 2] ?? "instance";
  const rep = parts.find((p) => /^rep-\d+$/.test(p));
  const armRunsIdx = parts.indexOf("arm-runs");
  const tag2 = armRunsIdx >= 0 ? parts[armRunsIdx + 1] : void 0;
  return [tag2, rep, iid, arm].filter((s) => s !== void 0 && s !== "runs").join(".").replace(/[^A-Za-z0-9._-]/g, "_");
}
async function writeSupervisorRunReportSafe(runDir, opts = {}) {
  try {
    return await writeSupervisorRunReport(runDir, opts);
  } catch (err) {
    console.log(
      `RUN-REPORT failed for ${runDir}: ${err instanceof Error ? err.message : String(err)}`
    );
    return null;
  }
}
async function reportSupervisorRound(outDir, opts = {}) {
  const runDirs = await findSupervisorRunDirs(outDir);
  const reports = [];
  for (const runDir of runDirs) {
    const r = await writeSupervisorRunReportSafe(runDir, { ...opts, echo: opts.echo ?? false });
    if (r !== null) reports.push(r);
  }
  const rollup = rollupSupervisorRuns(reports);
  const md = renderSupervisorRollupMarkdown(
    rollup,
    opts.title ?? `Round rollup \u2014 ${basename2(outDir)}`
  );
  const dest = opts.reportDir ?? outDir;
  if (opts.reportDir !== void 0) await mkdir(opts.reportDir, { recursive: true }).catch(() => {
  });
  await writeFile(join2(dest, "run-report-round.json"), JSON.stringify(rollup, null, 1)).catch(
    () => {
    }
  );
  await writeFile(join2(dest, "run-report-round.md"), md).catch(() => {
  });
  if (opts.appendHeadlineTo !== void 0) {
    await appendFile(opts.appendHeadlineTo, `${md}
`).catch(() => {
    });
  }
  if (opts.echo !== false) console.log(md);
  return rollup;
}
async function findSupervisorRunDirs(root) {
  const found = [];
  const walk = async (dir, depth) => {
    if (depth > 8) return;
    const entries = await readdir2(dir, { withFileTypes: true }).catch(() => []);
    for (const e of entries) {
      if (!e.isDirectory()) continue;
      if (e.name === "node_modules" || e.name === ".git") continue;
      const full = join2(dir, e.name);
      if (e.name === "runs") {
        const iids = await readdir2(full, { withFileTypes: true }).catch(() => []);
        for (const iid of iids) {
          if (!iid.isDirectory()) continue;
          const arms = await readdir2(join2(full, iid.name), { withFileTypes: true }).catch(() => []);
          for (const arm of arms) if (arm.isDirectory()) found.push(join2(full, iid.name, arm.name));
        }
        continue;
      }
      await walk(full, depth + 1);
    }
  };
  await walk(root, 0);
  return found.sort();
}

// src/supervisor-run/rollout-nodes.ts
var EMPTY_COST = {
  usd: null,
  tokens_in: null,
  tokens_out: null,
  tokens_reasoning: null,
  cache_read: null,
  cache_write: null,
  wall_s: null
};
function supervisorRunRolloutLines(src, opts = {}) {
  const gaps = [];
  const tree = parseSupervisorTree(src);
  if (src.journal === null) {
    gaps.push(
      `tree: ${src.supRunDir === null ? "no supervisor run dir" : "journal absent"} \u2014 no nodes recoverable`
    );
    return { rootId: null, nodes: [], gaps };
  }
  const state = parseJson(src.state);
  const result = parseJson(src.result);
  const judge = parseJson(src.judge);
  const stateResult = asRecord(state?.result);
  const rootId = tree.rootId;
  const runId = opts.runId ?? rootId ?? src.runRef;
  const suite = opts.suite ?? "supervisor-run";
  const instanceId = src.instanceId ?? src.runRef;
  const split = opts.split ?? "search";
  const capturedAt = opts.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString();
  const base = {
    schema: ROLLOUT_SCHEMA,
    run_id: runId,
    experiment_id: opts.experimentId ?? null,
    candidate_id: opts.candidateId ?? null,
    generation: opts.generation ?? null,
    candidate_index: opts.candidateIndex ?? null,
    task: {
      suite,
      instance_id: instanceId,
      split,
      seed: opts.seed ?? null,
      rep: opts.rep ?? 0
    },
    messages: [],
    tool_defs: []
  };
  const nodes = [];
  if (rootId !== null) {
    const judgeResolved = typeof judge?.resolved === "boolean" ? judge.resolved : null;
    const judgeScore = typeof judge?.score === "number" ? judge.score : null;
    const reward = judgeScore ?? (judgeResolved === null ? null : judgeResolved ? 1 : 0);
    if (reward === null) gaps.push("root.outcome.reward: no judge verdict for this run");
    const wallMs = tree.startedAt !== null && tree.completedAt !== null && tree.completedAt >= tree.startedAt ? tree.completedAt - tree.startedAt : null;
    nodes.push({
      ...base,
      rollout_id: rootId,
      parent_rollout_id: null,
      role: "supervisor",
      policy: {
        harness: opts.supervisorHarness ?? null,
        harness_version: null,
        model: opts.supervisorModel ?? null,
        provider: null,
        profile_commit: null,
        sampling: null
      },
      outcome: {
        reward,
        reward_source: src.judgeSource,
        verdict: judge ?? null,
        metrics: {
          arm: src.arm,
          sup_status: typeof state?.status === "string" ? state.status : null,
          sup_verdict: typeof state?.verdict === "string" ? state.verdict : null,
          delivered: typeof stateResult.delivered === "boolean" ? stateResult.delivered : null,
          verify_pass: typeof result?.verify_pass === "boolean" ? result.verify_pass : null,
          started_at: tree.startedAt,
          completed_at: tree.completedAt,
          workers_spawned: tree.workerSpawns.length,
          brain_metered_events: tree.brain.meteredCount
        },
        is_completed: state?.status === "completed",
        is_truncated: false,
        error: null
      },
      cost: {
        ...EMPTY_COST,
        usd: src.limits.spendUsd !== null ? null : typeof stateResult.spentUsd === "number" ? stateResult.spentUsd : tree.brain.usd,
        tokens_in: tree.brain.tokensIn,
        tokens_out: tree.brain.tokensOut,
        cache_read: tree.brain.hasCache ? tree.brain.cacheRead : null,
        cache_write: tree.brain.hasCache ? tree.brain.cacheWrite : null,
        wall_s: wallMs === null ? null : wallMs / 1e3
      },
      artifacts: {
        patch_path: typeof result?.patchPath === "string" ? result.patchPath : null,
        run_dir: src.supRunDir,
        transcript_ref: src.rootTranscriptRef !== void 0 ? src.rootTranscriptRef : src.supRunDir === null ? null : `${src.supRunDir}/journal.jsonl`
      },
      provenance: {
        captured_at: capturedAt,
        capture: "backfill",
        gap: "supervision journal carries structure and spend, not the brain transcript"
      }
    });
  } else {
    gaps.push("tree.root: no parentless `spawned` event in the journal");
  }
  const closeById = new Map(tree.closes.map((c) => [c.id, c]));
  const sourceByLabel = new Map((src.workers ?? []).map((w) => [w.label, w]));
  for (const spawn of tree.workerSpawns) {
    const close = closeById.get(spawn.id) ?? null;
    const facts = tree.workerLogs.get(spawn.label) ?? null;
    const workerSource = sourceByLabel.get(spawn.label) ?? null;
    const wallMs = facts?.started != null && facts.finishedAt != null ? facts.finishedAt - facts.started : null;
    const reward = facts?.passed === null || facts === null ? null : facts.passed ? 1 : 0;
    if (reward === null) {
      gaps.push(`worker ${spawn.label}: no verify verdict (worker logs absent or unfinished)`);
    }
    nodes.push({
      ...base,
      rollout_id: spawn.id,
      parent_rollout_id: spawn.parent,
      role: "worker",
      policy: {
        harness: opts.workerHarness ?? null,
        harness_version: null,
        model: opts.workerModel ?? null,
        provider: null,
        profile_commit: null,
        sampling: null
      },
      outcome: {
        reward,
        reward_source: reward === null ? null : "worker-self-verify",
        verdict: close === null ? null : { kind: close.kind, status: close.status, verdict: close.verdict },
        metrics: {
          label: spawn.label,
          spawned_at: spawn.at,
          settled_at: close?.at ?? null,
          started_at: facts?.started ?? null,
          finished_at: facts?.finishedAt ?? null,
          wall_ms: wallMs,
          patch_bytes: facts?.finishedPatchBytes ?? null,
          evidence_bytes: facts?.evidenceBytes ?? null,
          steers_queued: facts?.steersQueued ?? null,
          steers_delivered: facts?.steersDelivered ?? null,
          questions: facts?.questions ?? null
        },
        is_completed: close?.kind === "settled",
        is_truncated: close?.kind === "cancelled",
        error: close?.kind === "cancelled" ? close.verdict ?? "cancelled" : null
      },
      // `close.spend` is only a measurement when the close event carried one;
      // a store that never priced this worker must leave null, not 0.
      cost: {
        ...EMPTY_COST,
        usd: src.limits.spendUsd !== null || !close?.hasSpend ? null : close.spend.usd,
        tokens_in: workerSource?.tokensIn ?? (close?.hasSpend ? close.spend.tokens.input : null),
        tokens_out: workerSource?.tokensOut ?? (close?.hasSpend ? close.spend.tokens.output : null),
        // Mirror the tokens_in/out journal fallback so a loops-shaped store whose
        // `settled` spend carries cache counters is not reported as null cache
        // beside real tokens. Gate on `hasCache` — a spend object without cache
        // counters must stay null, not a fabricated 0.
        cache_read: workerSource?.cacheRead ?? (close?.hasSpend && close.spend.tokens.hasCache ? close.spend.tokens.cacheRead : null),
        cache_write: workerSource?.cacheWrite ?? (close?.hasSpend && close.spend.tokens.hasCache ? close.spend.tokens.cacheWrite : null),
        wall_s: wallMs === null ? null : wallMs / 1e3
      },
      // A reader that knows where its worker artifacts live says so; only the
      // loops layout is derivable from `supRunDir`, so guessing it for another
      // store would mint rows pointing at paths that never existed.
      artifacts: {
        patch_path: workerSource?.patchPath !== void 0 ? workerSource.patchPath : src.supRunDir === null ? null : `${src.supRunDir}/workers/${spawn.label}.patch`,
        run_dir: src.supRunDir,
        transcript_ref: workerSource?.transcriptRef !== void 0 ? workerSource.transcriptRef : src.supRunDir === null ? null : `${src.supRunDir}/workers/${spawn.label}.ndjson`
      },
      provenance: {
        captured_at: capturedAt,
        capture: "backfill",
        gap: workerSource?.transcriptRef == null ? "worker transcript lives in the harness session store \u2014 hydrate via src/rollout/readers" : "worker transcript recorded by the harness; messages not inlined into this row"
      }
    });
  }
  const invalid = nodes.filter((n) => !isRolloutLine(n));
  if (invalid.length > 0) {
    gaps.push(`${invalid.length} node(s) failed tangle.rollout.v1 validation`);
  }
  return { rootId, nodes, gaps };
}

export {
  unavailable,
  isUnavailable,
  showMeasured,
  NO_SOURCE_LIMITS,
  SUPERVISOR_RUN_SCHEMA,
  SUPERVISOR_RUN_ROLLUP_SCHEMA,
  parseSupervisorTree,
  analyzeSupervisorRunSources,
  parsePatch,
  rollupSupervisorRuns,
  DEFAULT_SPAWN_TOOLS,
  DEFAULT_STEER_TOOLS,
  DEFAULT_CANCEL_TOOLS,
  readClaudeCodeSupervisorRun,
  claudeCodeSupervisorRunReader,
  renderSupervisorRunHeadline,
  renderSupervisorRunMarkdown,
  renderSupervisorRollupMarkdown,
  findSupervisorRunDirIn,
  readLoopsSupervisorRun,
  loopsSupervisorRunReader,
  analyzeSupervisorRun,
  writeSupervisorRunReport,
  supervisorReportStem,
  writeSupervisorRunReportSafe,
  reportSupervisorRound,
  findSupervisorRunDirs,
  supervisorRunRolloutLines
};
//# sourceMappingURL=chunk-LKKT3IVV.js.map