#!/usr/bin/env node /** * Fully automated idle CPU/memory capture for OpenChamber. * * Unlike `profile:browser`, this command needs no human in the loop: it loads * the app, lets it settle, then records a window during which no input is * delivered. Everything it reports is therefore work the app performs while the * user is doing nothing, which is the regression class users notice as fan * noise, battery drain, and a permanently busy tab. * * Reported dimensions (per second of the idle window): * - main-thread busy time, script time, style recalculation, layout; * - style recalculation and layout counts; * - DOM node, document, frame, and JS event listener growth; * - JS heap trajectory (start/end/max plus linear growth rate); * - CPU sampling profile with self time per function; * - scheduled-work attribution per timer/animation-frame/observer call site. * * Runs are directly comparable: `--baseline ` prints a per-metric * delta table and exits non-zero when a budget in `--budget-*` is exceeded, so * the same command works as an investigation tool and as a regression gate. */ import { mkdir, readFile, writeFile } from "node:fs/promises" import { homedir } from "node:os" import { join, resolve } from "node:path" import process from "node:process" import { CdpClient, createPageTarget, evaluateValue, launchChrome, reservePort, resolveChrome, wait } from "./perf/cdp.mjs" import { buildIdleProbeSource, IDLE_PROBE_GLOBAL } from "./perf/idle-probe.mjs" import { summarizeCpuProfile } from "./perf/cpu-profile.mjs" import { growthPerSecond, metricMap, round } from "./perf/metrics.mjs" const HELP = `Usage: bun run profile:idle -- [options] Records what OpenChamber does while nobody is interacting with it. Options: --url OpenChamber URL (default: http://localhost:3000) --session Open this session before recording (deep link) --tab Open this main tab before recording --then-tab After settling, navigate to this tab without a reload, then record. Use it to measure what a surface keeps doing after the user leaves it. --panel Open the context panel on this surface before recording (chat, preview, terminal, git, pr, notes, file, diff, plan, context, browser, walkthrough). Repeatable; the first entry becomes the active tab. --duration Idle recording window (default: 30) --settle Wait after load before recording (default: 15) --output Artifact directory (default: artifacts/idle-profile-