76 lines
5.1 KiB
Markdown
76 lines
5.1 KiB
Markdown
# 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-13)
|
|
|
|
- **Branch:** `main`. The audio UX follow-up (`9f9ed34`), round 2 (`18abe42`),
|
|
and round 3 (`dc29adf`) are **committed and pushed**.
|
|
- **This session (TASK 4 ship step 6 — health stats in the bottom bar):**
|
|
1. **Wiring:** `MainViewModel.OnFramePumpHealthUpdated` subscribes to
|
|
`FramePump.HealthUpdated` and marshals onto the UI thread (the encoder's
|
|
stderr loop raises on a background thread — same pattern as the audio
|
|
level handlers), copying the parsed bitrate/FPS/dropped/duration into
|
|
`CurrentHealth`, which the bottom bar's left stats group already binds
|
|
(bitrate/FPS/dropped/duration/health-message).
|
|
2. **Session hygiene:** `ResetHealth(status)` zeroes dropped frames + the
|
|
elapsed duration (and clears `LastError`) on go-live and on End so stats
|
|
never linger from a previous stream; bitrate/FPS stay on the tier's
|
|
targets from `ApplyStreamQuality`.
|
|
3. **Reality:** the bar lights up with REAL encoder values once TASK 5 fills
|
|
`_rtmpUrlProvider` with the reusable stream's ingest URL — until then the
|
|
pump skips the encoder (logged) and the bar shows the tier's targets.
|
|
No new tests needed: `FramePumpTests.HealthUpdated_ForwardsEncoderHealth`
|
|
already covers the pump→event seam; the VM handler is a thin marshal+copy.
|
|
- **Mic status contract (creator's rule, verified — do NOT "fix"):** the status dot is
|
|
**red until a mic resource is actually connected**. `MicStatus` starts `NotConnected`
|
|
(red); it goes green ONLY when the mixer's `MicConnected` fires, which comes strictly
|
|
from the mic source's `Started` event raised after `StartRecording()` succeeds. Zero
|
|
devices at startup → stays red and the mixer is never started; capture failure → yellow.
|
|
Green must never be raised earlier (e.g. on loopback start or on `Start()` being called).
|
|
- **Uncommitted:** this session — `ViewModels/MainViewModel.cs` (health wiring +
|
|
`ResetHealth`), `TASKS.md` (ship step 6 ✅), `ai.md`, `ViewModels/index.md`, `HANDOFF`.
|
|
- **Verified:** pending (build + full test run right before commit).
|
|
- **Landmines:**
|
|
- Never set a local `Canvas.SetTop` on the social bar — a local value permanently
|
|
overrides `{Binding SocialBarTop}` (the `ClearValue` lesson from 5.5).
|
|
- `AudioMixer` meter `Push` is unconditional **by design now**: `OnMicSample`/
|
|
`OnLoopbackSample` compute the level first, then raise the event — a
|
|
`?.Invoke(meter.Push(...))` short-circuit skipped the meter update when
|
|
nothing was subscribed (found by `RestartMic_ResetsLevel`, fixed).
|
|
- `MicConnected` comes from the source `Started` event, raised right after
|
|
`StartRecording()` succeeds — tests must `MarkStarted()` the fake source
|
|
before asserting connection state.
|
|
- The mic dot is red until a resource connects (see contract above) — green
|
|
only after `Started`, yellow on `Failed`.
|
|
- Zero mic devices at startup = red dot AND the mixer is never started, so
|
|
loopback + the game bar can't run either (no capture at all) — acceptable.
|
|
- The game detector is polled on the UI thread via a 250ms `DispatcherTimer`;
|
|
`OnGameAudioPollTick` wraps `Poll()` in try/catch + `AppLog`.
|
|
- The pump reads the active scene on a background thread while the UI can still
|
|
edit it — a concurrent-mutation exception is contained (logged + `Failed` +
|
|
the pump stops), not a crash.
|
|
- `StopAsync` must stop the encoder (closes stdin) **before** awaiting the pump
|
|
loop — closing stdin unblocks a write stuck on pipe backpressure; the reverse
|
|
order deadlocks.
|
|
- Tests never instantiate `MainViewModel` directly except the round-clip
|
|
integration test (a real `MainWindow`), which never goes live — keep it that way.
|
|
- Sandbox can't reach outbound HTTPS — `HttpSocialValidator` stub-handler tests
|
|
only, never the real instance.
|
|
- **Next step:** commit + push this ship-step-6 work (one commit). Then the remaining
|
|
TASK 4 requirement is **ship step 7 — one-click go live + private-only enforcement**
|
|
(honor the dialog's chosen visibility / enforce `privacyStatus = "private"`; also
|
|
fixes the REC sign's private state — see round-3 note above). Also queued: task 21
|
|
(logo + About hub), task 22 (voice filters). Nothing else queued — do not expand
|
|
the task queue on your own. Optional, not queued: rewriting the healed entry's
|
|
`ProfileUrl` to `https://mastodon.llamachile.tube/@gramps` (user must say the word).
|
|
|
|
- **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`.
|