tools(stats): mine sessions from the logs, split by sink

`scripts/session-stats.py` turns every `startup*.log` into one row per FramePump session: tier,
scene, measured fps, drops, stalls, average/worst render, capture rate, and the build — with the
sink marked, because that is what makes the numbers quotable:

- **RECORD** — machine only, no socket. The cleanest minimum-config evidence.
- **TEST** — machine + socket, no audience; recognised by `Test session dock open` /
  `Test chat simulation`, which the creator pointed out are recorded too.
- **LIVE** — network and audience included.
- **UNKNOWN** — no marker; not evidence.

Verdicts use the average render against the frame budget, not the worst: the worst is dominated by
the 100 ms first-frame bake (a session that "holds" can still show worst 35 ms). `holds` = no drops,
no stalls, average under half the budget.

First run over the existing logs already separates the two halves of TASK 33: static Starting scenes
render at ~1.5 ms, the same pump with display capture running at 35–46 ms — the capture path, not the
overlays, is where a budget streamer loses the frame budget.
This commit is contained in:
2026-11-09 09:04:04 -08:00
parent ed32151136
commit 92d875c343
2 changed files with 274 additions and 0 deletions
+18
View File
@@ -139,6 +139,24 @@ save/load round trips are exact: an element removed in the UI (`RemoveElement`
close) does **not** come back after reload (`LayoutStorePersistenceTests` guards this).
## Session performance evidence
`python3 scripts/session-stats.py` mines every `startup*.log` (primary, rotated, and per-instance)
into one row per FramePump session: tier, scene, measured fps, drops, stalls, average/worst render,
capture rate — and the **sink**, which is the whole point:
| Sink | How it is recognised | What it proves |
|---|---|---|
| `RECORD` | `Recording ended` / `Recording discarded` | the machine alone — no socket |
| `TEST` | `Test session dock open` / `Test chat simulation` | the machine + socket, no audience |
| `LIVE` | `Broadcast created` / `Broadcast bound` | everything, network included |
| `UNKNOWN` | no marker (crashed or paused) | nothing — investigate before quoting it |
Verdicts: `holds` = 0 drops, 0 stalls, average render under **half** the frame budget; `strained` =
under the full budget; otherwise `over-budget`. Worst render is printed but never judged — it is
dominated by one-off startup hitches. This is the evidence source for the minimum-configuration
table in `product.md`: recordings first, because the network cannot pollute them.
## Persistence & external accounts (lookup)
- Layout: `%APPDATA%\ytLlive\ytLlive.db` (SQLite, schema v8 — scenes, sources, assets by SHA-256