| Sekce | Hodnota |
|---|---|
| Status | Accepted |
| Datum | 2026-05-08 |
| Oblast | Platform spending, UX, growth |
| Navazuje na | specification/mara-fatigue-fup.md, specification/invite-system.md |
Background
TalkIDE provozuje Maru (PM agenta) a Kaie (devops agenta) přes Anthropic API klíč platformy. Každý uživatelský prompt = call na Anthropic API = přímý $ výdaj platformy. V alpha fázi platí Anthropic tier-based monthly cap, který je vždy binding constraint dříve než RPM/OTPM limity:
- Tier 2: $500/měs → ufinancuje zhruba 13 registrovaných userů (při 60 % WAU a $10/user/týden)
- Tier 3: $1,000/měs → ~27 registrovaných
- Tier 4: $5,000/měs → ~135 registrovaných
Upgrade tieru je time-gated (Tier 1 → Tier 4 = minimálně 21 dní) a závisí na Anthropic schválení. Bez controlled growth alpha rate-limituje sebe sama globálním capm dřív, než to kdokoli čeká.
Tři vzájemně provázaná rozhodnutí v tomto ADR adresují tento problém na různých vrstvách.
Rozhodnutí 1 — Quota windows: 5h + weekly rolling (ne daily, ne 30-day)
Rozhodnutí: Per-user quota se měří ve dvou rolling windows — 5hodinová a 7denní.
Proč:
- Claude Pro/Max uživatelé tento mental model už znají z Claude.ai (5h okno). Přenést tutéž konvenci = nulové kognitivní tření pro early adoptery.
- Idle user nečerpá nic — window se startuje první Mara zprávou, ne půlnocí. Daily reset by penalizoval aktivní uživatele odpoledne vs. ráno.
- Weekly cap brání marathon abuse přes víc 5h sessions v jednom týdnu — je to tvrdší strop na kumulované spend bez toho, abychom museli řešit 30-denní billing cykly.
Default budgety: 5h window $2.00, weekly $10.00. Konfigurovatelné bez redeploymentu.
Rozhodnutí 2 — Žádný BYOK (Bring Your Own Key)
Rozhodnutí: Uživatelé nemůžou napojit vlastní Anthropic API klíč. Všechny cally jdou přes platformní klíč a platformní billing.
Proč:
- Revenue model: uživatel platí TalkIDE, ne Anthropic. BYOK by de facto přenesl hodnotu mimo platformu a znemožnil monetizaci.
- Spend tracking: platforma musí mít kompletní přehled o vlastním výdaji — s externími klíči by nebylo možné implementovat globální emergency brake ani capacity plánovací algoritmus.
- UX konzistence: BYOK uživatelé by měli odlišné rate limity, modely a chování → support nightmare.
Rozhodnutí 3 — Žádný carry-over nepoužité kvóty
Rozhodnutí: Nevyužitá kvóta z 5h nebo weekly window propadá. Use-it-or-lose-it.
Proč:
- Brání hromadění u power userů na “power-day” (uložení 3 týdnů kvóty → jeden maratonský den za cenu 3× weekly cap).
- Férové vůči ostatním v poolu — každý dostane stejný “svěží” budget v každém okně.
- Zjednodušuje Redis state: jen
window_start_ts+used_cents, žádné balances.
Rozhodnutí 4 — Uniformní quota pro všechny alpha invitees
Rozhodnutí: V alpha fázi mají všichni uživatelé stejný budget. Žádné free/paid tier dělení.
Proč:
- Monetizační tier vrstva přijde post-alpha, jakmile bude jasné, které use-cases mají WTP.
- Pro alpha (13–27 userů) je komplexita pricing tabulky zbytečná. Jedna hodnota v configu je jednodušší na správu i komunikaci (“TalkIDE alpha je zdarma, fair use platí”).
Rozhodnutí 5 — Grace finish: kontrola kvóty PŘED turnem, ne mid-turn
Rozhodnutí: Kvóta se kontroluje před každým turnem. Pokud je kvóta OK, celý turn proběhne
dokonce — i kdyby quota mezitím přesáhla limit. Další turn pak vrátí ASLEEP.
Proč:
- Zastavit Maru uprostřed generování odpovědi = přerušený výstup + ztracený kontext. Horší UX než dovolit turn dokončit.
- Overhead “grace finish” je ~5–10 % nad kvótu — akceptovatelné pro alpha.
- Předvídatelné chování: uživatel vždy dostane celou odpověď, nikdy ořezanou.
Rozhodnutí 6 — Founder-gated invite cascade (ne automatický viral growth)
Rozhodnutí: Invites NEJSOU udělované automaticky. Mirek ručně přes admin tool rozhoduje, kdy a komu udělit invites — na základě reálné kapacity (capacity recommender dashboard).
Proč:
- Viral growth je nepřátelský vůči tier upgrade timeline. Exponenciální nárůst userů před přechodem na vyšší tier = globální rate-limit pro všechny.
- Manuální kontrola umožňuje škálovat růst synchronně s kapacitou platformy.
- V alpha je retenční data důležitá — invite od reálné osoby (ne automatický kód) filtruje “drive-by” signupy.
Kaskáda: Gen 0 (Mirek seeds) → po ověření kapacity Mirek grantuje invites Gen 0 →
Gen 0 pozve Gen 1 → atd. Každý grant je auditovaný v invite_grants tabulce.
Rozhodnutí 7 — Personifikovaný FUP UX (“Mara fatigue states”)
Rozhodnutí: Místo technického “quota exceeded” error UI zobrazuje stav Marou jako personifikovaný fatigue state (FRESH → WARMED_UP → TIRED → GROGGY → EXHAUSTED → ASLEEP).
Proč:
- TalkIDE branduje Maru jako kolegu, ne jako API wrapper. “Kolegyně je unavená” je empatie. “Quota exceeded” je punitivní a technická.
- Fatigue state zároveň přirozeně komunikuje degradaci modelu — uživatel chápe, proč Mara “myslí pomaleji”, aniž by věděl o model swapech Sonnet → Haiku.
- Graduální degradace (model swap, thinking cap, delay) místo binárního cutoff dává uživateli čas “dopracovat, co nutně potřebuje” před sleep window.
Rozhodnutí 8 — i18n na FE straně, BE posílá enum
Rozhodnutí: Backend posílá strukturovaný fatigue_level: FRESH|WARMED_UP|TIRED|GROGGY|EXHAUSTED|ASLEEP
- countdown timestamp. Frontend si z pool textů vybere lokalizovanou message.
Proč:
- Žádný message pool v DB = žádná migrace při změně copy.
- FE tým může iterovat copy bez BE deploy.
- i18n je přirozené — stejný enum, jiný locale soubor.
- Pool 3–5 variant per state (random pick) brání stereotypnímu opakování zprávy.
Consequences
Pozitivní
- ✅ Platforma má plnou kontrolu nad Anthropic spend — žádné surprises
- ✅ Graduální UX degradace je empatická a brand-konsistentní s Mara personou
- ✅ Invite kaskáda umožňuje škálovat alpha synchronně s Anthropic tier upgrades
- ✅ Redis + PG dual-layer tracking umožňuje reconciliation a audit trail
- ✅ Grace finish eliminuje “broken mid-response” UX
- ✅
AnthropicGatewayServiceje Spring@Service(ne UseCase) volaný z UseCases — Anthropic call je infrastructural concern cross-cutting napříč více UC, ne business UC sám o sobě
Negativní / trade-offs
- ⚠️ Model swap (Sonnet → Haiku) při TIRED/GROGGY může zhoršit kvalitu výstupu — uživatel to pravděpodobně pozná, ale frame “Mara je unavená” dává kontext
- ⚠️ Bez carry-over mohou power useři pociťovat “ztrácím nevyužitý budget” — komunikační challenge pro onboarding
- ⚠️ Founder-gated growth je pomalý záměrně — tradeoff oproti rychlejší validaci PMF
References
- specification/mara-fatigue-fup.md — detailní spec quota mechanismu, state machine, gateway architektura
- specification/invite-system.md — detailní spec invite kaskády, DB schema, admin tool
Thanks for the feedback.