Context
src/mcp/find-opportunities.ts's runFindOpportunities (the hosted loopover_find_opportunities
MCP tool, #2308) has several real, reachable branches that test/unit/find-opportunities.test.ts
never exercises. A local unsharded npm run test:coverage run shows the file at 79.34% branch
coverage (96/121) — the lowest of any src/mcp/** file.
Confirmed-untested paths (verified by reading both the source and the full existing test file, which
only calls runFindOpportunities with targets, never searchQuery):
- The entire
parsed.searchQuery branch of runFindOpportunities (lines 232-235: calling
searchCandidateIssuesWithSummary instead of fetchCandidateIssuesWithSummary) and the
post-search canAccessRepo re-filter (lines 251-257) are never taken — every existing test passes
targets, never searchQuery.
buildGoalSpecsByRepo (lines 132-151) is never called with a real goalSpec.lane or
goalSpec.languages — no test asserts that a supplied lane narrows preferredLabels or that
languages becomes wantedPaths globs, and the !lane && languages.length === 0 early-return
(undefined) vs. the populated-spec path are both unverified.
appliedLane / appliedMinRankScore / warnings inclusion in the final result (lines 269-276):
no test asserts these optional fields actually appear in result when a lane/minRankScore/warning
is present, nor that they're omitted when absent.
resolveDiscoveryGithubToken's installation-token fallback loop (lines 178-198): when
env.GITHUB_PUBLIC_TOKEN is unset, the loop over reposByFullName.values() — skipping a repo with
no installationId (line 190's continue), calling createInstallationToken for one that has it,
and the try/catch swallowing a createInstallationToken failure to try the next repo — has zero
test coverage. Every existing test either sets GITHUB_PUBLIC_TOKEN or expects
github_token_unavailable.
validated.ok === false at the top of runFindOpportunities (line 208): the shared
validateFindOpportunitiesInput rejection paths are tested directly, but not through
runFindOpportunities itself.
Requirements
Add test cases to test/unit/find-opportunities.test.ts:
- A
searchQuery-only call (no targets) that stubs searchCandidateIssuesWithSummary (via the
same fetch stub pattern the existing tests use for fetchCandidateIssuesWithSummary) and asserts
result.status === "ok" with issues from the search path; combine with a canAccessRepo that
rejects one returned repo, asserting it's filtered out post-search.
- A
goalSpec.lane + goalSpec.languages call asserting appliedLane is present in the result and
that ranking behavior differs from an unscoped call (or at minimum that buildGoalSpecsByRepo's
output shape reaches the ranker — e.g. via a spy/mock if rankCandidateIssuesWithSummary is
swappable, otherwise assert on appliedLane/appliedMinRankScore presence).
- A call with
goalSpec.minRankScore above 0 asserting appliedMinRankScore is present in the
result, and a call with neither lane nor minRankScore asserting both are omitted.
resolveDiscoveryGithubToken (may need an internal export, or exercise via runFindOpportunities
with GITHUB_PUBLIC_TOKEN unset): one target with no stored installation (skipped), one target
whose createInstallationToken call is stubbed to throw (falls through to the next repo), and one
whose token resolves successfully.
- A directly-invalid
runFindOpportunities input (e.g. no targets and no searchQuery) asserting
status: "invalid_request" end-to-end, not just via validateFindOpportunitiesInput in isolation.
Deliverables
Test Coverage Requirements
src/mcp/find-opportunities.ts is scored by the 99%+ codecov/patch gate on any future touching PR.
This issue should bring the file from 79.34% to at or near 100% branch coverage.
Expected Outcome
runFindOpportunities's searchQuery path, goal-spec application, applied-field reporting, and
installation-token fallback are all provably correct, not just the targets + GITHUB_PUBLIC_TOKEN
happy path currently tested.
Links & Resources
src/mcp/find-opportunities.ts
test/unit/find-opportunities.test.ts (file to extend)
- Related:
test/unit/mcp-find-opportunities.test.ts, test/unit/mcp-cli-find-opportunities.test.ts
(MCP-tool-wrapper-level tests — check these don't already cover the search-query path before
duplicating; if they do, port the missing scenarios down to the unit-level test instead)
Context
src/mcp/find-opportunities.ts'srunFindOpportunities(the hostedloopover_find_opportunitiesMCP tool, #2308) has several real, reachable branches that
test/unit/find-opportunities.test.tsnever exercises. A local unsharded
npm run test:coveragerun shows the file at 79.34% branchcoverage (96/121) — the lowest of any
src/mcp/**file.Confirmed-untested paths (verified by reading both the source and the full existing test file, which
only calls
runFindOpportunitieswithtargets, neversearchQuery):parsed.searchQuerybranch ofrunFindOpportunities(lines 232-235: callingsearchCandidateIssuesWithSummaryinstead offetchCandidateIssuesWithSummary) and thepost-search
canAccessRepore-filter (lines 251-257) are never taken — every existing test passestargets, neversearchQuery.buildGoalSpecsByRepo(lines 132-151) is never called with a realgoalSpec.laneorgoalSpec.languages— no test asserts that a supplied lane narrowspreferredLabelsor thatlanguagesbecomeswantedPathsglobs, and the!lane && languages.length === 0early-return(
undefined) vs. the populated-spec path are both unverified.appliedLane/appliedMinRankScore/warningsinclusion in the final result (lines 269-276):no test asserts these optional fields actually appear in
resultwhen a lane/minRankScore/warningis present, nor that they're omitted when absent.
resolveDiscoveryGithubToken's installation-token fallback loop (lines 178-198): whenenv.GITHUB_PUBLIC_TOKENis unset, the loop overreposByFullName.values()— skipping a repo withno
installationId(line 190'scontinue), callingcreateInstallationTokenfor one that has it,and the
try/catchswallowing acreateInstallationTokenfailure to try the next repo — has zerotest coverage. Every existing test either sets
GITHUB_PUBLIC_TOKENor expectsgithub_token_unavailable.validated.ok === falseat the top ofrunFindOpportunities(line 208): the sharedvalidateFindOpportunitiesInputrejection paths are tested directly, but not throughrunFindOpportunitiesitself.Requirements
Add test cases to
test/unit/find-opportunities.test.ts:searchQuery-only call (notargets) that stubssearchCandidateIssuesWithSummary(via thesame
fetchstub pattern the existing tests use forfetchCandidateIssuesWithSummary) and assertsresult.status === "ok"with issues from the search path; combine with acanAccessRepothatrejects one returned repo, asserting it's filtered out post-search.
goalSpec.lane+goalSpec.languagescall assertingappliedLaneis present in the result andthat ranking behavior differs from an unscoped call (or at minimum that
buildGoalSpecsByRepo'soutput shape reaches the ranker — e.g. via a spy/mock if
rankCandidateIssuesWithSummaryisswappable, otherwise assert on
appliedLane/appliedMinRankScorepresence).goalSpec.minRankScoreabove 0 assertingappliedMinRankScoreis present in theresult, and a call with neither lane nor minRankScore asserting both are omitted.
resolveDiscoveryGithubToken(may need an internal export, or exercise viarunFindOpportunitieswith
GITHUB_PUBLIC_TOKENunset): one target with no stored installation (skipped), one targetwhose
createInstallationTokencall is stubbed to throw (falls through to the next repo), and onewhose token resolves successfully.
runFindOpportunitiesinput (e.g. no targets and no searchQuery) assertingstatus: "invalid_request"end-to-end, not just viavalidateFindOpportunitiesInputin isolation.Deliverables
it(...)blocks intest/unit/find-opportunities.test.tscovering the five requirementgroups above.
Test Coverage Requirements
src/mcp/find-opportunities.tsis scored by the 99%+codecov/patchgate on any future touching PR.This issue should bring the file from 79.34% to at or near 100% branch coverage.
Expected Outcome
runFindOpportunities'ssearchQuerypath, goal-spec application, applied-field reporting, andinstallation-token fallback are all provably correct, not just the
targets+GITHUB_PUBLIC_TOKENhappy path currently tested.
Links & Resources
src/mcp/find-opportunities.tstest/unit/find-opportunities.test.ts(file to extend)test/unit/mcp-find-opportunities.test.ts,test/unit/mcp-cli-find-opportunities.test.ts(MCP-tool-wrapper-level tests — check these don't already cover the search-query path before
duplicating; if they do, port the missing scenarios down to the unit-level test instead)