feat(sponsor-prompt): lower print/archive/cost thresholds to fire for typical new installs

The toast was calibrated for power users — lowest bars were 100 prints,
    50 archives, 100 cost. Most installs never crossed any of them, especially
    with the install base ~doubling since March. Matomo confirms: only 4
    prints-100 and 3 archives-50 deeplink visits to /sponsors.html in a 7-day
    window despite tens of thousands of weekly pulls.

    Adds lower thresholds without changing priority order or cooldown:
      PRINT_MILESTONES   = (10, 25, ...)
      ARCHIVE_MILESTONES = (5, 10, ...)
      COST_MILESTONES    = (25, 50, ...)

    Existing toast copy uses {count}/{total} interpolation in all 11 locales,
    so no i18n changes. Tests rebalanced so "below the floor" still tests
    with the new floor; new test_fires_at_lowest_threshold pins prints-10.
This commit is contained in:
maziggy
2026-06-28 12:47:42 +02:00
3 changed files with 19 additions and 8 deletions
+2
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -32,9 +32,9 @@ logger = logging.getLogger(__name__)
COOLDOWN_DAYS = 14
PRINT_MILESTONES = (100, 500, 1000, 2500, 5000)
COST_MILESTONES = (100, 500, 1000)
ARCHIVE_MILESTONES = (50, 250, 1000)
PRINT_MILESTONES = (10, 25, 100, 500, 1000, 2500, 5000)
COST_MILESTONES = (25, 50, 100, 500, 1000)
ARCHIVE_MILESTONES = (5, 10, 50, 250, 1000)
ANNIVERSARY_YEARS = 1
@@ -155,15 +155,24 @@ class TestPrintMilestones:
assert trigger is not None
assert trigger.milestone == "prints-100"
@pytest.mark.asyncio
async def test_fires_at_lowest_threshold(self, db_session: AsyncSession):
user = await _make_user(db_session)
await _add_completed_prints(db_session, user_id=user.id, count=10)
trigger = await service.evaluate(db_session, user.id)
assert trigger is not None
assert trigger.milestone == "prints-10"
assert trigger.threshold == 10
@pytest.mark.asyncio
async def test_failed_prints_dont_count(self, db_session: AsyncSession):
user = await _make_user(db_session)
await _add_completed_prints(db_session, user_id=user.id, count=50)
await _add_completed_prints(db_session, user_id=user.id, count=5)
for _ in range(60):
db_session.add(PrintLogEntry(status="failed", created_by_id=user.id))
await db_session.flush()
trigger = await service.evaluate(db_session, user.id)
# Only 50 completed → below 100 threshold → no print trigger.
# Only 5 completed → below 10 threshold → no print trigger.
# Anniversary not reached either; no other counter populated.
assert trigger is None
@@ -181,10 +190,10 @@ class TestArchiveMilestones:
class TestCostMilestones:
@pytest.mark.asyncio
async def test_fires_when_cost_sum_crosses_100(self, db_session: AsyncSession):
# Prints with cost = ~3.5 each, 30 prints → 105.
# 5 prints, cost ~21 each → 105 total. Below the 10-print threshold so
# the prints family stays silent and cost gets a chance.
user = await _make_user(db_session)
await _add_completed_prints(db_session, user_id=user.id, count=30, cost_each=3.5)
# 30 < 100 prints, so prints-100 not eligible. cost = 105 ≥ 100 → fires.
await _add_completed_prints(db_session, user_id=user.id, count=5, cost_each=21.0)
trigger = await service.evaluate(db_session, user.id)
assert trigger is not None
assert trigger.family == "cost"