feat(notifications): event detection (changes-requested) - #609
Conversation
Add review payload typing, a detectNotificationEvents helper for pull_request_review webhooks, and audit recording when a maintainer requests changes so the PR author can be notified downstream. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Note Gittensory Gate skippedPR closed before full evaluation. No late first comment was created.
Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers. |
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
reviewbot · advisory review Reviewed 5 changed file(s) — two independent AI reviewers. Suggested action: ✅ Safe to merge — the reviewer found no blocking issues. Reviewer A · Suggestions
Worth double-checking
Reviewer B · |
|
gittensory · advisory review Reviewed 5 changed file(s) — two independent AI reviewers. Suggested action: ✅ Safe to merge — both reviewers found no blocking issues. Reviewer A · Suggestions
Worth double-checking
Reviewer B · Suggestions
Worth double-checking
|
…feed (closes #536, advances #535) (#707) Closes the contribution loop's killer event: when a reviewer requests changes on a miner's PR, the miner now has a notification to read. Builds the event→subscription→delivery pipeline on top of the existing changes-requested detector (events.ts, #609), delivered through the miner's primary surface — MCP. - D1: `notification_subscriptions` (per-channel opt-out; badge on by default) + `notification_deliveries` with UNIQUE(dedup_key, channel) as the idempotency guard, so a duplicate webhook / queue retry produces exactly one delivery. - Queue: `notify-evaluate` / `notify-deliver` job types. The webhook enqueues notify-evaluate per detected event; evaluate resolves channels, writes one idempotent delivery row (rate-limited per recipient/window — bursts beyond the cap are recorded `suppressed`, never notified), and enqueues notify-deliver; deliver makes the badge row visible (pull-based). - Notification service (`src/notifications/service.ts`): channel resolution, public-safe changes-requested copy (via sanitizePublicComment), the badge feed builder (unread = delivered count), idempotent evaluate, and deliver. - MCP: `gittensory_list_notifications` + `gittensory_mark_notifications_read`, the miner's harness surface. Both self-scoped via requireContributorAccess — a session can only read/clear its OWN login's notifications. - `DetectedNotificationEvent`/`NotificationEventType` moved to types.ts (canonical location) to avoid a types↔events circular import. Scope: badge channel only (the AC's first channel, not gated behind #150/PWA). The maintainer-gated browser-extension badge UI (#534/#569), email (#570), and the predicted-gate fix-list enrichment remain follow-ups on #535. Tests: service unit (channel resolution, copy, feed, idempotency, rate-limit, mute, deliver), queue wiring (webhook→evaluate→deliver e2e + idempotency), MCP tool scope (own vs. other login). 97% coverage gate green; workers tests pass.
Summary
GitHubReviewPayloadand an optionalreviewfield onGitHubWebhookPayloadinsrc/types.tssopull_request_reviewwebhooks are typed end-to-end.detectNotificationEventsinsrc/notifications/events.tsto emit a singlepull_request_changes_requestedevent for the PR author, with self-notification and bot suppression.processGitHubWebhookvia audit metadata (notification.event_detected) for downstream notify-evaluate/deliver jobs.test/unit/notifications-events.test.tsand a queue processor test intest/unit/queue.test.tsfor detection, suppression rules, fallback metadata, and one audit record per changes-requested review.Closes #566
Scope
CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally; global coverage stays at or above 97% for lines, statements, functions, and branches (aim for 98%+ branch coverage locally so CI variance does not fail near the threshold)npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm run audit --audit-level=moderateIf any required check was skipped, explain why:
npm run validatewas run locally (coverstypecheck+test:coverage); branch coverage met the 97% threshold.actionlint,test:workers,build:mcp,test:mcp-pack,ui:*,audit) are left for CI to run.Safety
Notes
reviewpayload prerequisite needed for changes-requested detection (see feat(types): add review field to GitHubWebhookPayload #536 / roadmap(pillar 2): surfaces — browser-extension rebuild & notifications #527).notify-evaluate/notify-deliver) are tracked in feat(notifications): queue jobs (notify-evaluate/deliver) #568 and follow-on notification issues.