7.1 KiB
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. Rewrite this file at session end, compaction, or any interruption.
Session state (last updated: 2026-08-14)
-
Branch:
main, in sync withorigin/main. -
TASK 21 — real logo + creator-hub About: SHIPPED (this session). The About overlay is now the creator hub: the real logo ("llama fortnite superman logo" copied from
\\llamavault→Assets/llama-logo.png, the creator's own art — no third-party license), plus hub links — llama chile shop on YouTube (MainViewModel.ChannelUrl, public now), Mastodon (https://mastodon.llamachile.tube/@gramps), Buy me a coffee (https://buymeacoffee.com/llamachiley— LIVE), and Unlock Premium (greyed "coming soon"; the itch.io product URL is a tabled seam,MainViewModel.PremiumUrl— the itch.io account was just created and needs a setup session later). Licenses & legal flips the About overlay to an in-app scrolling panel loading the shippedTHIRD-PARTY-NOTICES.txt(ShowLicenses()reads from the executable dir on first open, graceful "not found" fallback — never the OS viewer); "← Back to About" (BackToAbout_Click) returns. Integration test (ONE):AboutHubTestsdrives the real window, asserting the hub opens, the link URLs are real, licensing loads the shipped notices text, and back returns to the hub. 174 tests passing, 0 warnings. -
TASK 8 — meter scaling amplification: SHIPPED + pushed (
0b71b03).AudioLevelMeter.ToDisplayadds +10 dB input amplification before the −60..0 dBFS log map: speech peaks (~0.2 RMS) read ~0.93 (red) and normal speech (~0.05) ~0.73 (yellow) at maxed volume; ≤0.001 linear still reads 0 (never idles on background noise). One knob shared by the mic + game bars;× MicVolumeuntouched. -
TASK 4 ship step 7 — one-click go live + private-only enforcement: SHIPPED (this session; the final open TASK 4 requirement). Double-enforced privacy:
- Dialog locked to Private —
GoLiveViewModel.Visibilityis a get-only"Private", the visibility ComboBox is gone (replaced by a "Streams always start Private" note); settings' dead "Default Visibility" dropdown +MainViewModel.Visibilities/DefaultStreamVisibilityremoved. - Service forces private —
YouTubeStreamService.CreateBroadcastalways sendsprivacyStatus="private"; ctor gainedHttpClient? http = nullseam for tests. - Wired into go-live —
BeginGoLivefiresCreateBroadcastAsync(stores_currentBroadcastIdfor TASK 5's bind/transition; failure →StreamStatus.Errorvia AppLog, never a crash) +_framePump.StartAsync();StopStreamclears_currentBroadcastId. - PRIVATE badge — dark-red bordered, next to REC in the top bar,
Visibility="{Binding IsLivePrivate}"(MainWindow.xaml ~110). - Integration test —
ytLive.Tests/YouTubeStreamServiceTests.cs: the broadcast-insert request must carry"privacyStatus":"private"(RecordingHandler seam) + a no-session → null guard test.
- Dialog locked to Private —
-
Verified: build 0 warnings / 0 errors; 174/174 tests pass (173 + the new AboutHubTests).
-
Uncommitted (this session's TASK 21 batch):
MainWindow.xaml,ViewModels/MainViewModel.cs,MainWindow.xaml.cs,Assets/llama-logo.png(replaced with the real logo),ytLive.Tests/AboutHubTests.cs(new),TASKS.md,HANDOFF.md. ai.md + ViewModels/index.md updates pending — commit + push before continuing. -
Next step: commit + push TASK 21, then TASK 5 — reusable
variablestream (create once per channel, cache ingestion URL, bind to broadcast, feed_rtmpUrlProviderso the pump actually pushes —_currentBroadcastIdis already stashed for it). Also queued: task 22 (voice filters), and setting up the itch.io product page (the creator just made the account; the premium-unlock URL then lands inMainViewModel.PremiumUrland the About hub's "Unlock Premium" button lights up). Nothing else queued — do not expand the task queue on your own. Optional, not queued: rewriting the healed entry'sProfileUrltohttps://mastodon.llamachile.tube/@gramps(user must say the word). -
Landmines:
- Never add another test that constructs
new App()— useRealAppHost.Run(...)(shared STA host for the one WPF App per AppDomain; round-clip + source-naming tests). - Never set a local
Canvas.SetTopon the social bar — a local value permanently overrides{Binding SocialBarTop}(theClearValuelesson from 5.5). AudioMixermeterPushis unconditional by design now:OnMicSample/OnLoopbackSamplecompute the level first, then raise the event — a?.Invoke(meter.Push(...))short-circuit skipped the meter update when nothing was subscribed (found byRestartMic_ResetsLevel, fixed).MicConnectedcomes from the sourceStartedevent, raised right afterStartRecording()succeeds — tests mustMarkStarted()the fake source before asserting connection state.- The mic dot is red until a resource connects (see contract below) — green
only after
Started, yellow onFailed. - 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;OnGameAudioPollTickwrapsPoll()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. StopAsyncmust 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
MainViewModeldirectly except via a realMainWindowon theRealAppHostSTA thread (round-clip + naming), which never go live. - Sandbox can't reach outbound HTTPS —
HttpSocialValidatorstub-handler tests only, never the real instance.
- Never add another test that constructs
-
Mic status contract (creator's rule, verified — do NOT "fix"): the status dot is red until a mic resource is actually connected.
MicStatusstartsNotConnected(red); it goes green ONLY when the mixer'sMicConnectedfires, which comes strictly from the mic source'sStartedevent raised afterStartRecording()succeeds. Zero devices at startup → stays red and the mixer is never started; capture failure → yellow. -
Secret/DB/port facts live: OAuth client id/secret in
Helpers/OAuthCredentials.cs; OAuth session token inHelpers/TokenStore.cs(DPAPI →%APPDATA%\ytLlive\ytLlive.auth); layout DB%APPDATA%\ytLlive\ytLlive.db(schema v8;SocialEntry.Softwarecolumn is a column-presence migration like the others, no version bump); OAuth callbackhttp://localhost:8765/oauth2/callback; crash log%APPDATA%\ytLlive\startup.log.