diff --git a/docs/architecture/architecture.md b/docs/architecture/architecture.md index 4f4c9bd..2f97529 100644 --- a/docs/architecture/architecture.md +++ b/docs/architecture/architecture.md @@ -250,6 +250,32 @@ After (newest-first): `[chanB-new, chanA-mid, chanA-old, chanB-null]` The set of *processed* videos now also excludes auto-mode back-catalogue beyond the recency window (those stay listed, summarised on demand); within the processed set, only order changes. +### Connect-time onboarding burst (ADR-018 → ADR-028) + +On a successful YouTube connect, `ConnectHandler` enqueues a connect-triggered discovery pass; +the `discoveryTrigger` runs that pass and then fires the **onboarding burst** — a third entry path +that summarises up to `TAPIR_ONBOARD_SUMMARIZE_COUNT` (default 3, hard-capped) of the new user's +videos so the first session is not empty. The burst still flows through `globalFetchGate` (it is +not a throughput change); ADR-028 sharpened *which* videos and *which model*: + +- **Selection** is `OnboardBurstVideoIDs`, not pure newest-first. It keeps newest-first order but + excludes a video whose **known** duration is outside `[TAPIR_MIN_VIDEO_SECONDS, + TAPIR_ONBOARD_MAX_VIDEO_SECONDS]` (drops Shorts and multi-hour livestream VODs). An unknown + (NULL) duration is degrade-open — kept, but ranked after known-good rows. The connect-triggered + discovery pass runs *before* the burst, and ADR-023's `videos.list` enrichment now **persists** + `duration_s` (instead of discarding it after the Shorts filter), so a fresh user's candidates + carry a duration in time for selection. +- **Model**: the burst runs through a dedicated summarizer chain led by + `TAPIR_ONBOARD_SUMMARIZER_MODEL` (default `iguana/gemma4-26b`, the stronger local model), with + the standard ADR-022 chain following as fallback. This is a wiring choice — a second + `engineProcessor` over the same store / transcript cache / sink; the engine and ports are + unchanged. Empty / equal-to-primary collapses it back onto the shared processor. + +`has-captions` is deliberately **not** a selection signal — it is only knowable after a gate fetch +(or a ~0-probability cache hit at pilot scale), so the burst can avoid known-junk but cannot +promise captions. Cached-transcript-first selection was investigated and rejected (ADR-028: +~3% cross-user overlap). + --- ## Sequence — core use case: new video summarized diff --git a/docs/use-cases/connect_account.feature b/docs/use-cases/connect_account.feature index e5bcb7b..0c8c864 100644 --- a/docs/use-cases/connect_account.feature +++ b/docs/use-cases/connect_account.feature @@ -24,12 +24,19 @@ Feature: Connect and manage video accounts Then a discovery pass for my account is triggered right away And I do not have to wait for the next scheduled pass to see my videos - Scenario: Connecting summarizes my newest videos right away + Scenario: Connecting summarizes my best recent videos right away Given I have no connected video accounts When I connect my YouTube account - Then up to the onboarding cap of my newest videos are summarized through the rate gate + Then up to the onboarding cap of my newest likely-good videos are summarized through the rate gate + And videos whose known duration is too short or too long are skipped And the rest are left to the scheduled recency-bounded pass + Scenario: The onboarding burst summarizes with a stronger model + Given I have no connected video accounts + When I connect my YouTube account + Then the burst summarizes with the stronger onboarding model first + And the standard summarizer chain still follows as a fallback + Scenario: Tokens are never stored in the clear When I connect any video account Then no OAuth token value is stored in the database diff --git a/test/acceptance/scenario_coverage_test.go b/test/acceptance/scenario_coverage_test.go index 0a2fec3..502b945 100644 --- a/test/acceptance/scenario_coverage_test.go +++ b/test/acceptance/scenario_coverage_test.go @@ -38,10 +38,11 @@ var scenarioCoverage = map[string]string{ "An authenticated user on the welcome page sees their way in and out": "TestWelcomeLoggedIn", // connect_account.feature - "Connect a YouTube account": "TestCallbackExchangesAndRecordsConnection", - "Connecting an account discovers videos immediately": "TestCallbackTriggersDiscovery", - "Connecting summarizes my newest videos right away": "TestNewestUnsummarizedVideoIDs", - "Tokens are never stored in the clear": "TestCallbackExchangesAndRecordsConnection", + "Connect a YouTube account": "TestCallbackExchangesAndRecordsConnection", + "Connecting an account discovers videos immediately": "TestCallbackTriggersDiscovery", + "Connecting summarizes my best recent videos right away": "TestOnboardBurstVideoIDs", + "The onboarding burst summarizes with a stronger model": "TestBurstChainModelsLeadsWithOnboardModel", + "Tokens are never stored in the clear": "TestCallbackExchangesAndRecordsConnection", // paste_url.feature "Paste a valid YouTube URL": "TestPasteValidURLAddsAndRequests",