You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.ts — export 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)
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.ts—export type FanoutTarget = { owner: string; repo: string }andexport 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).src/selfhost/orb-collector.tsif one exists, else a simplePromise.allover chunks of e.g. 5) and surface the GitHub rate-limit headers in aRawCandidateIssue[]-adjacent{ rateLimitRemaining, rateLimitResetAt }summary so a caller can back off.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.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 firstpackages/gittensory-engine/lib/opportunity-ranker.ts(from the ranker issue) — consumes this fan-out's outputsrc/mcp/local-write-tools.ts(70 lines) — the existing no-cloud-write boundary language/pattern to mirror for the no-clone boundaryvi.stubGlobal("fetch", ...)— the repo's existing GitHub-call test pattern (see any existingtest/unit/*.test.tsthat stubs fetch for GitHub calls)