From 4589ef5116dffc3cc46e6d6dd51a7db5723030c1 Mon Sep 17 00:00:00 2001 From: nghetienhiep <13849419+nghetienhiep@users.noreply.github.com> Date: Wed, 15 Jul 2026 06:02:25 +0000 Subject: [PATCH] fix(mcp): make decision-pack and repo-decision CLI commands honor --help Both commands were fully wired into runCli's dispatch table and CLI_COMMAND_SPEC but never checked options.help, so --help fell through to the normal --login/--repo requirement and threw a login error instead of printing usage, unlike every other single-purpose subcommand in this CLI family. Closes #5927 --- packages/loopover-mcp/bin/loopover-mcp.js | 28 +++++++++++++++++++++++ test/unit/mcp-cli-packets.test.ts | 14 ++++++++++++ 2 files changed, 42 insertions(+) diff --git a/packages/loopover-mcp/bin/loopover-mcp.js b/packages/loopover-mcp/bin/loopover-mcp.js index b52228ca43..6aff9ac112 100755 --- a/packages/loopover-mcp/bin/loopover-mcp.js +++ b/packages/loopover-mcp/bin/loopover-mcp.js @@ -2160,7 +2160,21 @@ async function issueSlopCli(args) { for (const finding of payload.findings ?? []) process.stdout.write(`- ${finding.title}: ${finding.detail}\n`); } +function printDecisionPackHelp() { + process.stdout.write( + [ + "Usage: loopover-mcp decision-pack --login [--json]", + "", + "Fetch the cached (or freshly built) contributor decision pack for a GitHub login.", + "Mirrors the loopover_get_decision_pack MCP tool and GET /v1/contributors/{login}/decision-pack. No source upload.", + "", + "Pass --json for machine-readable output.", + ].join("\n") + "\n", + ); +} + async function decisionPackCli(options) { + if (options.help === true) return printDecisionPackHelp(); const login = options.login ?? process.env.LOOPOVER_LOGIN ?? process.env.GITHUB_LOGIN; if (!login) throw new Error("Pass --login or set LOOPOVER_LOGIN."); const payload = await getDecisionPackWithCache(login); @@ -2173,7 +2187,21 @@ async function decisionPackCli(options) { if (payload.cache?.rerunGuidance) process.stdout.write(`Rerun when: ${payload.cache.rerunGuidance}\n`); } +function printRepoDecisionHelp() { + process.stdout.write( + [ + "Usage: loopover-mcp repo-decision --login --repo owner/repo [--json]", + "", + "Fetch the cached (or freshly built) repo decision for a GitHub login and repo.", + "Mirrors the loopover_explain_repo_decision MCP tool. No source upload.", + "", + "Pass --json for machine-readable output.", + ].join("\n") + "\n", + ); +} + async function repoDecisionCli(options) { + if (options.help === true) return printRepoDecisionHelp(); const login = options.login ?? process.env.LOOPOVER_LOGIN ?? process.env.GITHUB_LOGIN; if (!login) throw new Error("Pass --login or set LOOPOVER_LOGIN."); const repoFullName = options.repo; diff --git a/test/unit/mcp-cli-packets.test.ts b/test/unit/mcp-cli-packets.test.ts index 1b16a5bd1d..0840585ad5 100644 --- a/test/unit/mcp-cli-packets.test.ts +++ b/test/unit/mcp-cli-packets.test.ts @@ -73,6 +73,20 @@ describe("loopover-mcp CLI — packets", () => { }); }); + it("prints decision-pack help without requiring --login or making a network call", () => { + const help = run(["decision-pack", "--help"]); + expect(help).toMatch(/Usage: loopover-mcp decision-pack/); + expect(help).toMatch(/loopover_get_decision_pack/); + expect(help).toMatch(/contributor decision pack/); + }); + + it("prints repo-decision help without requiring --login/--repo or making a network call", () => { + const help = run(["repo-decision", "--help"]); + expect(help).toMatch(/Usage: loopover-mcp repo-decision/); + expect(help).toMatch(/loopover_explain_repo_decision/); + expect(help).toMatch(/repo decision/); + }); + it("ignores incompatible decision-pack cache entries and clears cache entries on request", async () => { tempDir = mkdtempSync(join(tmpdir(), "loopover-cli-")); const url = await startFixtureServer();