Skip to content

feat(mcp): mirror loopover_monitor_open_prs to the stdio wrapper and CLI#6789

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
reyanthony062001-ops:feat/6732-monitor-open-prs-cli-v2
Jul 17, 2026
Merged

feat(mcp): mirror loopover_monitor_open_prs to the stdio wrapper and CLI#6789
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
reyanthony062001-ops:feat/6732-monitor-open-prs-cli-v2

Conversation

@reyanthony062001-ops

Copy link
Copy Markdown
Contributor

Closes #6732. Supersedes #6781, which was auto-closed on a CI failure that came from its base, not its diff — see the note at the end.

loopover_monitor_open_prs (src/mcp/server.ts) and GET /v1/contributors/:login/open-pr-monitor (src/api/routes.ts, gated by requireContributorAccess) already do this work, but the stdio wrapper registered no matching tool and the CLI had no command — so a contributor could not review their own open PRs from the terminal. This mirrors the existing surface; it adds no route, no dependency, and no source upload.

What changed

  • registerStdioTool("loopover_monitor_open_prs", ...) in packages/loopover-mcp/bin/loopover-mcp.js, proxying the existing route via apiGet and reusing loginShape. Its descriptor carries the same description the MCP tool already publishes, under category: "discovery" alongside loopover_get_decision_pack. Tool count 63 → 64.
  • loopover-mcp monitor-open-prs --login <github-login> [--json], resolving the login from --login / LOOPOVER_LOGIN / GITHUB_LOGIN exactly as decisionPackCli does, registered in CLI_COMMAND_SPEC (so shell completion and suggestCommand's "did you mean" pick it up) and listed in --help + the Environment block.
  • Summary parity: the CLI prints the API's own summary rather than composing a second sentence, so the two mirrored surfaces cannot drift apart for one payload. A test pins that.
  • #6261 sanitization: the plain-text path passes API-chosen text through sanitizePlainTextTerminalOutput — the API composes summary/guidance and echoes PR titles back from third-party repos, so a hostile string must not be able to repaint the terminal. --json deliberately stays raw, since JSON.stringify escapes U+001B and callers parse that contract.

Tests

New test/unit/mcp-cli-monitor-open-prs.test.ts (8 tests, in the mcp-cli-* style): tool registration, route+method proxied, output parity between the mirrored surfaces for identical input, plain-text rendering, login resolution via both env vars, the shared login-required failure, ANSI sanitization (plain-text stripped / --json preserved), and --help/completion documentation. The fixture route + openPrMonitorFixture() mirror the real ContributorOpenPrMonitor shape.

Each new test was verified to fail against the un-mirrored bin before passing, and the sanitization test was verified to fail against an un-sanitized build — they catch the defects they describe rather than merely passing.

Validation

Rebased onto ab84f78 — the first green main after #6785 fixed the selfhost-grafana-dashboard assertions.

  • Full npx vitest run backend suite on this base: green, including test/unit/selfhost-grafana-dashboard.test.ts (30/30), the suite that failed on feat(mcp): mirror loopover_monitor_open_prs to the stdio wrapper and CLI #6781's base
  • npm run typecheck: clean · npm run build:mcp + npm run test:mcp-pack: pass
  • loopover-mcp tools --json reports 64, matching the bumped assertion in mcp-tool-rename-aliases.test.ts

Why #6781 was closed, and what changed here

#6781 carried this same diff. Its validate-tests (6) shard failed on test/unit/selfhost-grafana-dashboard.test.ts — six assertions in a file this diff does not touch. That break arrived with #6779 (b440c84) at 05:29Z and left main's own ci.yml red (42cca18, 67af510); #6781 was branched from 67af510 and inherited it. #6785 has since fixed those assertions and main is green again at ab84f78, which is this PR's base — so the shard-6 failure is gone rather than argued away.

The only change from #6781 is the base. The diff is byte-identical.

Note on the issue text

The issue specifies the assertion bump as 63 → 64, which is exactly right; this PR does that. It also asks for 99% patch coverage on "the new route/tool/CLI code" — worth flagging that the route and MCP tool already exist and are unchanged here, and packages/loopover-mcp/bin/** is outside the coverage include in vitest.config.ts, so this diff adds no Codecov-measured lines (codecov/patch passed on #6781 for that reason). The behaviour is covered by the unit tests above regardless.

The MCP tool loopover_monitor_open_prs and GET /v1/contributors/:login/open-pr-monitor
already served this, but the stdio wrapper registered no matching tool and the CLI had no
command, so a contributor could not review their own open PRs from the terminal.

- register loopover_monitor_open_prs in loopover-mcp.js, proxying the existing route
  (category: discovery, alongside loopover_get_decision_pack), taking the tool count 63 -> 64
- add `loopover-mcp monitor-open-prs --login <login> [--json]`, resolving the login from
  --login / LOOPOVER_LOGIN / GITHUB_LOGIN exactly as decisionPackCli does
- reuse the API's own summary so the CLI and the MCP tool never drift into two sentences
- sanitize API-chosen text on the plain-text path per JSONbored#6261 (the API composes the summary
  and guidance and echoes third-party PR titles); --json stays raw, as JSON.stringify escapes
  U+001B and callers parse that contract

No new dependency, no route change, no source upload.
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.63%. Comparing base (ab84f78) to head (77f3122).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6789   +/-   ##
=======================================
  Coverage   93.63%   93.63%           
=======================================
  Files         683      683           
  Lines       68148    68148           
  Branches    18703    18703           
=======================================
  Hits        63812    63812           
  Misses       3350     3350           
  Partials      986      986           
Flag Coverage Δ
shard-1 43.66% <ø> (ø)
shard-2 36.83% <ø> (ø)
shard-3 32.74% <ø> (ø)
shard-4 34.67% <ø> (ø)
shard-5 31.00% <ø> (ø)
shard-6 45.67% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 17, 2026
@loopover-orb

loopover-orb Bot commented Jul 17, 2026

Copy link
Copy Markdown

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-17 06:42:58 UTC

6 files · 1 AI reviewer · no blockers · readiness 82/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR mirrors the existing loopover_monitor_open_prs API/MCP-tool surface into the stdio wrapper and CLI, following the established pattern used for decision-pack/repo-decision: tool registration, CLI command spec, login resolution via --login/LOOPOVER_LOGIN/GITHUB_LOGIN, ANSI-sanitized plain-text output vs raw --json, and a summary-parity contract so the CLI doesn't compose a second sentence. The diff is well-tested (8 new tests covering registration, route proxying, mirror parity, ANSI stripping, and help/completion text) and consistent with prior PRs in this series (tool count 63→64 bumped correctly across all three counting tests). Code is correctly wired: getOpenPrMonitor hits the right route, openPrMonitorToolSummary is shared between the stdio tool and CLI, and sanitizePlainTextTerminalOutput is applied to every API-chosen string on the plain-text path while --json stays raw.

Nits — 5 non-blocking
  • packages/loopover-mcp/bin/loopover-mcp.js: monitorOpenPrsCli's nested loops (guidance, pullRequests, nextSteps) push its cyclomatic complexity to ~12 per the external brief; consider extracting a small `printOpenPr(pr)` helper for readability, though it's not a correctness issue.
  • The PR description says 'Closes CLI mirror for loopover_monitor_open_prs #6732' but doesn't show the actual issue text — worth double-checking the CLI flag name/shape (--login, --json) matches whatever the issue requested.
  • test/unit/mcp-cli-monitor-open-prs.test.ts: the ANSI-stripping test asserts `plain).not.toContain("")` which is a slightly fragile way to check for the absence of the escape character — an explicit regex like `/\x1b/` would be clearer intent, though this is purely stylistic.
  • Consider factoring the repeated per-PR printing block in monitorOpenPrsCli into a helper to reduce the flagged complexity and ease future changes to the output format.
  • If not already covered elsewhere, add a brief note in README or --help about what 'cleanupFirst'/'pendingScenarios' fields mean for --json consumers, since they're part of the payload contract now surfaced via CLI.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #6732
Related work ⚠️ 3 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 37 registered-repo PR(s), 23 merged, 1 issue(s).
Contributor context ✅ Confirmed Gittensor contributor reyanthony062001-ops; Gittensor profile; 37 PR(s), 1 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The PR adds registerStdioTool("loopover_monitor_open_prs", ...) proxying the existing GET /v1/contributors/:login/open-pr-monitor route, adds a monitor-open-prs CLI command resolving login from --login/LOOPOVER_LOGIN/GITHUB_LOGIN matching decisionPackCli, supports --json, updates the tool-count assertion from 63 to 64, and includes a new mcp-cli-monitor-open-prs.test.ts with an explicit output-par

Review context
  • Author: reyanthony062001-ops
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Cuda, HTML, JavaScript, Python, TypeScript
  • Official Gittensor activity: 37 PR(s), 1 issue(s).
  • Related work: Titles/paths share 7 meaningful terms. (issue #6732, issue #6747)
  • Related work: Titles/paths share 7 meaningful terms. (issue #6732, issue #6741)
  • Related work: Titles/paths share 8 meaningful terms. (issue #6732, issue #6751)
  • Additional title-only matches omitted; title-only overlap does not block.
Contributor next steps
  • Start here: Review top overlaps.
  • Then work through the remaining 2 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 544cb31 into JSONbored:main Jul 17, 2026
16 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 17, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI mirror for loopover_monitor_open_prs

1 participant