import { spawn, execFileSync } from "node:child_process";import fs from "node:fs";import os from "node:os";import path from "node:path"; const repoRoot = path.resolve(import.meta.dirname, "..");const marker = "<!-- desktop-perf-trace-summary -->";const defaultSeedRelativePath = "apps/desktop/scripts/perf-seed.json";const defaultPerfProjects = [ { id: "perf-project-1", cwd: "/tmp/perf/codething-mvp", name: "codething-mvp", }, { id: "perf-project-2", cwd: "/tmp/perf/contracts-bench", name: "contracts-bench", },]; function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms));} function parseArgs(argv) { let postPr = false; let seedPath = null; for (let index = 2; index < argv.length; index += 1) { const arg = argv[index]; if (arg === "--post-pr") { postPr = true; continue; } if (arg === "--seed") { const value = argv[index + 1]; if (!value || value.startsWith("--")) { throw new Error("--seed requires a file path"); } seedPath = value; index += 1; continue; } if (arg.startsWith("--seed=")) { const value = arg.slice("--seed=".length).trim(); if (value.length === 0) { throw new Error("--seed= requires a non-empty path"); } seedPath = value; continue; } throw new Error(`Unknown argument: ${arg}`); } return { postPr, seedPath, };} function toMs(us) { return us / 1000;} function round(n, digits = 3) { return Number(n.toFixed(digits));} function mb(bytes) { return bytes / (1024 * 1024);} function parseNumericEnv({ name, value, predicate, expectation, fallback }) { if (typeof value !== "string") { return null; } const raw = value.trim(); if (raw.length === 0) { console.warn( `[desktop-perf] invalid ${name}="${value}" (expected ${expectation}); using ${fallback}`, ); return null; } const parsed = Number(raw); if (Number.isFinite(parsed) && predicate(parsed)) { return { parsed, raw, }; } console.warn( `[desktop-perf] invalid ${name}="${value}" (expected ${expectation}); using ${fallback}`, ); return null;} function resolveNonNegativeNumberEnv({ name, value, fallback }) { const resolved = parseNumericEnv({ name, value, predicate: (parsed) => parsed >= 0, expectation: "non-negative number", fallback, }); return resolved?.parsed ?? fallback;} function resolveNonNegativeIntegerEnv({ name, value, fallback }) { const resolved = parseNumericEnv({ name, value, predicate: (parsed) => parsed >= 0, expectation: "non-negative number", fallback, }); if (!resolved) { return fallback; } const normalized = Math.trunc(resolved.parsed); if (normalized !== resolved.parsed) { console.warn( `[desktop-perf] non-integer ${name}="${resolved.raw}" truncated to ${normalized} for consistency`, ); } return normalized;} function resolvePositiveIntegerEnv({ name, value, fallback }) { const resolved = parseNumericEnv({ name, value, predicate: (parsed) => parsed > 0, expectation: "positive number", fallback, }); if (!resolved) { return fallback; } const normalized = Math.trunc(resolved.parsed); if (normalized !== resolved.parsed) { console.warn( `[desktop-perf] non-integer ${name}="${resolved.raw}" truncated to ${normalized} for consistency`, ); } return normalized;} function summarizeTrace(tracePath) { const payload = JSON.parse(fs.readFileSync(tracePath, "utf8")); const events = payload.traceEvents; const durationByName = new Map(); const dispatchRows = []; const functionRows = []; const userTiming = new Map(); const updateCounters = []; for (const event of events) { if (event.name === "UpdateCounters" && event.args?.data) { const heap = event.args.data.jsHeapSizeUsed; if (typeof heap === "number") { updateCounters.push(heap); } } if (event.cat === "blink.user_timing" && typeof event.name === "string") { userTiming.set(event.name, (userTiming.get(event.name) ?? 0) + 1); } if (event.ph !== "X" || typeof event.dur !== "number" || typeof event.name !== "string") { continue; } const byName = durationByName.get(event.name) ?? { count: 0, dur: 0, max: 0 }; byName.count += 1; byName.dur += event.dur; byName.max = Math.max(byName.max, event.dur); durationByName.set(event.name, byName); if (event.name === "EventDispatch") { const type = event.args?.data?.type ?? ""; dispatchRows.push({ type, dur: event.dur }); } if (event.name === "FunctionCall") { const functionName = event.args?.data?.functionName ?? "(unknown)"; functionRows.push({ functionName, dur: event.dur }); } } const aggregateDispatchType = (type) => { const rows = dispatchRows.filter((row) => row.type === type); if (rows.length === 0) { return { count: 0, totalMs: 0, avgMs: 0, maxMs: 0, }; } const totalDur = rows.reduce((sum, row) => sum + row.dur, 0); const maxDur = rows.reduce((max, row) => Math.max(max, row.dur), 0); return { count: rows.length, totalMs: round(toMs(totalDur)), avgMs: round(toMs(totalDur / rows.length)), maxMs: round(toMs(maxDur)), }; }; const aggregateFunction = (name) => { const rows = functionRows.filter((row) => row.functionName === name); if (rows.length === 0) { return { count: 0, totalMs: 0, avgMs: 0, maxMs: 0, }; } const totalDur = rows.reduce((sum, row) => sum + row.dur, 0); const maxDur = rows.reduce((max, row) => Math.max(max, row.dur), 0); return { count: rows.length, totalMs: round(toMs(totalDur)), avgMs: round(toMs(totalDur / rows.length)), maxMs: round(toMs(maxDur)), }; }; const topUserTiming = [...userTiming.entries()] .toSorted((a, b) => b[1] - a[1]) .slice(0, 10) .map(([name, count]) => ({ name, count })); const topDurationEvents = [...durationByName.entries()] .map(([name, value]) => ({ name, count: value.count, totalMs: round(toMs(value.dur), 2), avgMs: round(toMs(value.dur / value.count)), maxMs: round(toMs(value.max)), })) .toSorted((a, b) => b.totalMs - a.totalMs) .slice(0, 10); const heap = (() => { if (updateCounters.length === 0) return null; const first = updateCounters[0]; const last = updateCounters[updateCounters.length - 1]; const min = Math.min(...updateCounters); const max = Math.max(...updateCounters); return { firstMb: round(mb(first), 1), lastMb: round(mb(last), 1), minMb: round(mb(min), 1), maxMb: round(mb(max), 1), deltaMb: round(mb(last - first), 1), }; })(); const longDispatchCount = dispatchRows.filter((row) => row.dur >= 50_000).length; return { keypress: aggregateDispatchType("keypress"), textInput: aggregateDispatchType("textInput"), input: aggregateDispatchType("input"), keydown: aggregateDispatchType("keydown"), dispatchDiscreteEvent: aggregateFunction("dispatchDiscreteEvent"), performWorkUntilDeadline: aggregateFunction("performWorkUntilDeadline"), longDispatchCount, heap, topUserTiming, topDurationEvents, };} const pad = (value, width) => String(value).padEnd(width, " "); function evaluateThresholds(summary, thresholds) { const checks = [ { label: "keypress avg", actual: summary.keypress.avgMs, threshold: thresholds.maxKeypressAvgMs, ok: summary.keypress.avgMs <= thresholds.maxKeypressAvgMs, }, { label: "keypress max", actual: summary.keypress.maxMs, threshold: thresholds.maxKeypressMaxMs, ok: summary.keypress.maxMs <= thresholds.maxKeypressMaxMs, }, { label: "long EventDispatch spikes", actual: summary.longDispatchCount, threshold: thresholds.maxLongDispatchCount, ok: summary.longDispatchCount <= thresholds.maxLongDispatchCount, }, ]; const failures = checks .filter((check) => !check.ok) .map((check) => `${check.label} ${check.actual} exceeds ${check.threshold}`); return { checks, failures, passed: failures.length === 0, };} function createMarkdownSummary({ tracePath, donePayload, summary, thresholds, thresholdCheck }) { const THREAD_COL_WIDTH = 8; const TITLE_COL_WIDTH = 15; const largeThreadRenderStats = Array.isArray(donePayload.interactions?.largeThreadRenderStats) ? donePayload.interactions.largeThreadRenderStats : []; const formatThreadRenderRow = (stat) => { const threadShort = typeof stat.threadId === "string" ? stat.threadId.slice(0, THREAD_COL_WIDTH) : "n/a"; const titleShort = typeof stat.threadTitleShort === "string" ? stat.threadTitleShort : typeof stat.threadId === "string" ? stat.threadId.slice(0, 15) : "n/a"; const firstRenderMs = typeof stat.firstRenderMs === "number" ? stat.firstRenderMs : typeof stat.renderMs === "number" ? stat.renderMs : "n/a"; const followUpRenderMs = typeof stat.followUpRenderMs === "number" ? stat.followUpRenderMs : "n/a"; const followUpMinMs = typeof stat.followUpMinMs === "number" ? stat.followUpMinMs : "n/a"; const followUpMaxMs = typeof stat.followUpMaxMs === "number" ? stat.followUpMaxMs : "n/a"; const followUpSampleCount = typeof stat.followUpSampleCount === "number" ? stat.followUpSampleCount : "n/a"; const deltaMs = typeof stat.deltaMs === "number" ? stat.deltaMs : "n/a"; const deltaPct = typeof stat.deltaPct === "number" ? stat.deltaPct : "n/a"; const followUpRange = typeof followUpMinMs === "number" && typeof followUpMaxMs === "number" ? `${followUpMinMs}-${followUpMaxMs} (${followUpSampleCount}x)` : "n/a"; return `| ${pad(threadShort, THREAD_COL_WIDTH)} | ${pad(titleShort, TITLE_COL_WIDTH)} | ${stat.messageCount} | ${firstRenderMs} | ${followUpRenderMs} | ${followUpRange} | ${deltaMs} | ${deltaPct}% |`; }; const benchmarkThreadIds = Array.isArray(donePayload.interactions?.benchmarkThreadIds) ? donePayload.interactions.benchmarkThreadIds : []; const seedSource = donePayload.seed?.source === "file" ? `file (\`${donePayload.seed?.path ?? "unknown"}\`)` : (donePayload.seed?.source ?? "generated"); const topDurationHead = summary.topDurationEvents.slice(0, 3); const topDurationSummary = topDurationHead.length === 0 ? "none" : topDurationHead.map((entry) => `${entry.name} (${entry.totalMs}ms total)`).join(", "); const actionLines = thresholdCheck.passed ? [ "- Action: no threshold regressions detected in this run.", "- Follow-up: keep watching top duration events for drift in future traces.", ] : [ "- Action: threshold regression detected; profile and optimize the failing path(s) before merge.", ...thresholdCheck.failures.map((failure) => `- Failing metric: ${failure}`), ]; const lines = [ marker, "## Desktop Dev Perf Trace", "", `- Status: ${thresholdCheck.passed ? "PASS" : "FAIL"}`, `- Thresholds: keypress avg ${summary.keypress.avgMs}/${thresholds.maxKeypressAvgMs}ms, keypress max ${summary.keypress.maxMs}/${thresholds.maxKeypressMaxMs}ms, long dispatch spikes ${summary.longDispatchCount}/${thresholds.maxLongDispatchCount}`, `- Coverage: seed=${seedSource}; projects=${donePayload.seed?.projectCount ?? "n/a"}; threads=${donePayload.seed?.threadCount ?? "n/a"}; benchmark threads exercised=${benchmarkThreadIds.length}`, `- Interaction volume: thread clicks=${donePayload.interactions?.threadClicks ?? "n/a"}, typed chars=${donePayload.interactions?.typedChars ?? "n/a"}`, `- Top hotspots: ${topDurationSummary}`, "", ...actionLines, "", "<details>", "<summary>Detailed trace metrics and diagnostics</summary>", "", "### Run Metadata", "", `- Command: \`bun dev:desktop\``, `- Trace: \`${tracePath}\``, `- Started: ${donePayload.startedAt ?? "n/a"}`, `- Completed: ${donePayload.completedAt ?? "n/a"}`, `- Duration: ${donePayload.durationMs ?? "n/a"} ms`, "", "### Interaction Run", "", `- Thread clicks: ${donePayload.interactions?.threadClicks ?? "n/a"}`, `- Typed chars: ${donePayload.interactions?.typedChars ?? "n/a"}`, `- Benchmark thread ids exercised: ${benchmarkThreadIds.length > 0 ? benchmarkThreadIds.join(", ") : "none"}`, `- Model selected: ${donePayload.interactions?.selectedModel ?? "n/a"}`, `- Terminal opened by shortcut: ${donePayload.interactions?.terminal?.openedByShortcut ?? "n/a"}`, `- Terminal shortcut modifier: ${donePayload.interactions?.terminal?.modifierUsed ?? "n/a"}`, `- Terminal splits: ${donePayload.interactions?.terminal?.splitCount ?? "n/a"}`, `- Terminal command executed: ${donePayload.interactions?.terminal?.commandFileTouched ?? "n/a"}`, `- Terminal output observed: ${donePayload.interactions?.terminal?.commandEchoObserved ?? "n/a"}`, `- Terminal marker: ${donePayload.interactions?.terminal?.commandMarker ?? "n/a"}`, `- Terminal interactions enabled: ${donePayload.config?.runTerminalInteractions ?? "n/a"}`, `- Optional renderer interactions enabled: ${donePayload.config?.runOptionalRendererInteractions ?? "n/a"}`, `- Benchmark sweep enabled: ${donePayload.config?.runBenchmarkThreadSweep ?? "n/a"}`, `- Benchmark follow-up pass count: ${donePayload.config?.benchmarkFollowUpPassCount ?? "n/a"}`, "", "### Threshold Config", "", `- keypress avg max: ${thresholds.maxKeypressAvgMs}ms`, `- keypress max max: ${thresholds.maxKeypressMaxMs}ms`, `- long EventDispatch spike cap: ${thresholds.maxLongDispatchCount}`, "", "### Benchmark Thread Render", "", "| Thread | Title (15) | Messages | First Nav (ms) | Follow-up Median (ms) | Follow-up Range | Delta (ms) | Delta (%) |", "| --- | --- | ---: | ---: | ---: | --- | ---: | ---: |", ...(largeThreadRenderStats.length > 0 ? largeThreadRenderStats.map((stat) => formatThreadRenderRow(stat)) : ["| n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |"]), "", "### Input Event Metrics", "", "| Event | Count | Avg (ms) | Max (ms) | Total (ms) |", "| --- | ---: | ---: | ---: | ---: |", `| keypress | ${summary.keypress.count} | ${summary.keypress.avgMs} | ${summary.keypress.maxMs} | ${summary.keypress.totalMs} |`, `| textInput | ${summary.textInput.count} | ${summary.textInput.avgMs} | ${summary.textInput.maxMs} | ${summary.textInput.totalMs} |`, `| input | ${summary.input.count} | ${summary.input.avgMs} | ${summary.input.maxMs} | ${summary.input.totalMs} |`, `| keydown | ${summary.keydown.count} | ${summary.keydown.avgMs} | ${summary.keydown.maxMs} | ${summary.keydown.totalMs} |`, "", "### Scheduler/Event Hotspots", "", `- dispatchDiscreteEvent: ${summary.dispatchDiscreteEvent.totalMs}ms total (${summary.dispatchDiscreteEvent.count} calls)`, `- performWorkUntilDeadline: ${summary.performWorkUntilDeadline.totalMs}ms total (${summary.performWorkUntilDeadline.count} calls)`, `- EventDispatch spikes >= 50ms: ${summary.longDispatchCount}`, "", "### Threshold Check", "", ...thresholdCheck.checks.map( (check) => `- ${check.label} <= ${check.threshold}: ${check.ok ? "pass" : `fail (actual ${check.actual})`}`, ), "", ]; if (summary.heap) { lines.push("### Heap Counters", ""); lines.push( `- first=${summary.heap.firstMb}MB, last=${summary.heap.lastMb}MB, min=${summary.heap.minMb}MB, max=${summary.heap.maxMb}MB, delta=${summary.heap.deltaMb}MB`, "", ); } lines.push("### Top User Timing Marks", ""); for (const entry of summary.topUserTiming) { lines.push(`- ${entry.count}x ${entry.name}`); } lines.push("", "### Top Duration Events", ""); for (const entry of summary.topDurationEvents) { lines.push( `- ${entry.name}: total=${entry.totalMs}ms, avg=${entry.avgMs}ms, max=${entry.maxMs}ms, count=${entry.count}`, ); } lines.push("", "</details>", ""); return lines.join("\n");} async function waitForDoneFile(donePath, child, timeoutMs) { const startedAt = Date.now(); while (Date.now() - startedAt < timeoutMs) { if (fs.existsSync(donePath)) { return JSON.parse(fs.readFileSync(donePath, "utf8")); } if (child.exitCode !== null) { throw new Error(`desktop dev process exited early (code ${child.exitCode})`); } // oxlint-disable-next-line no-await-in-loop await sleep(500); } throw new Error(`Timed out waiting for done marker at ${donePath}`);} function tailLogText(logChunks, lineCount = 120) { const lines = logChunks.join("").split(/\r?\n/); return lines.slice(-lineCount).join("\n").trim();} function inferDesktopPerfTimeoutHint(logChunks) { const joined = logChunks.join(""); const lowered = joined.toLowerCase(); if (lowered.includes("waiting for bundles") && lowered.includes("outdated:")) { return "Desktop bundles were present but older than desktop source files; dev bundler did not refresh outputs in time."; } if (lowered.includes("waiting for bundles") && lowered.includes("stale:")) { return "Desktop bundles were detected as stale by startup freshness checks."; }Lines 1–500 of 887. Load more
import { spawn, execFileSync } from "node:child_process"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; const repoRoot = path.resolve(import.meta.dirname, ".."); const marker = "<!-- desktop-perf-trace-summary -->"; const defaultSeedRelativePath = "apps/desktop/scripts/perf-seed.json"; const defaultPerfProjects = [ { id: "perf-project-1", cwd: "/tmp/perf/codething-mvp", name: "codething-mvp", }, { id: "perf-project-2", cwd: "/tmp/perf/contracts-bench", name: "contracts-bench", }, ]; function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function parseArgs(argv) { let postPr = false; let seedPath = null; for (let index = 2; index < argv.length; index += 1) { const arg = argv[index]; if (arg === "--post-pr") { postPr = true; continue; } if (arg === "--seed") { const value = argv[index + 1]; if (!value || value.startsWith("--")) { throw new Error("--seed requires a file path"); } seedPath = value; index += 1; continue; } if (arg.startsWith("--seed=")) { const value = arg.slice("--seed=".length).trim(); if (value.length === 0) { throw new Error("--seed= requires a non-empty path"); } seedPath = value; continue; } throw new Error(`Unknown argument: ${arg}`); } return { postPr, seedPath, }; } function toMs(us) { return us / 1000; } function round(n, digits = 3) { return Number(n.toFixed(digits)); } function mb(bytes) { return bytes / (1024 * 1024); } function parseNumericEnv({ name, value, predicate, expectation, fallback }) { if (typeof value !== "string") { return null; } const raw = value.trim(); if (raw.length === 0) { console.warn( `[desktop-perf] invalid ${name}="${value}" (expected ${expectation}); using ${fallback}`, ); return null; } const parsed = Number(raw); if (Number.isFinite(parsed) && predicate(parsed)) { return { parsed, raw, }; } console.warn( `[desktop-perf] invalid ${name}="${value}" (expected ${expectation}); using ${fallback}`, ); return null; } function resolveNonNegativeNumberEnv({ name, value, fallback }) { const resolved = parseNumericEnv({ name, value, predicate: (parsed) => parsed >= 0, expectation: "non-negative number", fallback, }); return resolved?.parsed ?? fallback; } function resolveNonNegativeIntegerEnv({ name, value, fallback }) { const resolved = parseNumericEnv({ name, value, predicate: (parsed) => parsed >= 0, expectation: "non-negative number", fallback, }); if (!resolved) { return fallback; } const normalized = Math.trunc(resolved.parsed); if (normalized !== resolved.parsed) { console.warn( `[desktop-perf] non-integer ${name}="${resolved.raw}" truncated to ${normalized} for consistency`, ); } return normalized; } function resolvePositiveIntegerEnv({ name, value, fallback }) { const resolved = parseNumericEnv({ name, value, predicate: (parsed) => parsed > 0, expectation: "positive number", fallback, }); if (!resolved) { return fallback; } const normalized = Math.trunc(resolved.parsed); if (normalized !== resolved.parsed) { console.warn( `[desktop-perf] non-integer ${name}="${resolved.raw}" truncated to ${normalized} for consistency`, ); } return normalized; } function summarizeTrace(tracePath) { const payload = JSON.parse(fs.readFileSync(tracePath, "utf8")); const events = payload.traceEvents; const durationByName = new Map(); const dispatchRows = []; const functionRows = []; const userTiming = new Map(); const updateCounters = []; for (const event of events) { if (event.name === "UpdateCounters" && event.args?.data) { const heap = event.args.data.jsHeapSizeUsed; if (typeof heap === "number") { updateCounters.push(heap); } } if (event.cat === "blink.user_timing" && typeof event.name === "string") { userTiming.set(event.name, (userTiming.get(event.name) ?? 0) + 1); } if (event.ph !== "X" || typeof event.dur !== "number" || typeof event.name !== "string") { continue; } const byName = durationByName.get(event.name) ?? { count: 0, dur: 0, max: 0 }; byName.count += 1; byName.dur += event.dur; byName.max = Math.max(byName.max, event.dur); durationByName.set(event.name, byName); if (event.name === "EventDispatch") { const type = event.args?.data?.type ?? ""; dispatchRows.push({ type, dur: event.dur }); } if (event.name === "FunctionCall") { const functionName = event.args?.data?.functionName ?? "(unknown)"; functionRows.push({ functionName, dur: event.dur }); } } const aggregateDispatchType = (type) => { const rows = dispatchRows.filter((row) => row.type === type); if (rows.length === 0) { return { count: 0, totalMs: 0, avgMs: 0, maxMs: 0, }; } const totalDur = rows.reduce((sum, row) => sum + row.dur, 0); const maxDur = rows.reduce((max, row) => Math.max(max, row.dur), 0); return { count: rows.length, totalMs: round(toMs(totalDur)), avgMs: round(toMs(totalDur / rows.length)), maxMs: round(toMs(maxDur)), }; }; const aggregateFunction = (name) => { const rows = functionRows.filter((row) => row.functionName === name); if (rows.length === 0) { return { count: 0, totalMs: 0, avgMs: 0, maxMs: 0, }; } const totalDur = rows.reduce((sum, row) => sum + row.dur, 0); const maxDur = rows.reduce((max, row) => Math.max(max, row.dur), 0); return { count: rows.length, totalMs: round(toMs(totalDur)), avgMs: round(toMs(totalDur / rows.length)), maxMs: round(toMs(maxDur)), }; }; const topUserTiming = [...userTiming.entries()] .toSorted((a, b) => b[1] - a[1]) .slice(0, 10) .map(([name, count]) => ({ name, count })); const topDurationEvents = [...durationByName.entries()] .map(([name, value]) => ({ name, count: value.count, totalMs: round(toMs(value.dur), 2), avgMs: round(toMs(value.dur / value.count)), maxMs: round(toMs(value.max)), })) .toSorted((a, b) => b.totalMs - a.totalMs) .slice(0, 10); const heap = (() => { if (updateCounters.length === 0) return null; const first = updateCounters[0]; const last = updateCounters[updateCounters.length - 1]; const min = Math.min(...updateCounters); const max = Math.max(...updateCounters); return { firstMb: round(mb(first), 1), lastMb: round(mb(last), 1), minMb: round(mb(min), 1), maxMb: round(mb(max), 1), deltaMb: round(mb(last - first), 1), }; })(); const longDispatchCount = dispatchRows.filter((row) => row.dur >= 50_000).length; return { keypress: aggregateDispatchType("keypress"), textInput: aggregateDispatchType("textInput"), input: aggregateDispatchType("input"), keydown: aggregateDispatchType("keydown"), dispatchDiscreteEvent: aggregateFunction("dispatchDiscreteEvent"), performWorkUntilDeadline: aggregateFunction("performWorkUntilDeadline"), longDispatchCount, heap, topUserTiming, topDurationEvents, }; } const pad = (value, width) => String(value).padEnd(width, " "); function evaluateThresholds(summary, thresholds) { const checks = [ { label: "keypress avg", actual: summary.keypress.avgMs, threshold: thresholds.maxKeypressAvgMs, ok: summary.keypress.avgMs <= thresholds.maxKeypressAvgMs, }, { label: "keypress max", actual: summary.keypress.maxMs, threshold: thresholds.maxKeypressMaxMs, ok: summary.keypress.maxMs <= thresholds.maxKeypressMaxMs, }, { label: "long EventDispatch spikes", actual: summary.longDispatchCount, threshold: thresholds.maxLongDispatchCount, ok: summary.longDispatchCount <= thresholds.maxLongDispatchCount, }, ]; const failures = checks .filter((check) => !check.ok) .map((check) => `${check.label} ${check.actual} exceeds ${check.threshold}`); return { checks, failures, passed: failures.length === 0, }; } function createMarkdownSummary({ tracePath, donePayload, summary, thresholds, thresholdCheck }) { const THREAD_COL_WIDTH = 8; const TITLE_COL_WIDTH = 15; const largeThreadRenderStats = Array.isArray(donePayload.interactions?.largeThreadRenderStats) ? donePayload.interactions.largeThreadRenderStats : []; const formatThreadRenderRow = (stat) => { const threadShort = typeof stat.threadId === "string" ? stat.threadId.slice(0, THREAD_COL_WIDTH) : "n/a"; const titleShort = typeof stat.threadTitleShort === "string" ? stat.threadTitleShort : typeof stat.threadId === "string" ? stat.threadId.slice(0, 15) : "n/a"; const firstRenderMs = typeof stat.firstRenderMs === "number" ? stat.firstRenderMs : typeof stat.renderMs === "number" ? stat.renderMs : "n/a"; const followUpRenderMs = typeof stat.followUpRenderMs === "number" ? stat.followUpRenderMs : "n/a"; const followUpMinMs = typeof stat.followUpMinMs === "number" ? stat.followUpMinMs : "n/a"; const followUpMaxMs = typeof stat.followUpMaxMs === "number" ? stat.followUpMaxMs : "n/a"; const followUpSampleCount = typeof stat.followUpSampleCount === "number" ? stat.followUpSampleCount : "n/a"; const deltaMs = typeof stat.deltaMs === "number" ? stat.deltaMs : "n/a"; const deltaPct = typeof stat.deltaPct === "number" ? stat.deltaPct : "n/a"; const followUpRange = typeof followUpMinMs === "number" && typeof followUpMaxMs === "number" ? `${followUpMinMs}-${followUpMaxMs} (${followUpSampleCount}x)` : "n/a"; return `| ${pad(threadShort, THREAD_COL_WIDTH)} | ${pad(titleShort, TITLE_COL_WIDTH)} | ${stat.messageCount} | ${firstRenderMs} | ${followUpRenderMs} | ${followUpRange} | ${deltaMs} | ${deltaPct}% |`; }; const benchmarkThreadIds = Array.isArray(donePayload.interactions?.benchmarkThreadIds) ? donePayload.interactions.benchmarkThreadIds : []; const seedSource = donePayload.seed?.source === "file" ? `file (\`${donePayload.seed?.path ?? "unknown"}\`)` : (donePayload.seed?.source ?? "generated"); const topDurationHead = summary.topDurationEvents.slice(0, 3); const topDurationSummary = topDurationHead.length === 0 ? "none" : topDurationHead.map((entry) => `${entry.name} (${entry.totalMs}ms total)`).join(", "); const actionLines = thresholdCheck.passed ? [ "- Action: no threshold regressions detected in this run.", "- Follow-up: keep watching top duration events for drift in future traces.", ] : [ "- Action: threshold regression detected; profile and optimize the failing path(s) before merge.", ...thresholdCheck.failures.map((failure) => `- Failing metric: ${failure}`), ]; const lines = [ marker, "## Desktop Dev Perf Trace", "", `- Status: ${thresholdCheck.passed ? "PASS" : "FAIL"}`, `- Thresholds: keypress avg ${summary.keypress.avgMs}/${thresholds.maxKeypressAvgMs}ms, keypress max ${summary.keypress.maxMs}/${thresholds.maxKeypressMaxMs}ms, long dispatch spikes ${summary.longDispatchCount}/${thresholds.maxLongDispatchCount}`, `- Coverage: seed=${seedSource}; projects=${donePayload.seed?.projectCount ?? "n/a"}; threads=${donePayload.seed?.threadCount ?? "n/a"}; benchmark threads exercised=${benchmarkThreadIds.length}`, `- Interaction volume: thread clicks=${donePayload.interactions?.threadClicks ?? "n/a"}, typed chars=${donePayload.interactions?.typedChars ?? "n/a"}`, `- Top hotspots: ${topDurationSummary}`, "", ...actionLines, "", "<details>", "<summary>Detailed trace metrics and diagnostics</summary>", "", "### Run Metadata", "", `- Command: \`bun dev:desktop\``, `- Trace: \`${tracePath}\``, `- Started: ${donePayload.startedAt ?? "n/a"}`, `- Completed: ${donePayload.completedAt ?? "n/a"}`, `- Duration: ${donePayload.durationMs ?? "n/a"} ms`, "", "### Interaction Run", "", `- Thread clicks: ${donePayload.interactions?.threadClicks ?? "n/a"}`, `- Typed chars: ${donePayload.interactions?.typedChars ?? "n/a"}`, `- Benchmark thread ids exercised: ${benchmarkThreadIds.length > 0 ? benchmarkThreadIds.join(", ") : "none"}`, `- Model selected: ${donePayload.interactions?.selectedModel ?? "n/a"}`, `- Terminal opened by shortcut: ${donePayload.interactions?.terminal?.openedByShortcut ?? "n/a"}`, `- Terminal shortcut modifier: ${donePayload.interactions?.terminal?.modifierUsed ?? "n/a"}`, `- Terminal splits: ${donePayload.interactions?.terminal?.splitCount ?? "n/a"}`, `- Terminal command executed: ${donePayload.interactions?.terminal?.commandFileTouched ?? "n/a"}`, `- Terminal output observed: ${donePayload.interactions?.terminal?.commandEchoObserved ?? "n/a"}`, `- Terminal marker: ${donePayload.interactions?.terminal?.commandMarker ?? "n/a"}`, `- Terminal interactions enabled: ${donePayload.config?.runTerminalInteractions ?? "n/a"}`, `- Optional renderer interactions enabled: ${donePayload.config?.runOptionalRendererInteractions ?? "n/a"}`, `- Benchmark sweep enabled: ${donePayload.config?.runBenchmarkThreadSweep ?? "n/a"}`, `- Benchmark follow-up pass count: ${donePayload.config?.benchmarkFollowUpPassCount ?? "n/a"}`, "", "### Threshold Config", "", `- keypress avg max: ${thresholds.maxKeypressAvgMs}ms`, `- keypress max max: ${thresholds.maxKeypressMaxMs}ms`, `- long EventDispatch spike cap: ${thresholds.maxLongDispatchCount}`, "", "### Benchmark Thread Render", "", "| Thread | Title (15) | Messages | First Nav (ms) | Follow-up Median (ms) | Follow-up Range | Delta (ms) | Delta (%) |", "| --- | --- | ---: | ---: | ---: | --- | ---: | ---: |", ...(largeThreadRenderStats.length > 0 ? largeThreadRenderStats.map((stat) => formatThreadRenderRow(stat)) : ["| n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |"]), "", "### Input Event Metrics", "", "| Event | Count | Avg (ms) | Max (ms) | Total (ms) |", "| --- | ---: | ---: | ---: | ---: |", `| keypress | ${summary.keypress.count} | ${summary.keypress.avgMs} | ${summary.keypress.maxMs} | ${summary.keypress.totalMs} |`, `| textInput | ${summary.textInput.count} | ${summary.textInput.avgMs} | ${summary.textInput.maxMs} | ${summary.textInput.totalMs} |`, `| input | ${summary.input.count} | ${summary.input.avgMs} | ${summary.input.maxMs} | ${summary.input.totalMs} |`, `| keydown | ${summary.keydown.count} | ${summary.keydown.avgMs} | ${summary.keydown.maxMs} | ${summary.keydown.totalMs} |`, "", "### Scheduler/Event Hotspots", "", `- dispatchDiscreteEvent: ${summary.dispatchDiscreteEvent.totalMs}ms total (${summary.dispatchDiscreteEvent.count} calls)`, `- performWorkUntilDeadline: ${summary.performWorkUntilDeadline.totalMs}ms total (${summary.performWorkUntilDeadline.count} calls)`, `- EventDispatch spikes >= 50ms: ${summary.longDispatchCount}`, "", "### Threshold Check", "", ...thresholdCheck.checks.map( (check) => `- ${check.label} <= ${check.threshold}: ${check.ok ? "pass" : `fail (actual ${check.actual})`}`, ), "", ]; if (summary.heap) { lines.push("### Heap Counters", ""); lines.push( `- first=${summary.heap.firstMb}MB, last=${summary.heap.lastMb}MB, min=${summary.heap.minMb}MB, max=${summary.heap.maxMb}MB, delta=${summary.heap.deltaMb}MB`, "", ); } lines.push("### Top User Timing Marks", ""); for (const entry of summary.topUserTiming) { lines.push(`- ${entry.count}x ${entry.name}`); } lines.push("", "### Top Duration Events", ""); for (const entry of summary.topDurationEvents) { lines.push( `- ${entry.name}: total=${entry.totalMs}ms, avg=${entry.avgMs}ms, max=${entry.maxMs}ms, count=${entry.count}`, ); } lines.push("", "</details>", ""); return lines.join("\n"); } async function waitForDoneFile(donePath, child, timeoutMs) { const startedAt = Date.now(); while (Date.now() - startedAt < timeoutMs) { if (fs.existsSync(donePath)) { return JSON.parse(fs.readFileSync(donePath, "utf8")); } if (child.exitCode !== null) { throw new Error(`desktop dev process exited early (code ${child.exitCode})`); } // oxlint-disable-next-line no-await-in-loop await sleep(500); } throw new Error(`Timed out waiting for done marker at ${donePath}`); } function tailLogText(logChunks, lineCount = 120) { const lines = logChunks.join("").split(/\r?\n/); return lines.slice(-lineCount).join("\n").trim(); } function inferDesktopPerfTimeoutHint(logChunks) { const joined = logChunks.join(""); const lowered = joined.toLowerCase(); if (lowered.includes("waiting for bundles") && lowered.includes("outdated:")) { return "Desktop bundles were present but older than desktop source files; dev bundler did not refresh outputs in time."; } if (lowered.includes("waiting for bundles") && lowered.includes("stale:")) { return "Desktop bundles were detected as stale by startup freshness checks."; }