Skip to content

feat(miner): add cross-repo opportunity discovery - #1097

Closed
9876543210-tc-0123456789 wants to merge 1 commit into
JSONbored:mainfrom
9876543210-tc-0123456789:feat/proactive-cross-repo-opportunity
Closed

feat(miner): add cross-repo opportunity discovery#1097
9876543210-tc-0123456789 wants to merge 1 commit into
JSONbored:mainfrom
9876543210-tc-0123456789:feat/proactive-cross-repo-opportunity

Conversation

@9876543210-tc-0123456789

Copy link
Copy Markdown
Contributor

Summary

This change implements deterministic cross-repo opportunity discovery for miners and adds opt-in proactive alerts for high-value issues.
It fixes the current gap where miner discovery was mostly repo-local and reactive by:

  • adding a cross-repo ranked shortlist via MCP
  • reusing existing metadata-only signals instead of introducing new ML/scoring models
  • adding alert filters for lane, label, and freshness
  • extending proactive notifications beyond only “new issue opened” to also include newly-prioritized and aging opportunities

Related Issues

Change Type

  • New feature
  • Bug fix
  • MCP/API surface update
  • Database schema change
  • Notification behavior update
  • Tests added/updated
  • Documentation update
  • Breaking change

Real Behavior Proof

Validated locally with:

  • npm run typecheck
  • npx vitest run test/unit/issue-watch.test.ts test/unit/opportunity-discovery.test.ts test/unit/openapi.test.ts test/unit/mcp-output-schemas.test.ts test/integration/api.test.ts

Result:

  • typecheck passed
  • all targeted tests passed
  • 77/77 tests passed in the final validation slice

Key Files

  • src/services/opportunity-discovery.ts
  • src/mcp/server.ts
  • src/notifications/service.ts
  • src/queue/processors.ts
  • src/db/schema.ts
  • src/db/repositories.ts
  • src/signals/engine.ts
  • migrations/0053_cross_repo_opportunity_alert_filters.sql

Checklist

  • Cross-repo opportunity discovery added
  • Deterministic metadata-only ranking preserved
  • No raw reward/private miner data exposed
  • MCP surface wired
  • Hosted/server MCP path covered
  • Watch subscriptions support lane/label/freshness filters
  • Proactive notifications added for matching opportunity changes
  • Tests added/updated
  • Typecheck passed
  • Validation tests passed

@superagent-security

Copy link
Copy Markdown
Contributor

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

@9876543210-tc-0123456789

Copy link
Copy Markdown
Contributor Author

@JSONbored Could you review my PR?

@9876543210-tc-0123456789

Copy link
Copy Markdown
Contributor Author

@JSONbored Could you plz review my PR?

@ghost

ghost commented Jun 23, 2026

Copy link
Copy Markdown

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review — closed

14 files · 2 AI reviewers · 1 blocker · readiness 93/100 · CI green

🛑 Closed — AI reviewers agree on a likely critical defect: src/notifications/service.ts: In detectIssueWatchEvents, lane filtering is only applied when the repo is private, so public repo watches ignore the lanes filter, producing incorrect notification behavior. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Review summary
The PR adds cross‑repo opportunity discovery, new watch filters (lanes, freshness), and a new MCP tool. Core changes compile and tests pass, but lane filtering is only applied for private repositories, breaking the intended subscription semantics for public repos. The new types and schema updates are consistent across the codebase.

Blockers

  • src/notifications/service.ts: In detectIssueWatchEvents, lane filtering is only applied when the repo is private, so public repo watches ignore the lanes filter, producing incorrect notification behavior.
  • The `detectIssueWatchEvents` function in `src/notifications/service.ts` does not handle the case where `issue.createdAt` and `issue.updatedAt` are both undefined, which will cause `issueAgeDays` to be `0` and potentially lead to incorrect filtering. Verify this case is handled correctly.

<details>
<summary>Nits (5)</summary>

  • src/mcp/server.ts: The findOpportunities input schema duplicates the lane enum definition; consider extracting a shared schema.
  • src/services/opportunity-discovery.ts: normalizeLanes casts strings to ParticipationLane without validation; could enforce allowed values.
  • src/db/repositories.ts: upsertIssueWatchSubscription stores null for freshnessDays even when undefined; could omit the column to rely on DB default.
  • src/mcp/server.ts: watchIssues output includes freshnessDays:null; since the field is optional, omitting null would be cleaner.
  • src/notifications/service.ts: issueAgeDays calculation falls back to 0 if timestamps are missing, which may mask data issues.
    </details>

Why this is blocked

  • AI reviewers agree on a likely critical defect: src/notifications/service.ts: In detectIssueWatchEvents, lane filtering is only applied when the repo is private, so public repo watches ignore the lanes filter, producing incorrect notification behavior.: src/notifications/service.ts: In detectIssueWatchEvents, lane filtering is only applied when the repo is private, so public repo watches ignore the lanes filter, producing incorrect notification behavior.
Signal Result Evidence
Code review ❌ 1 blocker 2 reviewers, synthesized
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Review load ✅ 20/20 Readiness component derived from cached public PR metadata and labels; size label size:L.
Validation evidence ✅ 25/25 PR body includes validation/test evidence.
Open PR queue ✅ 10/10 0 open PR(s), 0 likely reviewable.
Contributor context ✅ Confirmed Gittensor contributor DragunovX16; Gittensor profile; 7 PR(s), 0 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Nits — 1 non-blocking
  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
Review context
  • Author: DragunovX16
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: TypeScript, Python, Clojure, CSS, Java, Kotlin, Scala
  • Official Gittensor activity: 7 PR(s), 0 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Explain no-issue PR.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Review load = cached public PR metadata such as size labels, changed paths, and preflight status.
  • Open PR queue = repo-wide review pressure; it is not a PR quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
Review details

Generated from public PR metadata and the diff. Advisory only; deterministic signals remain authoritative.

The PR adds cross‑repo opportunity discovery, new watch filters (lanes, freshness), and a new MCP tool. Core changes compile and tests pass, but lane filtering is only applied for private repositories, breaking the intended subscription semantics for public repos. The new types and schema updates are consistent across the codebase.

Blockers

  • src/notifications/service.ts: In detectIssueWatchEvents, lane filtering is only applied when the repo is private, so public repo watches ignore the lanes filter, producing incorrect notification behavior.
  • The `detectIssueWatchEvents` function in `src/notifications/service.ts` does not handle the case where `issue.createdAt` and `issue.updatedAt` are both undefined, which will cause `issueAgeDays` to be `0` and potentially lead to incorrect filtering. Verify this case is handled correctly.

<details>
<summary>Nits (5)</summary>

  • src/mcp/server.ts: The findOpportunities input schema duplicates the lane enum definition; consider extracting a shared schema.
  • src/services/opportunity-discovery.ts: normalizeLanes casts strings to ParticipationLane without validation; could enforce allowed values.
  • src/db/repositories.ts: upsertIssueWatchSubscription stores null for freshnessDays even when undefined; could omit the column to rely on DB default.
  • src/mcp/server.ts: watchIssues output includes freshnessDays:null; since the field is optional, omitting null would be cleaner.
  • src/notifications/service.ts: issueAgeDays calculation falls back to 0 if timestamps are missing, which may mask data issues.
    </details>

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 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.

  • Re-run Gittensory review

@ghost ghost added gittensory:reviewed gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. labels Jun 23, 2026
@JSONbored JSONbored closed this Jun 23, 2026
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
1877 2 1875 0
View the top 2 failed test(s) by shortest run time
test/unit/subnet-interface.test.ts > buildSubnetInterfaceDescriptor > defaults the upstream repo when not provided and contains no private/reward wording
Stack Traces | 0.00652s run time
AssertionError: expected '{"schemaVersion":"1.0","generatedAt":…' not to match /wallet|hotkey|reward|payout|earn|sco…/i

- Expected:
/wallet|hotkey|reward|payout|earn|scoring|multiplier|trust score|scoreability|rank(?:ing)?/i

+ Received:
"{\"schemaVersion\":\"1.0\",\"generatedAt\":\"2026-06-14T00:00:00.000Z\",\"subnet\":{\"netuid\":74,\"name\":\"gittensor\",\"home\":\"https://gittensor.io\",\"upstreamRepo\":\"entrius/gittensor\"},\"provider\":{\"name\":\"Gittensory\",\"role\":\"contribution_interface\",\"site\":\"https://gittensory.aethereal.dev\",\"summary\":\"Gittensor-native contribution planning layer: MCP guidance for contributors and a free anti-slop + AI second-opinion gate for maintainers.\"},\"interfaces\":{\"mcp\":{\"kind\":\"mcp\",\"transport\":\"http\",\"endpoint\":\"https://x.dev/mcp\",\"package\":\"@jsonbored/gittensory-mcp\",\"minimumVersion\":\"0.5.0\",\"recommendedVersion\":\"0.6.0\",\"tools\":[{\"name\":\"gittensory_get_decision_pack\",\"summary\":\"Surface contribution candidates across registered repos with duplicate-risk context.\"},{\"name\":\"gittensory_find_opportunities\",\"summary\":\"Rank the best cross-repo issues to build right now with lane, freshness, and queue context.\"},{\"name\":\"gittensory_check_before_start\",\"summary\":\"Check whether an issue is already claimed or solved before writing code.\"},{\"name\":\"gittensory_validate_linked_issue\",\"summary\":\"Confirm whether a planned PR has a linked issue before opening it.\"},{\"name\":\"gittensory_preflight_pr\",\"summary\":\"Preflight a planned PR for lane fit, duplicate risk, and review burden.\"},{\"name\":\"gittensory_monitor_open_prs\",\"summary\":\"Track your open PRs and what to clean up first.\"},{\"name\":\"gittensory_list_notifications\",\"summary\":\"See review feedback (e.g. changes requested) on your PRs.\"},{\"name\":\"gittensory_agent_plan_next_work\",\"summary\":\"Suggest useful next gittensor contribution actions from current repo and PR context.\"}]},\"githubApp\":{\"kind\":\"github_app\",\"slug\":\"gittensory\",\"installUrl\":\"https://github.com/apps/gittensory\"}},\"onboarding\":{\"docs\":\"https://gittensory.aethereal.dev\",\"steps\":[\"Maintainers: install the Gittensory GitHub App on a gittensor-registered repository.\",\"Contributors (miners): connect the Gittensory MCP endpoint in your agent harness (Claude Code, Cursor, etc.).\",\"Use gittensory_find_opportunities or gittensory_get_decision_pack to find high-fit, low-duplicate issues, then gittensory_check_before_start before writing code.\",\"Preflight with gittensory_preflight_pr and open a focused PR linked to its issue.\"]}}"

 ❯ test/unit/subnet-interface.test.ts:31:44
test/unit/signals.test.ts > world-class backend signals > keeps stale and ambiguous bounties out of strong opportunity ranking
Stack Traces | 0.0237s run time
AssertionError: expected { …(10) } to match object { fit: 'caution', score: 70 }
(8 matching properties omitted from actual)

- Expected
+ Received

  {
    "fit": "caution",
-   "score": 70,
+   "score": 80,
  }

 ❯ test/unit/signals.test.ts:965:32

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

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

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(miner): proactive cross-repo opportunity discovery — "best issue to build right now"

2 participants