Skip to content

feat(notifications): active issue-watch monitor — gittensory_watch_issues (#699 path B) - #735

Merged
JSONbored merged 1 commit into
mainfrom
feat/issue-watch-monitor
Jun 14, 2026
Merged

feat(notifications): active issue-watch monitor — gittensory_watch_issues (#699 path B)#735
JSONbored merged 1 commit into
mainfrom
feat/issue-watch-monitor

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

What

Completes the active half of #699 (path A shipped the pull surface in #706): miners subscribe to repos for new grabbable, high-multiplier issues, and when one opens they're notified through the #535 pipeline.

How

  • issue_watch_subscriptions table (migration 0036) + repositories CRUD: upsertIssueWatchSubscription (idempotent on login+repo; re-subscribe updates the label filter), listIssueWatchSubscriptionsForLogin, deleteIssueWatchSubscription, listIssueWatchersForRepo. Labels are lowercased for case-insensitive matching.
  • engine.isGrabbableHighMultiplierIssue (exported): open + maintainer-created + not WIP — the exact condition path A ranks to the top.
  • notifications/service.detectIssueWatchEvents: fans out one event per matching watcher (honours the optional label filter; skips the issue's own author). DB-backed (reads watchers), so it lives beside the pure detectNotificationEvents. New eventType issue_watch_match (its pullNumber field carries the issue number) + buildIssueWatchNotification (public-safe "open to grab" copy — no reward/score/multiplier language).
  • processors: the issue-opened webhook path detects watch events and merges them into the existing notify-evaluate enqueue loop — reusing the whole feat(notifications): event-to-subscription-to-delivery service #535 delivery + rate-limit + idempotency machinery.
  • MCP gittensory_watch_issues (watch/unwatch/list, self-scoped): the miner control surface. Matches arrive via gittensory_list_notifications.

Flow

A maintainer opens a new non-WIP issue on a watched repo → each subscribed miner (matching their label filter, excluding the issue author) gets a badge notification: "New issue to grab on owner/repo#N." Maintainer-created issues are the highest-fit targets, so miners can claim them early.

Tests

Grabbable-issue logic, subscription CRUD (idempotency + label normalization), fan-out detection (label filter / author-skip / no-author edge / no-watchers), public-safe copy, the content dispatch, the MCP tool (incl. self-scope rejection), and the webhook end-to-end (opened issue → watcher enqueued, author skipped). Typecheck + UI lint + OpenAPI clean; 97% coverage held.

…sues (#699 path B)

Miners subscribe to repos for NEW grabbable, high-multiplier issues; when one
opens, the watchers are notified through the #535 pipeline. Completes the active
half of #699 (path A shipped the pull surface in #706).

- issue_watch_subscriptions table (migration 0036) + repositories CRUD (upsert
  idempotent on login+repo, list-for-login, delete, list-watchers-for-repo);
  labels lowercased for case-insensitive filtering.
- engine: export isGrabbableHighMultiplierIssue (open + maintainer-created + not
  WIP) — the exact condition path A ranks up.
- notifications/service: detectIssueWatchEvents fans out one event per matching
  watcher (label filter; skips the issue's own author), DB-backed so it sits
  alongside the pure detectNotificationEvents; buildIssueWatchNotification
  (public-safe "open to grab" copy). New eventType issue_watch_match (its
  pullNumber field carries the issue number).
- processors: the issue-opened webhook path detects watch events and fans them
  into the existing notify-evaluate enqueue loop.
- MCP gittensory_watch_issues (watch/unwatch/list, self-scoped) — the miner
  surface; matches surface through gittensory_list_notifications.

Tests: grabbable-issue logic, subscription CRUD, fan-out detection (label filter
/ author-skip / no-author edge), public-safe copy, the dispatch, the MCP tool
(incl. self-scope), and the webhook end-to-end. 97% coverage held.
@ghost

ghost commented Jun 14, 2026

Copy link
Copy Markdown

Note

Gittensory Gate skipped

PR closed before full evaluation. No late first comment was created.

Signal Result Evidence Action
Gate result ⚠️ Skipped #735 is no longer open. No action.

💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

@ghost ghost added the gittensory:reviewed label Jun 14, 2026
@ghost

ghost commented Jun 14, 2026

Copy link
Copy Markdown

gittensory · advisory review

Reviewed 10 changed file(s) — two independent AI reviewers.

Suggested action:Safe to merge — both reviewers found no blocking issues.

Reviewer A · gpt-oss-120b — recommends ✅ merge
The PR adds full support for issue‑watch subscriptions, including DB schema, repository helpers, notification generation, detection logic, MCP tool, and comprehensive unit tests. The implementation respects the public‑private sanitizer and appears type‑safe.

Suggestions

  • Add a unit test that verifies evaluateNotificationEvent processes an issue_watch_match event without errors (e.g., rate‑limit handling).
  • Confirm that the test environment runs the new migration so the issue_watch_subscriptions table is created before the CRUD tests execute.
  • Consider documenting the new gittensory_watch_issues tool in the public API docs for discoverability.

Worth double-checking

  • If evaluateNotificationEvent does not handle the new issue_watch_match type, notifications may be dropped.
  • Missing migration execution in CI could cause test failures for the new table.

Reviewer B · nemotron-3-120b-a12b — recommends ✅ merge
This PR adds issue-watch functionality (path B of #699) allowing miners to subscribe to repositories for notifications about new grabbable, high-multiplier issues. Changes span DB schema, repositories, notifications, MCP server, types, signals, queue processors, and include comprehensive tests. The implementation correctly handles public/private boundaries (using sanitizePublicComment), implements idempotent subscriptions, respects label filters, skips issue authors, and reuses the existing notification pipeline. Code is well-tested and follows project conventions.

Suggestions

  • Consider adding a comment in detectIssueWatchEvents explaining why we lowerCase/trim both issue and watcher labels for clarity.
  • In upsertIssueWatchSubscription, the labels normalization (lowercase, trim, dedupe) could be extracted to a helper function for reuse elsewhere.
  • The MCP tool's output schema could explicitly mark 'watching' as non-optional since it's always returned (though currently optional due to TypeScript inference).

Worth double-checking

  • Verify that the label matching logic (lowercase/trim) aligns with how GitHub treats labels (case-insensitive, but GitHub preserves original casing).
  • Ensure the 5000 limit for listIssueWatchersForRepo is sufficient for popular repos and doesn't inadvertently exclude watchers (though 5000 is high).
  • Confirm that the dedupKey format (issue_watch_match:{repo}#{number}:{watcher}) won't collide with other notification types (it's prefixed uniquely).

@ghost ghost added the gittensory-review label Jun 14, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant