Skip to content

feat(inbox): saved-market move alerts - #1007

Open
AntonioVentilii wants to merge 8 commits into
mainfrom
av/market-move-inbox-notifications
Open

AntonioVentilii wants to merge 8 commits into
mainfrom
av/market-move-inbox-notifications

Conversation

@AntonioVentilii

Copy link
Copy Markdown
Contributor

Motivation

The market inbox kind ("a market you follow moved") and the notify.marketAlerts preference were stubbed alongside the saved-markets feature but never wired — marketAlerts did nothing and the kind had no producer. This connects them: saving a market is the follow signal, and a material YES move now notifies you. Implements spec docs/ai/spec-driven-development/specs/2026-06-23-feat-market-move-inbox-notifications.md. Stacked on #1006 (streak/level), which it shares inbox.store.ts with.

Changes

  • New marketMoveInboxStore derived source + initMarketMoveAlerts effect (mounted in NotifToastHost): snapshots the YES probability of each saved, open market; seeds a baseline on first observation (no card); when the probability moves at least MARKET_MOVE_THRESHOLD (10 pts) it records a move alert and advances the baseline so the same move can't re-fire. Gated by preferences.notify.marketAlerts.
  • Persisted, capped (MARKET_ALERT_MAX), windowed (MARKET_ALERT_WINDOW_MS) alert list + per-market baseline map, with the new keys cleared on identity switch. Baselines for un-saved markets are pruned; one live alert per market.
  • Cards deep-link to the market, count toward the badge, and use the generic per-id read/dismiss overlay — no special acknowledge path.
  • New inbox.market.* i18n (title + up/down body) across all live catalogs + pt-BR.
  • docs/ai meta-update: PRODUCT.md documents saved-market move alerts; spec authored under docs/ai/spec-driven-development/specs/.
  • No satellite change; no new analytics event (notification_opened already carries the kind).

Tests

  • npm run check:i18n → 7 live locales aligned (2461 keys).
  • npm run check (svelte-check) → 0 errors, 0 warnings.
  • npx prettier --check + npx eslint on all changed files → clean (incl. --max-warnings 0).

Replace the removed mock streak/level seed cards with producers derived
from the live profile: a flame-milestone card (3/7/15/30 days) and a
level-up card, gated by a persisted high-water marker so a returning user
sees no retroactive backlog and a broken-then-rebuilt streak re-notifies.
The streak card respects the streak-reminder preference.
Wire the previously-dormant market notification kind to the existing
saved-markets feature: when a saved, open market's YES probability shifts
by at least MARKET_MOVE_THRESHOLD since last seen, surface a move card,
gated by the notify.marketAlerts preference. A persisted per-market
baseline seeds on first observation (no card) and advances on a fired move
so the same shift can't re-fire; alerts are capped and aged out.
# Conflicts:
#	docs/ai/PRODUCT.md
#	src/lib/stores/inbox.store.ts
…ications

# Conflicts:
#	src/lib/stores/inbox.store.ts
Correct the STREAK_MILESTONES docstring (the VXP award ladder uses 14, not
the flame-stage 15, so the two are intentionally not coupled); guard
milestoneWhen against a non-finite persisted stamp; skip the localStorage
write when the marker is unchanged; and reload the marker on owner change so
a previous user's seen markers can't suppress the next user's cards.
Base automatically changed from av/funny-lamarr-28628f to main June 26, 2026 20:44
AntonioVentilii added a commit that referenced this pull request Jun 26, 2026
# Motivation

Two inbox notification kinds — `streak` and `level` — have no producer
since the mock seed was removed, so they can never fire. This wires them
to live profile data so a daily-flame milestone or a level-up actually
surfaces in the inbox. Implements spec
`docs/ai/spec-driven-development/specs/2026-06-23-feat-streak-level-inbox-notifications.md`
(the `market` kind is the sibling spec / PR #1007). Branch is merged up
to current `main` (which had already removed the mock seed entirely), so
this change is purely additive.

# Changes

- New `streakInboxStore` / `levelInboxStore` derived sources in
`inbox.store.ts`, merged into `combinedInboxStore` (badge, list, toast,
mark-read, dismiss, mark-all all apply). The streak card fires on a
flame-stage milestone (3/7/15/30 days), the level card on a
profile-level increase.
- New persisted high-water marker (`INBOX_PROGRESS_STORAGE_KEY` +
`inboxProgressStore`): seeds to the current value on first observation
(no retroactive backlog on a fresh device), advances on acknowledge, and
lowers when a streak breaks so re-climbing re-notifies. Maintained by
`initInboxProgress`, mounted in `NotifToastHost` beside
`initInboxToasts`.
- Streak card respects `preferences.notify.streakReminder`; both route
to their kind-default surface (Flow / Profile).
- `streakMilestone` helper added to `streak.utils.ts`.
- Identity-storage reconcile clears the new progress key on account
switch.
- docs/ai meta-update: `PRODUCT.md` documents the new inbox milestones;
spec authored under `docs/ai/spec-driven-development/specs/`.
- No analytics change — `notification_opened` already carries the kind
as its label; no satellite change.

# Tests

- `npm run check:i18n` → 7 live locales aligned; new keys added to all
live catalogs + pt-BR.
- `npm run check` (svelte-check) → 0 errors, 0 warnings.
- `npx prettier --check` + `npx eslint` on changed files → clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant