Files
LlamaCasty/Helpers/index.md
T
gramps b1d6034662 TASK 55 slice 1: the startup log is size-capped
The creator (2026-10-09): 'we need some sort of log-rotation so that we don't
inadvertently fill up a user's drive.' startup.log was uncapped - 23MB and growing
every few seconds, because FfmpegEncoder logs every non-progress ffmpeg stderr line.

The policy lives in a new Helpers/LogRotation.cs as a pure function over a path
(RollIfNeeded(logPath, maxBytes, retainedFiles)), so AppLog's 156 call sites keep
their surface and the rule is testable on its own. At 5MB the live file rolls to
startup.1.log and one rolled copy is kept - the FILE SET is bounded, not just the
live file, so a long stream cannot grow the log without limit. A failed rotation
degrades to the old behaviour instead of taking the app down.

Pattern reference (cited): Serilog's file sink pairs fileSizeLimitBytes (the cap)
with retainedFileCountLimit (how many rolled files to keep) -
https://github.com/serilog/serilog-sinks-file

Guard: ytLive.Tests/AppLogRotationTests.cs - the ONE test drives the real
AppLog.Write against a temp dir (two internal seams: PathOverride, MaxBytes) and
asserts the roll, the fresh live file, and that after a SECOND roll the directory
still holds exactly startup.log + startup.1.log.

Also fixed a stale catalog row: TASK 12 (master limiter) shipped 2026-08-15 and was
still marked 'Queued'.
2026-10-22 06:51:04 -07:00

3.4 KiB

Helpers — index

Cross-cutting utilities. See schema.md for the memory-map conventions.

File Purpose
ViewModelBase.cs INotifyPropertyChanged + SetProperty<T>() — base for all ViewModels
RelayCommand.cs ICommand implementation for all button actions
AppLog.cs File logger to %APPDATA%\ytLlive\startup.log; startup checkpoints + unhandled-exception capture (the crash this map is named for). Size-capped: rolls to startup.1.log at 5 MB (TASK 55)
LogRotation.cs The size-capped-rotation policy as a pure function over a path: roll startup.log → startup.1.log when it passes the cap, keeping N rolled copies. Separate from AppLog so the logger's 156-call-site surface never changes and the rule is testable alone (TASK 55)
FocusPreservingListBox.cs ListBox subclass that keeps selection/focus coherent when the selected item is deleted; IsSelectable predicate skips hidden scenes; drag-reorder guard
OAuthCredentials.cs Baked-in Google OAuth client ID/secret (desktop app; loopback callback)
TokenStore.cs DPAPI-protected OAuth session persistence (%APPDATA%\ytLlive\ytLlive.auth, CurrentUser scope); Save/Load/Clear — sign-in survives restarts
ImageCache.cs Image byte caching (assets live in the DB)
InverseBoolToVisibilityConverter.cs / NotNullToVisibilityConverter.cs XAML value converters for visibility bindings
AllTrueToVisibilityConverter.cs Multi-value AND-gate → Visible; gates the layer-row capture menu items on row-IsBackground + staged-scene-is-Live (TASK 25)
CameraConflictProbe.cs Best-effort diagnostic: when a camera won't start, enumerates running processes known to hold cameras (OBS, Zoom, Teams, NVIDIA Broadcast, browsers, etc.) — Windows doesn't expose "which process has this device" via any public API, so this is a suspect list, not a verdict
StripPool.cs Four DEDICATED background threads at BelowNormal priority that split one composite into horizontal row strips (the caller runs a strip too); started lazily, runs inline below 64 rows. UNIT 5 — do NOT demote the ThreadPool from Parallel.For, it leaks into unrelated work (see ai.md "Render budget")
FrameCadence.cs Pure arrival-cadence counter (FrameCadence + FrameCadenceSummary.Describe): frames, gaps, hitches, longest/avg gap for a window of a timestamped stream. Fed by MediaCaptureFrameSource (camera stamps vs our arrivals) and FramePump (distinct webcam Epochs that reached the output) — UNIT 0, see ai.md "Frame cadence"
HexToBrushConverter.cs A "#RRGGBB" hex string → SolidColorBrush (transparent on bad input), so a template can paint a colour swatch straight from the palette. Registered in the theme as HexToBrush — the theme paints the colour, never the UI code (TASK 63)
ClosedBoxTemplateSelector.cs An ItemTemplateSelector that gives a ComboBox's CLOSED box a different template from its drop-down rows: WPF calls it with the ContentPresenter's templated parent — the ComboBox for the closed box, the ComboBoxItem for a row. The only way to tell them apart (SelectionBoxItemTemplate is read-only and mirrors ItemTemplate) — TASK 63

Related: Themes/Controls.xaml styles the lists this class backs; Models/index.md and ViewModels/index.md for the objects it works on.