The model (the host axis and the flavor axis, the master clock, the facade, the
rules and the layer that enforces each), the same questions answered for each
host, the decisions behind the design, and the checkpoints to run on a Windows
machine, including the installer.
`komorebi-recorder view <session>` opens a recording in a window: the video of
every display, a timeline with a lane for the bug regions, events, log errors,
the machine and the findings, and an inspector for the state at the playhead,
one event traced end to end, and komorebi's log. The window is untitled so
komorebi leaves it alone, and out of any recording being made. It is where a bug
is marked: the form takes the region from the selection or the playhead and asks
what went wrong and what was expected. It opens from the recorder window as
well.
komorebi for Windows hides a window by cloaking it in place, so its state cannot
show whether a window is really hidden. `record --probe-windows` follows each
window event with a read of the window's real state from Windows and, now and
then, asks komorebi whether it manages the window. The analysis compares the
two: a window komorebi shows that Windows hides, one it hides that Windows
shows, and a visible window it does not manage. macOS refuses the flag with a
message.
When and where on each display the picture changed, found by decoding the video,
and a contact sheet of frames with the times, events and bug region marked. A
display with no video for part of a range has a gap there instead of an invented
frame.
The brief starts from what the user marked as the bug, in their words, and ranks
the events most worth tracing first; findings an agent concludes are saved with
the evidence they cite, which must exist. The commands arrive: `state`, `diff`,
`events`, `window`, `trace`, `code`, `brief`, `overview`, `search`, `annotate`,
`annotations`, `guide` and `schema`, all with `--json`, and a search is bounded
by a budget.
One event end to end: what its handler logged, what other threads logged
meanwhile, and every change with who made it and how sure that is. The state,
the diff and the events are answered as plain values, an overview ranks what
stands out in a recording, and invariants flag states that are wrong: a window
in two containers, a window parked off screen on the workspace that is showing
(a rule that holds only where komorebi hides windows by moving them, so it is
skipped on Windows).
A komorebi `State` is read into monitors, workspaces and windows through each
flavor's rules, and what changed between two states is said in terms a person
would use. `at`, `range`, `summary` and `locate` ask what the recording holds
around a video time, and the other way round, with the text and JSON the later
commands share.
`doctor` says what the machine can do for a recording: which komorebi runs and
how it logs, whether the screen can be captured and played back, the displays
and their scale, and the host clock. Probes measure one thing: the clock across
a sleep, a short capture, a decode, whether komorebi would tile a window of
ours.
Reading the video back: AVFoundation on macOS, the Media Foundation source
reader on Windows, a clear error elsewhere. A request for the frames between two
times is answered with the frame that was on screen at the start, even when the
decoder had to seek to an earlier key frame. `selftest` records a rendered
on-screen clock and compares the clock the video shows with the time the session
predicts.
Run with no command, `komorebi-recorder` opens a small window with Record and
Stop. It is untitled and borderless because komorebi does not manage windows
without a title, so opening it does not move the layout under investigation, and
it keeps itself out of the video (by process name on macOS, with
`WDA_EXCLUDEFROMCAPTURE` on Windows). `komorebi-recorder-gui` is the same
program built for the GUI subsystem on Windows, so that a shortcut opens no
console; both are in the zips and the installer.
`komorebi-recorder record` starts every source in the order that makes the
non-video sources a superset of the video, stops them in reverse, and
checkpoints the manifest as it goes, so that a recorder that is killed leaves a
session `reindex` can recover. `--no-video` records everything but the screen,
and Ctrl-C or `--duration` stops and finalizes a recording. The format of
`annotations.jsonl`, the append-only file that bug regions, notes and findings
are written to, is defined here too. The command table arrives with it, with
`displays` and `reindex`, and with the text-and-JSON conventions the later
commands share.
`timeline.jsonl` is a merged, time-sorted index that points into the raw files
by byte range, so the raw files are never rewritten and the index can be rebuilt
at any time. It places komorebi's log, events, the OS trace and the recorder's
own incidents on one timeline, and answers what was around a video time and
where in the video a log line or event is. `frames` extracts PNG frames from the
recorded video with ffmpeg, which is never used to capture.
Docking, sleep and lock are where komorebi bugs show up, so the recording
carries on through them. On Windows a hidden window hears suspend, resume, the
lid, the displays and session lock as Windows delivers them; on a Mac a sleep is
found because the host clock pauses while the wall clock does not, and the lock
is polled on both hosts. A tracker turns these into reactions: a display that is
gone has its video finalized at once, one that returns starts a new segment, and
every stream is started afresh after a wake instead of trusting the old one.
Screen capture behind a `CaptureBackend`: ScreenCaptureKit and AVFoundation on
macOS (HEVC by default), Windows Graphics Capture and a Media Foundation writer
on Windows (H.264). Each display is written as fragmented mp4 in segments with
every frame's master-clock timestamp, and a manager decides, from what the
backend reports, when a segment ends and another begins. The segment logic is
shared by both backends and tested without a screen.
What the OS says while komorebi acts: the unified log (`log stream`) on macOS,
one file per managed application, komorebi's process and the system; on Windows
the WinEvents komorebi hears, folded when repeated, and the Event Log's warnings
and its display, power and GPU providers. Both end up as `oslog/*.ndjson` on the
master clock, and a host with no OS trace says so instead of failing.
A session is a directory and its manifest, `session.json`: the host, the
komorebi flavor, the clock anchors, the log segments and the applications seen,
written atomically. komorebi's own log is recorded as the exact byte range
written while recording (`%TEMP%` on Windows, its data directory on a Mac),
together with the version of the komorebi that wrote it. A generated README in
each session says what every file is, quoting paths the way the host's shell
reads them.
The recorder subscribes to komorebi over its socket (a unix socket on macOS,
`uds_windows` on Windows) and writes every notification with the state it came
with, stamped on the master clock. Its accept loop only hands off to a writer
thread, since komorebi notifies subscribers while holding its locks. What
happens to the recording itself (a komorebi that exits, a stream that dies) is
written as incidents, and a lock file says whether a recorder is still running
in a session.
Which komorebi produced a session is a separate axis from the host the recorder
ran on. `Flavor` names the two and `Rules` holds what each knows: what its
events look like on the wire, which of them move a window, and which are
komorebi making things up. komorebi for Mac and komorebi for Windows each
implement it, and a missing method is a compile error. The Windows rules were
written from komorebi's source and say so until a recording confirms them.
Events are classified through the rules, and the names of things in a session
(`event:12`, `log:7`) are parsed here too, with the envelope and exit codes
every command will answer in.
Every record in a session is stamped on one monotonic clock:
`mach_absolute_time` on macOS and `QueryPerformanceCounter` on Windows, behind a
`platform` facade with a third `unsupported` host that builds anywhere. Anchors
pair that clock with the wall clock, a map interpolates between them, and a jump
detector notices sleep and clock steps by comparing how far each moved. Video
timecodes are parsed and printed here too.
`Host` and `ClockKind` say what a session was recorded on.