finishing AIs work because tokens
This commit is contained in:
@@ -130,6 +130,11 @@ GlobalHotkeyTests + HotkeyConfigTests (TASK 20), WebcamMenuGateTests (TASK 26),
|
||||
`AudioPipelineTests.Mix_HonorsProviderGains…` + `RoundClipInteractionTests.Round_Clip_Corner_Is_Grabbable…`
|
||||
are NOT regressions; see HANDOFF.md. Run test classes individually — the full-suite vstest run hangs.)**
|
||||
|
||||
Reward-event capture (monetization awareness, see the Monetization section) will add its integration
|
||||
tests here when it ships: one real chat-poll payload containing all seven reward event types →
|
||||
assert the persisted canonical `RewardEvent` rows (type + amount/currency/tier/memberLevel/participant
|
||||
ids) round-trip into SQLite.
|
||||
|
||||
### Real-MainWindow tests MUST be hermetic (DB pollution bug)
|
||||
|
||||
The integration test boots a real `MainWindow` → `MainViewModel` → real `LayoutStore`
|
||||
@@ -861,6 +866,33 @@ crooked.
|
||||
how-tos / feature requests / manual-skimmers. Maintenance cadence = "when I get around to it" with
|
||||
emergency patches; not a 24/7 service promise.
|
||||
|
||||
**Monetization awareness (built-in, ungated, free — 2026-09-01):** the app is monetization-aware by
|
||||
design, for **every** creator, free and ungated (the only subscriber swap remains the branding-flash
|
||||
removal above). It has three layers, all free — this is the product's differentiator, not a paid tier:
|
||||
|
||||
- **Reward-event capture (the data foundation).** The live-chat poll (`YouTubeChatService.Poll`)
|
||||
already receives every reward event over `liveChatMessages` but today only decodes two
|
||||
(`superChatEvent`, `newSponsorEvent`); the other five — `superStickerEvent`, `membershipGiftingEvent`,
|
||||
`giftMembershipReceivedEvent`, `memberMilestoneChatEvent`, `giftEvent` — are silently dropped. The
|
||||
plan: decode all seven into a canonical `RewardEvent` and persist each to a SQLite table
|
||||
(`RewardEvents`: broadcastId, type, timestamp, amountMicros, currency, tier, memberLevelName,
|
||||
gifter/recipient channelIds). `superChatEvents.list` (30-day lookback) backfills prior broadcasts.
|
||||
This single feed is the foundation that Alerts, the session report, and the journey tracker all read.
|
||||
- **Session / broadcast report.** A session is created at Go Live; the poll + End roll that session's
|
||||
reward totals (new members, Super Chat $, stickers $, gifts, milestones). This is the in-app
|
||||
replacement for the emailed external "stream activity report" — the incumbents (Streamlabs et al.)
|
||||
email near-useless post-stream summaries; we track the same data natively and maintain it.
|
||||
- **Journey tracker.** On sign-in/startup, pull current `channels.list?mine=true&part=statistics`
|
||||
(`subscriberCount`/`viewCount`/`videoCount` — the current OAuth scopes suffice). Compute position
|
||||
toward each YPP tier threshold and project an ETA curve from the creator's own
|
||||
per-stream/per-day velocity (subs + watch hours). **YPP thresholds are versioned, date-aware DATA,
|
||||
never constants** — the Tier-2 bar doubles for new applicants on **2027-02-01** (long-form 4,000 →
|
||||
8,000 qualified hrs / 365d; Shorts 10M → 20M / 90d), while the Tier-1 fan-funding bar (500 subs /
|
||||
3,000 hrs / 3M Shorts) is unchanged. Hardcoding the pre-2027 numbers would ship a wrong ETA.
|
||||
Analytics-API scopes (`yt-analytics.readonly`, additive `yt-analytics-monetary.readonly`) are an
|
||||
additive capability behind a seam (`IChannelStatsProvider`), not a v1 blocker — current-scope data
|
||||
is the v1 baseline; the Analytics scopes would require an OAuth re-consent, deferred.
|
||||
|
||||
**What was rejected:** always-on watermark (obscurable — replaced by the flash), hard stream-time
|
||||
cutoffs (the worst dead end — a stream dying mid-broadcast reads as broken, and YouTube streams
|
||||
routinely run 2-4 hours), soft-limit nagging, freemium feature tiers, and donation-only (relies on
|
||||
|
||||
Reference in New Issue
Block a user