# HANDOFF — session state

> Current operational state, read right after `TASKS.md`. Trust this file as the
> truth of what is in flight — do not re-derive from git/fs unless it points at
> a problem. Conventions: [`schema.md`](schema.md). Rewrite this file at session
> end, compaction, or any interruption.

## Session state (last updated: 2026-08-12)

- **Branch:** `main`. TASK 4 ship step 4 (WASAPI audio capture) is **built and
  tested** but **NOT committed** — the working tree is dirty with the audio
  layer (6 new files in `Services/Audio/` + `ytLive.Tests/AudioMixerTests.cs`,
  the `NAudio.Wasapi` 2.2.1 package reference, the THIRD-PARTY-NOTICES entry,
  the `MainViewModel` wiring, the `FfmpegEncoder.cs:139` CS8602 fix) and its
  memory updates (TASKS.md, ai.md, Services/index.md, HANDOFF.md). Ready to
  commit when the user says so.
- **Finished this session:** TASK 4 ship step 4 — the live audio capture layer:
  `IAudioSource`/`AudioSample` seam, `WasapiLoopbackAudioSource`
  (`WasapiLoopbackCapture` on the default render device), `WasapiMicAudioSource`
  (`WasapiCapture`, NAudio device resolved by `FriendlyName` matching
  `MicSourceName` via a re-read `Func<string?>` provider, default-endpoint
  fallback), `AudioMixer` (owns both sources, starts/stops with go-live, feeds
  the pure `AudioLevelMeter` → `MicLevelChanged`), `WaveToFloat` (IEEE-float /
  PCM16 / extensible). `MainViewModel` constructs the mixer, `BeginGoLive`
  success → `Start()`, `StopStream` → `Stop()`, `MicLevelChanged` marshalled to
  the UI thread → `AudioLevel`. Loopback samples are currently dropped (the
  encoder's AAC mix, ship step 5, consumes them). Build: **0 warnings** (a
  pre-existing CS8602 in `FfmpegEncoder.cs:139` surfaced during the rebuild and
  was fixed with `process!`). Tests: **139 passing** (was 122; +17 new audio).
- **Landmines:**
  - `WaveFormatExtensible.SubFormat` is a **`Guid`** in NAudio 2.x, not a
    `WaveFormatEncoding` — compare it to
    `NAudio.Dmo.AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT` (the IEEE-float
    subtype constant; it lives in the `NAudio.Dmo` namespace, not CoreAudioApi).
  - Use the **`NAudio.Wasapi` 2.2.1 feature package**, not the `NAudio`
    meta-package — the wasapi types come from that package (`WasapiCapture` in
    `NAudio.CoreAudioApi`, `WasapiLoopbackCapture` in `NAudio.Wave`); `NAudio.Core`
    comes in transitively.
  - The audio meter is an exponential smoother (0.2 factor) — a single pushed
    sample only moves 20% toward its RMS. Tests must push repeatedly before
    asserting a converged level.
  - Tests never instantiate `MainViewModel` directly except the round-clip
    integration test (a real `MainWindow`), which never goes live — so the mixer
    is constructed but never started there; NAudio types are only constructed,
    never touching devices. Keep it that way.
  - Mic device resolution must re-read `MicSourceName` at each `Start` (the app
    persists only the DisplayName, not a device ID).
  - Windows-only: all capture runs only while live (privacy indicator otherwise).

- **Next step:** TASK 4 ship step 5 — the frame-pipeline wiring
  (`CameraManager`/`ScreenCaptureManager` → compositor resolver → encoder
  construction, plus the loopback → encoder AAC mix). Nothing else queued — do
  not expand the task queue on your own.

- **Secret/DB/port facts live:** OAuth client id/secret in `Helpers/OAuthCredentials.cs`;
  OAuth session token in `Helpers/TokenStore.cs` (DPAPI → `%APPDATA%\ytLlive\ytLlive.auth`);
  layout DB `%APPDATA%\ytLlive\ytLlive.db` (schema v8; `SocialEntry.Software`
  column is a column-presence migration like the others, no version bump); OAuth callback
  `http://localhost:8765/oauth2/callback`; crash log `%APPDATA%\ytLlive\startup.log`.
