[Feed feedback] Treat passive swipes as neutral and emit explicit engagement events
- Dominant language
- TypeScript
- Stars
- 4
- Forks
- 4
- PR merge metrics
- No merged PRs in 30d
Description
## Goal
Capture useful engagement signals without treating an ordinary swipe as negative feedback.
## Current implementation
PR #51 now:
- emits `impression` after the card remains at least 50 percent visible for 1 second;
- emits `dwell` separately after 3 seconds;
- treats passive swipe-away as neutral;
- emits `readme_open`, `like`, `unlike`, `dislike`, `undislike`, and `save`;
- centralizes feedback action names across the app and backend; and
- validates feedback batches before forwarding them to ML.
## Remaining problems
### Neutral events invalidate the feed
Every activity batch currently invalidates the Redis delivery queue, including batches that contain only `impression`. The app flushes this batch before requesting the next page, so a passive impression can delete the remaining feed and force regeneration.
Relevant code:
- https://github.com/ACM-VIT/gh-social/blob/b34d89d50afe6cc222350494078ec6d5b52dec13/backend/controllers/activityController.ts#L49-L63
- https://github.com/ACM-VIT/gh-social/blob/b34d89d50afe6cc222350494078ec6d5b52dec13/backend/services/feedService.ts#L263-L268
### Reaction state can disagree with persisted feedback
Switching from dislike to like clears the dislike only in local UI state and emits only `like`. The reverse path emits only `dislike`. The ML store can therefore retain both states while the UI displays one.
- https://github.com/ACM-VIT/gh-social/blob/b34d89d50afe6cc222350494078ec6d5b52dec13/src/components/home/RepositoryScreen.tsx#L181-L227
### Save can be recorded before it succeeds
The app queues `save` before the board mutation completes. If the mutation fails, ML can still treat the repository as consumed.
- https://github.com/ACM-VIT/gh-social/blob/b34d89d50afe6cc222350494078ec6d5b52dec13/src/components/home/save-popup.tsx#L121-L132
### Automated coverage is still missing
PR #51 does not add tests for the feedback transition matrix.
## Acceptance criteria
- [x] Reading a README and then swiping does not emit a negative skip.
- [x] A passive swipe produces impression or dwell data without an explicit negative label.
- [x] Thumb-down and its reversal use distinct actions.
- [x] Event names match the versioned ML contract.
- [ ] A neutral impression does not invalidate or regenerate the feed.
- [ ] Switching between like and dislike clears the previous persisted state.
- [ ] Save feedback is emitted only after the save mutation succeeds.
- [ ] Tests cover impression thresholding, passive swipe, README open, dislike reversal, like reversal, and save reversal.
## Related work
- App PR: https://github.com/ACM-VIT/gh-social/pull/51
- ML PR: https://github.com/ACM-VIT/gh-social-ml/pull/23
- ML feedback state: https://github.com/ACM-VIT/gh-social-ml/issues/29
- Durable event delivery: https://github.com/ACM-VIT/gh-social/issues/56
Contributor guide
Research direction
Start with backend/controllers/activityController.ts and backend/services/feedService.ts to trace how impression-only batches affect the Redis delivery queue, then inspect src/components/home/RepositoryScreen.tsx and src/components/home/save-popup.tsx for reaction and save event timing. Add coverage for the listed transition and threshold cases, with completion shown by neutral impressions preserving the feed, reversals clearing prior state, and save events following successful mutations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- redis, typescript
- Domain
- backend, frontend, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100