PR #85 opened: feat: curate activity feed — filter bot noise, dedupe PR events, plain-text excerpts
Why
The homepage feed was an unfiltered webhook dump: every PR appeared twice (opened + merged), dependabot bumps dominated the front page, and raw PR markdown/HTML (<details> blocks from dependabot bodies) leaked into the cards. For a client-facing portfolio that's noise drowning signal.
What
Ingest filtering (both paths — webhook + 30-min API sync):
- Skip events authored by bots (
*[bot], dependabot, renovate, github-actions) — newApp\Support\FeedNoisehelper - When a PR merges, delete its superseded
pr_opened/pr_closeditems, matched by repo + PR number so cross-path duplicates are caught too (RemoveSupersededPrItemsaction) - Store PR author in metadata going forward
Bugfix: ProcessGitHubWebhook referenced enum cases that don't exist (FeedItemType::PullRequestOpened etc. — the enum has PrOpened). PR webhooks have been throwing \Error (uncatchable by the catch (\Exception)) this whole time — all PR items were coming from the API sync only. Fixed.
Display: FeedItemData gains an excerpt field — prefers metadata.ai_summary (groundwork for the AI pass, next PR), falls back to markdown/HTML-stripped body via existing MarkdownHelper. Feed cards render the excerpt instead of raw PR body.
Backfill: php artisan cleanup:feed-noise (supports --dry-run) purges historic bot items (author metadata where present, dependency-bump title heuristics for older rows) and superseded PR duplicates.
After merge
Run php artisan cleanup:feed-noise --dry-run then php artisan cleanup:feed-noise on prod to clean existing data.
Tests
32 passing across ProcessGitHubEventTest + new CleanupFeedNoiseTest; full Feed suite (116) green.