test(cmux-next): --record-launch records every launch window from its first composited frame
A DEBUG-only recorder for launch frames. It's the instrument for Leo's never-blank first launch frame item: the first frame paints the snapshot, then goes live, with no blank, white or black frame between.
debug.window_record can't see a launch, because it needs the control socket and that comes up only after launch settles (AppDelegate, launchSettle.settled(within: 4s)). With --record-launch DIR [--record-launch-seconds S]:
- When it starts:
DebugTimings.installstarts an app-clock frame client before the first window exists. - What it records: once a display frame, any main window (
ShellWindow) it hasn't seen gets its own recorder. That recorder takes a frame at once, then one per display frame of that window, from the window's first composited frame. That covers the launch window and each restored window, even those that wait off screen for their content. - What it writes:
DIR/window-N/holds JPEG frames andframes.json. The JSON hastimes,luminanceandpeakper frame, asdebug.window_recordwrites them, plusprocessMs, the frame's time since the process started. That's the launch marks' clock. - Limits: each window records for S seconds (6 by default, 12 at most). The app looks for new windows for 30 s.
- Code: the hook lives in
DebugWindowRecordandDebugTimings. It doesn't touchWindowController,WindowManagerorAppDelegate, which are all over the god-file limit.
DebugLaunchRecordTests covers the arguments. Next, a DEV build of this head records a cold launch and a launch with restored windows on a capture mini. Every blank or unpainted frame found gets its own failing test and fix PR, and if the launch is clean, a guard follows.
No capture: DEBUG-only instrumentation, nothing visible changes.
Capture
A real recording with this probe: a DEV build of this head on capture slot cua-5, 60 fps. Times are ms since process start. Top row: a cold launch. Bottom row: a relaunch that restores two windows.

What it found (fixes follow in their own PRs):
- Restore: frame 0, at 1831 ms, is solid white.
- Restore: the sidebar is gone from 2193 to 2339 ms.
- Restore: "Conversations need a newer cmux daemon." shows from 2012 to 2339 ms.
- Cold: the layout settles in pieces from 3256 to about 5000 ms.
Agent session: huge-blue
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Adds --record-launch DIR [--record-launch-seconds S], a DEBUG-only recorder that captures every launch window from its first composited frame. debug.window_record can't see a launch because it needs the control socket, which comes up only after launch settles.
- Starts from
DebugTimings.install, before the first window exists, and records eachShellWindowfrom its first captured frame intoDIR/window-N/. - Each frame's
frames.jsonincludesprocessMs, its time since process start, on the launch marks' clock. - Time zero is the first frame actually captured, so a window that shows before it can be captured doesn't start the clock early.
- Windows record for S seconds (6 by default, at most 12); a recording ends when its window closes, and the app keeps looking for new windows for 30 s.
- DEBUG-only: nothing changes without the flag; a plain
debug.window_recordkeeps its own clock behavior.