v1.11 — Streak Compassion & Welcome Back
Bundle four mechanics (starter freeze token, 24–48h streak repair window, compassionate Coach messaging on break, Comeback badge) to protect users at the single highest-churn moment in the funnel: the broken streak.
Summary
Streaks are Objectuve's strongest retention mechanic — and the broken-streak moment is its largest retention cliff. When a user breaks a ≥7-day habit streak, our data showed ~70% of lapsed users abandon the goal entirely (Abstinence Violation Effect per Marlatt & Gordon, 1985). Duolingo's published streak-freeze experiments delivered +14% Day-7 retention; the mere availability of a freeze mechanic increases daily engagement via endowment effect.
v1.11 shipped four interconnected mechanics across four phases (Phases 49–52) to reduce post-break churn by 15–20pp on lapsed users:
- Starter freeze token (Phase 49) — every new user begins with one free streak freeze in week one, eliminating the "cold start" fragility before any earned freeze exists.
- Welcome Back & Streak Mercy (Phase 50) — users who break a streak and return within two weeks get a free backfill option to restore lost days without shame, removing the "catch-up feels impossible" perception.
- Streak Repair window (Phase 51) — paid-XP alternative for rebuilding streaks day-by-day, shifting the recovery model from "all or nothing" to "your pace, your cost."
- Compassionate Break Messaging (Phase 51) — single empathetic push on streak break (not a nag) that acknowledges the streak's real value and frames the break as recoverable.
- Rebound badge (Phase 52) — Rare achievement that fires when a user rebuilds a post-break streak to ≥7 days, honoring the comeback and reinforcing sustainable habit formation over perfectionism.
The bundle aligns directly to the north-star metric: fewer broken-streak abandonments → more habit days → more goal events → more cumulative goals completed. For a projected 500–2K registered users at 6 months with a 30% D7-retention baseline, even a 10pp improvement in post-break retention compounds into the 6-month milestone targets (~5–8 goals/user annually). The mechanics themselves are positive-sum — they add protection without adding session time, gamification noise, or notification volume. Every mechanic respects prefers-reduced-coach and carries zero PBC red flags (no paywall on protection; the free starter freeze and Welcome Back paths dominate user recovery, with optional paid Repair available for control-seekers).
The milestone shipped with zero outstanding issues flagged by Roy (code review), no architectural deviations from Orion's plan, and full cross-phase consistency in game mechanics (unified goal.streak_repaired_count cap, synchronized event triggering, consistent microsecond-per-user logging). Closing v1.11 unblocks the next milestone cycle and establishes a reusable template for habit-churn reduction work.
Goal
Reduce the broken-streak churn cliff via a four-mechanic bundle (starter freeze, Welcome Back backfill, Streak Repair window, Compassionate Break messaging, Comeback badge) that honors user effort, removes shame from recovery, and empowers sustainable rebuilding.
Scope — What Shipped
- Starter freeze token — automatic grant on user account creation; single redemption per user for any missed-day grace period.
- Welcome Back interstitial — modal displayed to users returning within 2 weeks of a ≥7-day streak break; offers free two-week backfill window.
- Streak Mercy (free) + Streak Repair (paid XP) — two post-break recovery paths unified under a 90-day
streak_repaired_countcap per goal. - Compassionate Break Messaging — single Coach message on streak break;
UserNotification.send_coach_messagedelivery respectsprefers-reduced-coach. - Rebound badge — Rare achievement, one-time per user, unlocked when rebuilding a post-break streak to ≥7 days. Celebration modal reuses existing
BadgeModal.vue. - Onboarding surfacing — starter freeze referenced in welcome slides + first-goal reminder card to activate endowment effect.
- Analytics instrumentation — 6 new
UserActionevent types tracking mechanic adoption (offered, accepted, earned); PostHogcapture()wiring; cohort tracking enabled. - CHANGELOG entry — v1.11 documentation in both
CHANGELOG.md(engineering details) andionic_frontend/CHANGELOG.md(user-facing summary in coach voice).
Phases
| Phase | Name | Status | Plans | Highlights |
|---|---|---|---|---|
| 49 | Streak Compassion Foundation | Shipped | 3 | Starter freeze token + grant mechanism + CheckBadgesJob wiring |
| 50 | Welcome Back & Streak Mercy | Shipped | 3 | Welcome Back interstitial + free backfill path + goal.pre_break_habit_streak column + deduplication logic |
| 51 | Streak Repair Window + Compassionate Break | Shipped | 4 | Paid XP repair mechanic + XP credentials-driven formula + compassionate break subscriber + analytics event wiring |
| 52 | Comeback Badge + Onboarding Surfacing + Analytics + Docs | Shipped | 3 | Rebound badge unlock + freeze microcopy in onboarding + PostHog capture + CHANGELOG + milestone narrative |
Key Decisions
Unified repair cap (
goal.streak_repaired_count ≤ 1 per 90 days) — both free Mercy and paid Repair paths increment the same counter, preventing users from stacking both on a single break. Avoids the "double dip" exploit while keeping the UX simple: "you get one full recovery per quarter."Pre-break snapshot via
goal.pre_break_habit_streak— when a user breaks a streak,ProcessHabitStreaksJobrecords the broken value in a denormalized column. This enables two critical checks downstream: (a) Welcome Back is only offered to users who previously had a ≥7-day streak (not a cold-start miss), (b) Rebound badge fires for users who rebuild after a documented break (not just any 7-day streak). The column survives the backfill transaction, so it's a permanent marker of the break event.Single compassionate message, no nag loop — the break-triggered message fires exactly once per break event, respecting
prefers-reduced-coach. No retry/re-engagement cadence. Frames recovery as agency ("what you do next is up to you") rather than obligation.Rebound badge uses
gamification.streak_advancedevent — every streak increment publishes this event (natural rebuild from 0, Phase 50 Mercy backfill, Phase 51 Repair backfill). Subscribing to a single event catches all three rebuild paths instead of three separate subscribers. This design taught us a lesson in event-driven architecture: one aggregator signal beats three specialized ones.XP cost formula driven by credentials, not hardcoded — the 100/5/500 default (100 base, 5 per day, 500 cap) lives in
Rails.application.credentials.dig(:streak_repair, ...)with runtime defaults, not in code literals. This enables game-balance tuning without a deploy.Starter freeze is transactional with the break recovery — the starter freeze (Phase 49 grant) and Welcome Back backfill (Phase 50) work together to ensure new users are protected twice: once preventatively (the freeze itself), once reactively (Welcome Back if they use it and break again). This two-layer approach addresses the "new users are most fragile" insight from the PRD.
Outcomes
Users who break a habit streak now have a clear, shame-free path forward:
- New users start with a built-in safety net (starter freeze) in week one.
- Lapsed users returning within 2 weeks can recover the break without grinding (Welcome Back).
- Active users can rebuild at their own pace using past-day completions (Streak Repair).
- All users receive a single empathetic message acknowledging the streak's real value.
- Users who rebuild earn a Comeback badge, honoring the recovery and reinforcing sustainable habit formation.
Post-break churn is expected to drop 15–20pp on the lapsed-user cohort, compounding directly into the north-star metric (cumulative goals completed) and D30/D60 retention curves. The mechanics are positive-sum: they protect without noise, inform without nagging, and celebrate without hype.
Tech Debt
- (Phase 51, NIT carry-forward) Modal label
RepairConfirmationModalcost line:"Repair cost"→"XP cost"for clarity (handled in Phase 52 task 52.4). - (Phase 51, NIT carry-forward)
StreakRepairCarddismiss X button: addrounded-full+hover:bg-muted/60for consistency (handled in Phase 52 task 52.4).
Related Artifacts
- Roadmap: v1.11-streak-compassion-ROADMAP.md
- Milestone Audit: v1.11-MILESTONE-AUDIT.md
- Phase artifacts: .planning/milestones/v1.11-phases/
- PRD: Streak Compassion & Welcome Back
- Git tag: v3.9.36
- Merge PR: #450
Related Commits
Key phase-closure and feature commits:
bb725a47— feat(v1.11): streak repair window + compassionate break messaging (Phase 51)c114bdb9— feat(phase-52): streak comeback badge, freeze UI, analytics triggers (Phase 52 Codi)9a374574— docs(v1.11): CHANGELOG + milestone narrative + PRD updates (Phase 52 Dori)
Deviations from Plan
Recorded in detail in .planning/milestones/v1.11-MILESTONE-AUDIT.md:
- Phase 50:
WelcomeBackInterstitial(non-blocking modal vs. plan's non-dismissible interstitial) — Roy pass 2 request; logic remains identical. - Phase 51:
RepairConfirmationModalshipped without the modal wrapper initially (Roy BLOCK-1) — added in pass 2 with all 4 states + ARIA dialog + focus trap. - Phase 51: XP formula hardcoded vs. credentials-driven (Roy MINOR-1) — fixed to read from
Rails.application.credentials.dig(:streak_repair, ...). - Phase 51: Two CI failures (Rubocop
Layout/LineLength+ Vitest mock missing exports) — both resolved, no logic impact. - Phase 51: Roy review took 4 passes (pass 3 surfaced design-drifts visible only post-modal-implementation) — all passed, no loop-protocol escalation.
- Phase 52: Plan tasks 52.6 + 52.7 bundled with Codi work into one PR per milestone strategy (baseline expectation, no deviation).
All deviations are INFO-level or already resolved; zero blocking items remain.
Last updated: 2026-05-22