Skip to content

feat(mcp): add gittensory_explain_gate_disposition tool (#2234) - #4220

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
nickmopen:feat/mcp-explain-gate-disposition
Jul 8, 2026
Merged

feat(mcp): add gittensory_explain_gate_disposition tool (#2234)#4220
JSONbored merged 1 commit into
JSONbored:mainfrom
nickmopen:feat/mcp-explain-gate-disposition

Conversation

@nickmopen

Copy link
Copy Markdown
Contributor

Closes #2234.

gittensory_predict_gate returns a pass/fail verdict, but there's no tool for the structured per-rule reasons behind it. This adds a read-only companion — gittensory_explain_gate_disposition — that returns the itemized rule dispositions (which specific gate rules block vs advise, and why) from the repo's public .gittensory.yml only. No merge/close decision (that stays maintainer-only).

What's here

  • server.ts
    • Extracted computePredictedGateVerdict — shared by both tools so they run the identical deterministic prediction and can't diverge (no behavior change to predict_gate).
    • Pure buildGateDispositions(verdict) — maps blockers → block, warnings → advisory (blockers first); a read-only reshaping of what the predictor already computed, no new gate logic.
    • New gittensory_explain_gate_disposition tool reusing predictGateShape + a zod outputSchema for the {rule, status, reason} list.
  • Tests — pure buildGateDispositions (pass-all / one-blocker / multi-blocker), plus tool-level blocking and passing cases driven through the existing predict-gate harness; asserts the output stays public-safe.

Validation

Typecheck clean. Full suite (npm run test):

Test Files  596 passed | 2 skipped (598)
     Tests  12149 passed | 12 skipped   (0 failed)

Includes the existing gittensory_predict_gate test (confirms the shared-compute refactor is behavior-preserving).

gittensory_predict_gate returns a pass/fail verdict; this adds a read-only companion
tool that surfaces the STRUCTURED per-rule dispositions behind it — which specific gate
rules block vs advise, and why — from the repo's PUBLIC .gittensory.yml only. No
merge/close decision.

- server.ts: extract computePredictedGateVerdict (shared by both tools, so they can't
  diverge — no behavior change to predict_gate); pure buildGateDispositions(verdict)
  maps blockers→block, warnings→advisory (blockers first); new
  gittensory_explain_gate_disposition tool reusing predictGateShape + a zod
  outputSchema for the itemized {rule, status, reason} list.
- Tests: pure buildGateDispositions (pass-all/one-blocker/multi-blocker), plus
  tool-level blocking + passing cases via the predict-gate harness; asserts public-safe.

Verified: typecheck clean; full suite green (12149 passed, 0 failed).
@nickmopen
nickmopen requested a review from JSONbored as a code owner July 8, 2026 14:52
@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.76%. Comparing base (24d058a) to head (69cd8fd).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4220   +/-   ##
=======================================
  Coverage   93.75%   93.76%           
=======================================
  Files         389      389           
  Lines       36499    36511   +12     
  Branches    13376    13376           
=======================================
+ Hits        34221    34233   +12     
  Misses       1621     1621           
  Partials      657      657           
Files with missing lines Coverage Δ
src/mcp/server.ts 94.99% <100.00%> (+0.08%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

loopover-orb Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ Gittensory review result - approve/merge recommended

Review updated: 2026-07-08 19:01:01 UTC

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

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR extracts the shared `computePredictedGateVerdict` method used by both `predictGate` and the new `explainGateDisposition`, ensuring both tools run the identical deterministic prediction, then reshapes the verdict via a pure `buildGateDispositions` function into per-rule `{rule, status, reason}` entries. The refactor is behavior-preserving for `predictGate` (same return shape at the end of the method), and the new tool reuses existing auth/access checks (`requireContributorAccess`, `requireRepoAccess`) and the same public `.gittensory.yml` resolution path, so it doesn't introduce a new privilege or data-exposure surface beyond what `predictGate` already returns. Tests cover the pure mapping function's ordering (blockers-first) directly and exercise the tool end-to-end for both a blocking and a passing case via the existing predict-gate test harness.

Nits — 5 non-blocking
  • No tool-level (`explainGateDisposition`) test covers a mixed case with both a blocking and an advisory rule firing together — only the pure `buildGateDispositions` unit test exercises that combination (test/unit/mcp-explain-gate-disposition.test.ts).
  • The tool description and multiple inline comments repeat '(feat(mcp): add gittensory_explain_gate_disposition tool (deterministic dry-run gate reasons) #2234)' verbatim across src/mcp/server.ts, which is more issue-tracker noise than durable documentation and will go stale once the issue closes.
  • `buildGateDispositions`'s `Pick<PredictedGateVerdict, "blockers" | "warnings">` parameter type is good, but the function doesn't guard against `finding.detail` being empty/undefined for public-safety — worth a quick sanity check that `detail` is always populated for both blockers and warnings upstream.
  • Add an integration test where the manifest produces both a blocker and a warning (e.g. missing linked issue + a lint-level warning) to confirm the tool-level ordering and count fields (`blocking`/`advisory` counts in the summary) behave as unit-tested.
  • Consider extracting the repeated `(feat(mcp): add gittensory_explain_gate_disposition tool (deterministic dry-run gate reasons) #2234)` issue references into a single top-of-section comment rather than repeating it on every new symbol, per the existing file's commenting style.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #2234
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low 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: 160 registered-repo PR(s), 103 merged, 11 issue(s).
Contributor context ✅ Confirmed Gittensor contributor nickmopen; Gittensor profile; 160 PR(s), 11 issue(s).
Gate result ✅ Passing No configured blocker found.
Linked issue satisfaction

Addressed
The PR registers gittensory_explain_gate_disposition reusing predictGateShape, extracts a shared computePredictedGateVerdict so the two tools can't diverge, adds a pure buildGateDispositions mapper with a zod outputSchema exposing rule/status/reason, and includes tests covering pass-all, one-blocking-rule, and multi-blocker cases at both the unit and tool level.

Review context
  • Author: nickmopen
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: TypeScript, Python
  • Official Gittensor activity: 160 PR(s), 11 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
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.

🟩 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 Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@JSONbored
JSONbored merged commit 8eb55ae into JSONbored:main Jul 8, 2026
8 checks passed
JSONbored added a commit that referenced this pull request Jul 9, 2026
…ass (#4537)

reReviewStoredPullRequest / the direct pull_request webhook handler both
thread ONE shared LiveGithubFacts object through readiness,
maybePublishPrPublicSurface, and runAgentMaintenancePlanAndExecute -- but
the latter two independently force-refetched the same PR's mergeable_state
and CI aggregate live from GitHub, back to back, with no mutation between
the two reads. Adds reuseOrRefreshLiveMergeState/reuseOrRefreshLiveCiAggregate,
which reuse a value already populated by a FORCED write earlier in the same
pass instead of re-fetching. Deliberately not the existing cachedLiveMergeState/
cachedLiveCiAggregate variants: those fall through to the durable
cross-webhook cache on a request-local miss, which can replay an older
webhook's snapshot -- exactly what the disposition input's #4220 invariant
prohibits. Tracks which keys were populated by a forced (genuinely-live-
this-pass) write via new forcedMergeStateKeys/forcedCiAggregateKeys sets on
LiveGithubFacts, so a value written by the READINESS path's own
cache-preferring reader is never mistaken for a fresh one.

Closes #4498.
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. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

feat(mcp): add gittensory_explain_gate_disposition tool (deterministic dry-run gate reasons)

2 participants