Skip to content

Commit f031ff3

Browse files
fix(miner): correct usedDefaultGoalSpec for non-matching goal specs (#2873)
Report default goal-spec usage per ranked repo match instead of treating any supplied goalSpecsByRepo map as custom spec usage. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent d63c718 commit f031ff3

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

packages/gittensory-miner/lib/opportunity-ranker.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ function collectCandidates(candidates) {
8484
return { normalized, skippedInvalid };
8585
}
8686

87+
function rankedUsesDefaultGoalSpec(ranked, options = {}) {
88+
const goalSpecsByRepo = buildGoalSpecsByRepo(options);
89+
const specRepos = Object.keys(goalSpecsByRepo);
90+
if (ranked.length === 0) return specRepos.length === 0;
91+
return ranked.some((issue) => {
92+
const target = issue.repoFullName.trim().toLowerCase();
93+
return !specRepos.some((repo) => repo.trim().toLowerCase() === target);
94+
});
95+
}
96+
8797
/**
8898
* Rank metadata-only fan-out candidates locally. Never clones source, never uploads metadata, and never writes to
8999
* GitHub — it only composes deterministic engine signals and returns the sorted list.
@@ -99,7 +109,7 @@ export function rankCandidateIssuesWithSummary(candidates, options = {}) {
99109
return {
100110
issues: ranked,
101111
skippedInvalid,
102-
usedDefaultGoalSpec: Object.keys(buildGoalSpecsByRepo(options)).length === 0,
112+
usedDefaultGoalSpec: rankedUsesDefaultGoalSpec(ranked, options),
103113
defaultGoalSpec: DEFAULT_MINER_GOAL_SPEC,
104114
};
105115
}

test/unit/miner-opportunity-ranker.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,42 @@ describe("rankCandidateIssues (#2302 follow-up)", () => {
100100
expect(summary.skippedInvalid).toBe(0);
101101
});
102102

103+
it("summary reports default goal-spec usage when supplied specs do not match ranked repos", () => {
104+
const summary = rankCandidateIssuesWithSummary([rawIssue()], {
105+
nowMs: NOW,
106+
goalSpecsByRepo: {
107+
"other/repo": {
108+
minerEnabled: true,
109+
wantedPaths: [],
110+
blockedPaths: [],
111+
preferredLabels: ["feature"],
112+
blockedLabels: [],
113+
maxConcurrentClaims: 2,
114+
issueDiscoveryPolicy: "neutral",
115+
},
116+
},
117+
});
118+
expect(summary.usedDefaultGoalSpec).toBe(true);
119+
});
120+
121+
it("summary reports custom goal-spec usage when a ranked repo has a matching spec", () => {
122+
const summary = rankCandidateIssuesWithSummary([rawIssue()], {
123+
nowMs: NOW,
124+
goalSpecsByRepo: {
125+
"acme/widgets": {
126+
minerEnabled: true,
127+
wantedPaths: [],
128+
blockedPaths: [],
129+
preferredLabels: ["help wanted"],
130+
blockedLabels: [],
131+
maxConcurrentClaims: 2,
132+
issueDiscoveryPolicy: "neutral",
133+
},
134+
},
135+
});
136+
expect(summary.usedDefaultGoalSpec).toBe(false);
137+
});
138+
103139
it("prefers fresher, better-labeled opportunities over stale question threads", () => {
104140
const ranked = rankCandidateIssues(
105141
[

0 commit comments

Comments
 (0)