Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/gittensory-miner/lib/opportunity-ranker.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ function collectCandidates(candidates) {
return { normalized, skippedInvalid };
}

function rankedUsesDefaultGoalSpec(ranked, options = {}) {
const goalSpecsByRepo = buildGoalSpecsByRepo(options);
const specRepos = Object.keys(goalSpecsByRepo);
if (ranked.length === 0) return specRepos.length === 0;
return ranked.some((issue) => {
const target = issue.repoFullName.trim().toLowerCase();
return !specRepos.some((repo) => repo.trim().toLowerCase() === target);
});
}

/**
* Rank metadata-only fan-out candidates locally. Never clones source, never uploads metadata, and never writes to
* GitHub — it only composes deterministic engine signals and returns the sorted list.
Expand All @@ -99,7 +109,7 @@ export function rankCandidateIssuesWithSummary(candidates, options = {}) {
return {
issues: ranked,
skippedInvalid,
usedDefaultGoalSpec: Object.keys(buildGoalSpecsByRepo(options)).length === 0,
usedDefaultGoalSpec: rankedUsesDefaultGoalSpec(ranked, options),
defaultGoalSpec: DEFAULT_MINER_GOAL_SPEC,
};
}
36 changes: 36 additions & 0 deletions test/unit/miner-opportunity-ranker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,42 @@ describe("rankCandidateIssues (#2302 follow-up)", () => {
expect(summary.skippedInvalid).toBe(0);
});

it("summary reports default goal-spec usage when supplied specs do not match ranked repos", () => {
const summary = rankCandidateIssuesWithSummary([rawIssue()], {
nowMs: NOW,
goalSpecsByRepo: {
"other/repo": {
minerEnabled: true,
wantedPaths: [],
blockedPaths: [],
preferredLabels: ["feature"],
blockedLabels: [],
maxConcurrentClaims: 2,
issueDiscoveryPolicy: "neutral",
},
},
});
expect(summary.usedDefaultGoalSpec).toBe(true);
});

it("summary reports custom goal-spec usage when a ranked repo has a matching spec", () => {
const summary = rankCandidateIssuesWithSummary([rawIssue()], {
nowMs: NOW,
goalSpecsByRepo: {
"acme/widgets": {
minerEnabled: true,
wantedPaths: [],
blockedPaths: [],
preferredLabels: ["help wanted"],
blockedLabels: [],
maxConcurrentClaims: 2,
issueDiscoveryPolicy: "neutral",
},
},
});
expect(summary.usedDefaultGoalSpec).toBe(false);
});

it("prefers fresher, better-labeled opportunities over stale question threads", () => {
const ranked = rankCandidateIssues(
[
Expand Down
Loading