A user action enters at the top. It either exits as a nudge card at the bottom, or it dies at one of the two gates: the relevance filter or the guardrails.
hire-team is exempt; it rides on struggle signals.dismissals++ and the zero-dismissals signal is dropped, which lowers every future score.featuresShownThisSession and the session counter ticks. Ignoring the card costs the user that feature for the rest of the session just as much as dismissing it does.Two maps, one multiplier, one threshold. That's the whole scoring model.
The first edit is the informative one. The tenth tells you a little more, not ten times more. Log₂ gives the first occurrence full weight and then flattens, which replaced a pile of threshold signals like edit-count-5 and slides-15plus that used to create cliff behavior.
This runs the real calculateScores(), computeRelevantFeatures() and checkGuardrails() math with the actual weight maps. Change the person, the prompt, and what they're doing, and watch which feature wins.
Scoring decides what. Guardrails decide whether. Any single failure holds the nudge.
| Check | Threshold | Why it exists |
|---|---|---|
| Pro user | isProUser | Kill switch. Once they convert, nudges are off permanently. |
| Session cap | 3 / session | Three interruptions is the ceiling on one visit. |
| Cooldown | 60s | No back-to-back cards, even if two features both clear 14. |
| Feature repeat | once / session | Never pitch the same feature twice in a session. |
| Intent floor | universal ≥ 3 | Behavior alone isn't enough. There has to be some independent buying signal — low credits, a pricing visit, a return session. |
| Activity pause | 3s idle | Don't interrupt mid-drag. Wait for a natural beat. |
pricing-visit visited three times counts as 3 toward the floor but contributes 3 × log₂(4) × 0.4 = 2.4 to each score. The floor is a check on which intent signals exist, not how hard they fired.| Feature | Type | Sub-features | The signals that actually move it |
|---|---|---|---|
| 🧠 Better AI Models | PRO | 3 | deck-regenerate (5), undo-redo (3), insert-slide-prompt (3) |
| 🎨 Brand Kit | PRO | 4 | theme-global (4), style-change (3), doc-upload (3), deck-switch (3) |
| ✨ Remove Watermark | PRO | 2 | share-link-copy (3), play-preview (3), deck-publisher (3) |
| 📄 PowerPoint/PDF Export | PRO | 3 | export-download (5), doc-upload (4), export-click (3) |
| 👥 Invite Collaborators | PRO | 4 | invite-attempt (5), prompt-team (5), acq-referral (3) |
| 📈 Viewer Analytics | PRO | 3 | share-link-copy (3), deck-sharer (3), doc-upload (2) |
| 🤝 Hire Our Team | SERVICE | 1 | deck-regenerate (5), doc-upload-long (4), undo-redo (3) |
ai-models — regenerating the deck and undoing repeatedly. The difference is that AI Models says "unlock a better model" while Hire Our Team says "let us handle it." It's also the only feature exempt from the relevance filter, because struggle isn't something a role or a prompt can predict.| User does | System does |
|---|---|
| Clicks the CTA | isProUser = true. Every future nudge is killed at the first guardrail. |
| Clicks "Not now" | dismissals++ and zero-dismissals (a universal, +1) is removed, so every feature's score drops slightly. Rejection makes the system quieter. |
| Ignores it (10s) | Auto-closes. Costs the same as a dismissal in feature suppression, but doesn't drop zero-dismissals. |