Skip to content

feat(mcp): compute loopover_lint_pr_text in-process from the shared engine - #6308

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
nghetienhiep:fix/issue-6268
Jul 16, 2026
Merged

feat(mcp): compute loopover_lint_pr_text in-process from the shared engine#6308
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
nghetienhiep:fix/issue-6268

Conversation

@nghetienhiep

Copy link
Copy Markdown
Contributor

What

Make the local MCP server's loopover_lint_pr_text tool compute its result in-process from
@loopover/engine, matching the remote server's existing in-process behavior, so PR-text lint works
fully offline instead of proxying over HTTP (apiPost("/v1/lint/pr-text", …)).

Why

buildPrTextLint's canonical logic lived in packages/loopover-engine/src/signals/engine.ts, which is
excluded from the engine package's tsc emit (it carries host-bound ../../../../src/** imports), so it
was never in the published dist/ — the local package could not import it and fell back to an HTTP proxy.

How

  • Extracted buildPrTextLint + its types and private helpers into a new self-contained, buildable module
    packages/loopover-engine/src/signals/pr-text-lint.ts. It reuses the already-extracted shared rubric
    (GENERIC_COMMIT_PATTERN / hasClearNoIssueRationale from signals/slop.ts, tokenize from
    signals/predicted-gate-engine.ts, hasValidationNote, sanitizePublicComment, nowIso) so there is
    one definition, not a hand-kept mirror.
  • signals/engine.ts now re-exports from that module, so the API route and the remote MCP server keep
    their ../signals/engine import path and behavior byte-for-byte unchanged.
  • Exposed it from the engine barrel (@loopover/engine).
  • Bumped packages/loopover-mcp's @loopover/engine dependency from ^1.0.0 (stale — resolved the
    registry 1.0.0, which predates this export) to ^3.0.0, so it links the workspace engine exactly like
    packages/loopover-miner already does. Updated the tool handler to call buildPrTextLint(input)
    directly and refreshed its description ("Computed in-process; … no API round-trip").

Testing

  • New test/unit/mcp-lint-pr-text.test.ts: drives the real stdio server with an unreachable
    LOOPOVER_API_URL + tight timeout, so any regression back to an HTTP proxy would fail — proving the tool
    runs fully offline.
  • Existing test/unit/pr-text-lint.test.ts (via the signals/engine re-export) covers the moved module at
    100% statements/branches/functions/lines.
  • npm run typecheck, npm run engine-parity:drift-check, npm run test:engine-parity, engine package
    tests (566), npm run build:mcp, npm run test:mcp-pack, npm run docs:drift-check,
    npm run command-reference:check, npm audit --audit-level=moderate — all green.

Closes #6268

@nghetienhiep
nghetienhiep requested a review from JSONbored as a code owner July 16, 2026 00:44
@superagent-security

Copy link
Copy Markdown
Contributor

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

…ngine

The local MCP server's loopover_lint_pr_text proxied over HTTP
(apiPost("/v1/lint/pr-text", …)) because buildPrTextLint lived in the
host-bound signals/engine.ts, which is excluded from @loopover/engine's tsc
emit and so never reached the published dist/.

Extract buildPrTextLint and its types into a self-contained, buildable
signals/pr-text-lint.ts that reuses the already-extracted shared rubric
(GENERIC_COMMIT_PATTERN/hasClearNoIssueRationale from slop.ts, tokenize from
predicted-gate-engine.ts) so there is one definition, not a mirror.
signals/engine.ts re-exports it, keeping the API route and remote MCP server
unchanged, and the engine barrel now exposes it.

Bump loopover-mcp's @loopover/engine dependency from ^1.0.0 (which resolved
the stale registry 1.0.0 predating this export) to ^3.0.0 so it links the
workspace engine like loopover-miner already does, then call buildPrTextLint
directly in the tool handler. A user running the local MCP server can now lint
PR text fully offline, matching the remote server's in-process behavior.

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

loopover-orb Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-16 01:10:25 UTC

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

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This extracts `buildPrTextLint` and its private helpers out of the host-bound `signals/engine.ts` into a new buildable module `signals/pr-text-lint.ts`, re-exports it from `engine.ts` for byte-identical behavior on existing consumers, exposes it from the `@​loopover/engine` barrel, and switches the local MCP tool to call it directly instead of proxying over HTTP. The bump of `loopover-mcp`'s engine dependency from `^1.0.0` to `^3.0.0` correctly matches `loopover-miner`'s existing workspace link, and the new stdio test drives the real server against an unreachable API URL, which genuinely proves the tool no longer needs network access. The only detail worth double-checking is that `GENERIC_COMMIT_PATTERN` is now imported into the new module from `signals/slop.ts` rather than from the deleted local copy in `engine.ts` — the PR description frames this as removing a hand-kept mirror rather than the sole source, which is consistent with the diff.

Nits — 5 non-blocking
  • engine.ts:4829 — confirm no other module still imports `GENERIC_COMMIT_PATTERN` directly from `./engine.js` now that its local definition there is deleted (the diff's own removed comment claimed it was shared with the slop signal via this export).
  • pr-text-lint.ts's JSDoc block at the top is fairly long (12 lines) largely restating the PR description; consider trimming to what a future reader needs, not the extraction history.
  • test/unit/mcp-lint-pr-text.test.ts relies on a hardcoded `LOOPOVER_API_TIMEOUT_MS: 400` and an unreachable `127.0.0.1:1` address — mention in a comment (already partially done) that this is intentionally unreachable, not just slow, so a future reader doesn't 'fix' the timeout.
  • Add a one-line unit test in test/unit/pr-text-lint.test.ts (if not already covering it) for the score/verdict rank-disagree case called out in the PrTextLintReport.score doc comment, since that's a subtle enough behavior to regress silently.
  • Double check package-lock.json fully removes the stale nested `packages/loopover-mcp/node_modules/@​loopover/engine@​1.0.0` entry with no dangling references elsewhere in the lockfile.

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 #6268
Related work ⚠️ 2 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: 112 registered-repo PR(s), 64 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor nghetienhiep; Gittensor profile; 112 PR(s), 0 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The PR extracts buildPrTextLint into a buildable, host-import-free module (pr-text-lint.ts), exports it from the @​loopover/engine barrel, and updates loopover-mcp.js's tool handler to call buildPrTextLint directly instead of apiPost, while engine.ts keeps re-exporting it so the remote server's behavior is unchanged. It also bumps the workspace dependency to link the real engine package and adds a

Review context
  • Author: nghetienhiep
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 112 PR(s), 0 issue(s).
  • Related work: Titles/paths share 14 meaningful terms. (issue #6268, issue #6267)
  • Related work: Titles/paths share 10 meaningful terms. (issue #6268, issue #6269)
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 <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> 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://gittensory.aethereal.dev/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
Contributor

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 7c81b73 into JSONbored:main Jul 16, 2026
14 checks passed
loopover-orb Bot pushed a commit that referenced this pull request Jul 16, 2026
…d engine (#6329)

Make the local MCP server's loopover_check_slop_risk tool compute its result in-process from
@loopover/engine, matching the remote server's existing in-process behavior, so slop-risk
self-checks work fully offline instead of proxying over HTTP (apiPost("/v1/lint/slop-risk", …)).

buildSlopAssessment's canonical logic already lives in packages/loopover-engine/src/signals/slop.ts,
and both the remote MCP server (src/mcp/server.ts checkSlopRisk) and the API route
(/v1/lint/slop-risk) call it directly. The only blocker for the local CLI was that
@loopover/engine's exports map did not expose ./signals/slop.

- Add a ./signals/slop entry to packages/loopover-engine/package.json's exports map, pointing at
  the same built module the barrel and the src/ re-export shim already consume.
- Update loopover_check_slop_risk's handler to call buildSlopAssessment(input) directly and wrap
  it as { ...assessment, rubric: SLOP_RUBRIC_MARKDOWN } — byte-for-byte the shape the
  /v1/lint/slop-risk route returned, so the tool's documented output (slopRisk, band, findings,
  rubric) is unchanged, only computed locally. Refresh its description accordingly.
- Leave the remote server, the API route, the slop-risk CLI subcommand, and the review-pr
  composition untouched, mirroring #6308's identical change for loopover_lint_pr_text.

Closes #6267

Co-authored-by: nghetienhiep <13849419+nghetienhiep@users.noreply.github.com>
@github-actions github-actions Bot mentioned this pull request Jul 16, 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.

feat(mcp): make loopover_lint_pr_text work offline in the local CLI by exposing the shared engine.ts logic

1 participant