Skip to content

feat(miner-discovery): cross-repo GitHub search/listing fan-out (metadata-only) #2307

Description

@JSONbored

Implement the actual metadata-only cross-repo fan-out: given a contributor-supplied list of target repos (or a GitHub search query), list open issues across all of them using only the GitHub REST/GraphQL search and issue-listing endpoints — never git clone, never fetching file blobs beyond the small CONTRIBUTING/AI-USAGE docs the AI-policy issue already covers. This is the client-side orchestration layer that calls the AI-policy hard-skip, then the ranker, over the raw GitHub metadata.

Deliverables

  • packages/gittensory-miner/lib/opportunity-fanout.tsexport type FanoutTarget = { owner: string; repo: string } and export async function fetchCandidateIssues(targets: FanoutTarget[], githubToken: string): Promise<RawCandidateIssue[]> — for each target, first checks the AI-policy verdict (hard-skip on ban), then lists open issues via the GitHub REST issues-list endpoint (metadata fields only: number, title, labels, created_at, updated_at, comments count — never body content beyond what's needed for lane-fit label/path heuristics).
  • Explicit rate-limit courtesy: batch requests with a small concurrency cap (mirror the concurrency-limiting pattern already used in src/selfhost/orb-collector.ts if one exists, else a simple Promise.all over chunks of e.g. 5) and surface the GitHub rate-limit headers in a RawCandidateIssue[]-adjacent { rateLimitRemaining, rateLimitResetAt } summary so a caller can back off.
  • Unit tests using vi.stubGlobal("fetch", ...) (the repo's existing GitHub-call test pattern): a banned repo in the target list contributes zero issues and zero extra fetch calls beyond the policy-doc fetch; a mixed allowed/banned target list only fans out to the allowed ones; a GitHub API error for one target degrades that target to an empty list (with a warning) rather than failing the whole fan-out.
  • Explicit doc-comment stating the no-clone / metadata-only boundary, matching the boundary language already used in src/mcp/local-write-tools.ts ("gittensory never performs the write" — here: "never clones source, never uploads source").

References

  • packages/gittensory-engine/lib/ai-policy-map.ts (from the AI-policy issue) — the hard-skip check this orchestrator calls first
  • packages/gittensory-engine/lib/opportunity-ranker.ts (from the ranker issue) — consumes this fan-out's output
  • src/mcp/local-write-tools.ts (70 lines) — the existing no-cloud-write boundary language/pattern to mirror for the no-clone boundary
  • vi.stubGlobal("fetch", ...) — the repo's existing GitHub-call test pattern (see any existing test/unit/*.test.ts that stubs fetch for GitHub calls)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:featureGittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions