mergeSummary
tcm merge's report, briefly, for an agent that made the change it lands: what it said (conflicts, what was
merged as text, what no longer typechecks), the definitions edited or conflicted by name (without their code), and
how many of each other kind (re-hashed dependents, added, …).
export function mergeSummary(out: string): string { const said: string[] = []; let section: { label: string; names: string[] } | undefined; const sections: { label: string; names: string[] }[] = []; for (const line of out.split("\n")) { if (/^ {2}\S/.test(line)) sections.push((section = { label: line.trim(), names: [] })); else if (section && /^ {4}\S/.test(line)) section.names.push(line.trim().split(/\s+/)[1] ?? ""); else if (section && /^ {5,}/.test(line)) continue; else if (line.trim()) said.push(line); } const listed = (names: string[]) => names.length > 8 ? `${names.slice(0, 8).join(", ")}, and ${names.length - 8} more` : names.join(", "); return [ ...said, // (a line of its own, not a section: "no changes", "merged cleanly") ...sections.map((s) => !s.names.length ? ` ${s.label}` : s.label === "edited" || s.label === "conflicted" ? ` ${s.label}: ${listed(s.names)}` : ` ${s.label}: ${s.names.length}`, ), ].join("\n"); }