briefOutput
A command's output as a tool says it, briefly: a test run's passing tests as a list of names rather than a line
each (hundreds of them), so what failed, what ran, and the counts, are what an agent reads. The tests that ran are
named; the cached ones too when tests were named or something failed (else the summary counts them). A merge's
or revert's changes by name and count (mergeSummary: tcm diff has the code). Waiting for the machine's suite
slots, a section's last line of it, above its summary, unless the summary says how long it waited. Other commands'
as they are.
import { SLOT_WAIT_LINE } from "#codebase/tcmts/cli/budget"; import { liveArgv, mergeSummary } from "#codebase/tcmts/cli/mcp"; export function briefOutput(argv: string[], out: string): string { // (the command, as the codebase's own tcm runs it, `live`, or run in another directory) const own = liveArgv([]); if (own.every((a, i) => argv[i] === a)) return briefOutput(argv.slice(own.length), out); if (argv[0] === "-C") return briefOutput(argv.slice(2), out); if (argv[0] === "merge" || argv[0] === "revert") return mergeSummary(out); if (argv[0] !== "test") return out; // tests named on the command line (not a flag's value) const named = argv.slice(1).some((a, i, xs) => !a.startsWith("-") && xs[i - 1] !== "--bin"); // names under the namespace they share, so a list of end-to-end tests isn't mostly `tcmts.cli.test.e2e.` const listed = (label: string, paths: string[]) => { const shown = paths.slice(0, 40).map((p) => p.split(".")); let n = 0; while (shown.length > 1 && shown.every((s) => s.length > n + 1 && s[n] === shown[0][n])) n++; const more = paths.length > shown.length ? `, and ${paths.length - shown.length} more` : ""; const under = n ? ` under ${shown[0].slice(0, n).join(".")}` : ""; return `${label}${under}: ${shown.map((s) => s.slice(n).join(".")).join(", ")}${more}`; }; const lines: string[] = []; let ran: string[] = []; let cached: string[] = []; let failed = false; let wait: string | undefined; for (const l of out.split("\n")) { if (SLOT_WAIT_LINE.test(l)) { wait = l.trim(); continue; } const pass = /^\s*✓ (\S+)\s*(\(cached\))?/.exec(l); if (pass) { (pass[2] ? cached : ran).push(pass[1]); continue; } if (/^\s*✗ /.test(l)) failed = true; // a section's summary: its passing tests by name, above it if (/^(suites: )?\d+ passed, \d+ failed/.test(l)) { if (ran.length) lines.push(listed("ran", ran)); if (cached.length && (named || failed)) lines.push(listed("cached", cached)); if (wait && !/waiting for slots/.test(l)) lines.push(wait); wait = undefined; ran = []; cached = []; failed = false; } lines.push(l); } if (wait) lines.push(wait); return lines .join("\n") .replace(/\n{3,}/g, "\n\n") .trim(); }