From 8fa54d2de75522f908f878d43f75bf0926e2e18e Mon Sep 17 00:00:00 2001 From: gramps Date: Tue, 1 Sep 2026 07:27:35 -0700 Subject: [PATCH] finishing AIs work because tokens --- HANDOFF.md | 9 +++++++++ TASKS.md | 14 ++++++++++++-- ai.md | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index b3be0d4..6aae2cb 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -27,6 +27,15 @@ Nothing actively mid-flight. The last TASK 21 work unit (the **UI picker / acqui slice**) is **handed off**, not in progress — spec reproduced in the section below. It is a GUI feature that must be built + verified natively on Windows. +**2026-09-01 — doc-only work unit (monetization awareness spec'd into the map):** NOT +code — the user asked to integrate the built-in monetization-awareness requirement into +the existing docs as precursor/related work, then said "exec". Done: `ai.md` +(Monetization section + Tests note), `TASKS.md` (TASK 10 "Related work" + the two Alerts +items), and `MONETIZATION.md` (gitignored; product stance that analytics is free & ungated). +No code changed; no task numbers added (kept as related work per the no-expand-queue rule). +Whether this stays a docs-only change or seeds the first code slice (reward-event capture) +is the user's call — nothing in flight until decided. + ## Project-wide code-complete picture (2026-08-31, user's framing) The user revisited the ongoing "how code-complete are we" question. Current agreed read: diff --git a/TASKS.md b/TASKS.md index 80c6323..866fdc7 100644 --- a/TASKS.md +++ b/TASKS.md @@ -119,7 +119,7 @@ Lifecycle: `created → ready → [testing] → live → complete` (transitional 17. ☐ **Text source** — live text ("Starting soon", "Back in 5", handle, callout) 18. ✅ **Chat box** — YouTube live chat rendered *on* the stream so viewers read along in-video — `ChatBoxRenderer` (WPF FormattedText → VideoFrame), configurable font size/color/badges/timestamps/max-messages via Elements panel, schema v10, persisted across save/load 19. ❌ **Background removal (milestone 2)** — ONNX Runtime + DirectML, MediaPipe Selfie Segmentation — deliberately NOT in this build -20. ☐ **Alerts** — Super Chat / membership / subscribe pop-ins; build after the six; **the one paid feature** (see Monetization in `ai.md`) +20. ☐ **Alerts** — Super Chat / membership / subscribe pop-ins; build after the six; **the one paid feature** (see Monetization in `ai.md`). **Precursor — reward-event capture (2026-09-01):** Alerts render from the app's canonical `RewardEvent` feed (all 7 `liveChatMessage` reward types, persisted to SQLite + the session report — see TASK 10 → "Related work — monetization awareness"), so it consumes that already-built data rather than re-integrating `liveChatMessages`. That capture is the required prior milestone. 21. ✅ **Show Desktop toggle** — `Source.ShowDesktop` bool persisted in DB (schema migration + LayoutStore read/write). When checked, primary monitor captures regardless of fullscreen game state. Toggling off falls back to running game or releases to static placeholder. `ClearBackdropCaptureAsync` clears `CaptureKey` + `VideoImageSource` so static fallback renders. Toggle on Live backdrop context menu (IsCheckable MenuItem). 22. ✅ **Top bar — status light + avatar + Log In button** — red/green/pulsing ellipse (disconnected/connected/live). Avatar border visible only when connected, loads via `BitmapImage` code-behind. "Log In" button visible when disconnected, calls `StartStreamCommand` → GoLiveWindow. `ShowStartStream` now requires `IsConnected`. 23. ✅ **Chat preview — one-at-a-time mock messages** — `RunMockChatPreviewAsync`: simple async loop, displays `MockChatMessages[n]` via `Take(n+1)`, 1000ms between messages, wraps at end. `ChatPreviewEnabled` property on Source (default true). Stops on real messages, restarts on fade timer clear. @@ -148,7 +148,8 @@ the hot few and nothing esoteric. If a user needs more, they've graduated to OBS 6. **Chat box** — YouTube live chat rendered *on* the stream so viewers read along in-video. YT-native. 7. **Alerts** — Super Chat / membership / subscribe pop-ins. The dopamine source. **The one big lift** (Super Chat event streaming + on-stream rendering/animation); build after the six. **Also the one - paid feature** — see Monetization in `ai.md`. + paid feature** — see Monetization in `ai.md`. Consumes the canonical `RewardEvent` feed (reward-event + capture, TASK 10 → related work). Deliberately NOT supported: game capture, browser source, media playlist, VLC, color-key voodoo, MIDI. @@ -710,6 +711,15 @@ the validator → persisted), compositor bar overlay (top/bottom + above-flash), **Goal:** annual subscription via Polar.sh that removes the branding watermark. All features are free — the only difference between free and paid is the watermark. +**Related work — monetization awareness (2026-09-01, ungated, free):** this task's billing is the +*payer* side; the *product* also carries built-in, ungated monetization awareness for every creator — +reward-event capture (all 7 `liveChatMessage` reward event types → canonical `RewardEvent` → SQLite +persistence), per-session/broadcast reports (members, Super Chat $, stickers, gifts, milestones — the +in-app replacement for the emailed "stream activity report"), and a journey tracker (position % + +ETA vs. versioned, date-aware YPP thresholds; the Tier-2 bar doubles for new applicants 2027-02-01). +Details and design notes: `ai.md` → Monetization. This is tracked as related work under this task's +narrative, not a separate task number — it ships in its own code slices with one integration test each. + **Business details (pricing, Polar product/checkout/discounts) in `MONETIZATION.md` (gitignored).** **Polar product:** `d105dfa1-497e-423b-8cd4-e0ee2e3abbc0` (LlamaCasty, $99/yr, currently `private`) diff --git a/ai.md b/ai.md index 765c765..a03b3b7 100644 --- a/ai.md +++ b/ai.md @@ -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