feat(mcp): wire gittensory_feasibility_gate's claimStatus to the local claim ledger (#5157)#5374
Conversation
…l claim ledger (JSONbored#5157) gittensory_feasibility_gate took claimStatus as a purely caller-supplied string, never actually connected to real local claim state, even though packages/gittensory-miner/lib/claim-ledger.js already tracks it. Adds optional repoFullName/issueNumber inputs. When both are supplied and a local gittensory-miner install's claim ledger DB file exists, claimStatus is now read from that ledger (an active claim on the exact issue -> "claimed", otherwise "unclaimed") instead of trusting the caller-supplied value. The DB file's existence is checked BEFORE opening anything, so this advisory-only tool never creates the ledger as a side effect -- it stays strictly read-only, never calls recordClaim/releaseClaim/expireClaim, and never gains any ability to block, cancel, or override a claim or attempt; real claim-conflict authority remains entirely with the maintainer-only path. Falls back to today's caller-supplied-string behavior unchanged when repo/issue are omitted, the ledger file doesn't exist, or gittensory-miner isn't resolvable at all. The feasibility calculator's own decision logic is untouched -- this only changes where claimStatus is sourced from.
…ad of silently trusting the caller (JSONbored#5157) resolveLedgerClaimStatus's catch block previously swallowed every error from opening/querying the ledger, not just "package not found" -- so a real local install whose ledger DB file exists but is corrupt, locked, or unreadable would silently fall back to a caller-supplied claimStatus that might contradict the (unreadable) ground truth. Narrows the fallback: module-resolution failure or a missing DB file still return null (fall back to the caller-supplied value -- correct, since there's genuinely nothing local to check). A DB file that exists but fails to open/query now returns the existing "unknown" claimStatus value instead, which the calculator already treats as a neutral signal -- honest about the read failure rather than guessing.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5374 +/- ##
==========================================
- Coverage 94.41% 94.37% -0.04%
==========================================
Files 551 551
Lines 44168 44168
Branches 14632 14632
==========================================
- Hits 41702 41685 -17
- Misses 1791 1808 +17
Partials 675 675
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-12 15:37:13 UTC
✅ Suggested Action - Approve/Merge
Review summary Blockers
Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands 🟩 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.
|
|
An AI reviewer flagged a likely defect, but its confidence was below this repository's configured close-confidence floor, so this is held for a maintainer to confirm instead of closing automatically. Resolve the flagged defect (see the review notes), or ask a maintainer to override. |
JSONbored
left a comment
There was a problem hiding this comment.
Closing:
packages/gittensory-mcp/bin/gittensory-mcp.js:240 opens the ledger with openClaimLedger(dbPath) after only checking existsSync(dbPath), so an existing empty or uninitialized SQLite file can still be schema-initialized/written by this advisory-only path; change this to a genuinely read-only open/query path or first verify the ledger schema exists without running the ledger initializer.
Summary
gittensory_feasibility_gateinpackages/gittensory-mcp/bin/gittensory-mcp.jstookclaimStatusas a purely caller-supplied string -- the pure feasibility calculator was never actually connected to real local claim state, even thoughpackages/gittensory-miner/lib/claim-ledger.jsalready tracks it.repoFullName/issueNumberinputs tofeasibilityGateShape. When both are supplied AND a localgittensory-minerinstall's claim ledger DB file exists,claimStatusis now read from that ledger (an active claim on the exact issue ->"claimed", otherwise"unclaimed") instead of trusting the caller-supplied value.existsSyncbefore opening anything, so this advisory-only tool never creates the ledger as a side effect. It never callsrecordClaim/releaseClaim/expireClaim, and never gains any ability to block, cancel, or override a claim or attempt -- real claim-conflict resolution authority stays entirely with the maintainer-only path (Wire claim-conflict resolution end-to-end #4848), unaffected.repoFullName/issueNumberare omitted, the ledger DB file doesn't exist (no local install detected), or@jsonbored/gittensory-minerisn't resolvable at all.claimStatus: "unknown"value instead of silently falling back to a caller-supplied string that might contradict ground truth we know exists but can't currently read.buildFeasibilityVerdict) is completely untouched -- this diff only changes whereclaimStatusis sourced from.Resubmission note
This is a resubmission of #5361, which the review gate held/closed on a legitimate finding (not a false positive this time): the original
catchblock swallowed every error from opening/querying the ledger, not just "package not found" -- so a corrupt or locked ledger DB file would have silently fallen back to a possibly-wrong caller-suppliedclaimStatus. Fixed by narrowing the fallback to genuinely "nothing to check" cases (missing inputs, missing DB file, unresolvable package) and reporting"unknown"-- an existing, neutral claimStatus value the calculator already understands -- for an existing-but-unreadable ledger, with a new regression test covering exactly that discriminating case.Test plan
npx vitest run test/unit/mcp-feasibility-gate.test.ts-- 13/13 passing (6 pre-existing + 7 new), spawning the real MCP server subprocess via stdio and pointingGITTENSORY_MINER_CLAIM_LEDGER_DBat fixture SQLite files built withopenClaimLedger/claimIssuefrom the miner package directly. Covers: ledger-backed"claimed"overriding a contradicting caller-supplied value, ledger-backed"unclaimed"overriding a contradicting caller-supplied value, fallback when the DB file doesn't exist, the new regression:"unknown"(not a silent caller-supplied fallback) when the DB file exists but is corrupt, fallback whenrepoFullName/issueNumberare omitted, a no-write invariant, and the updated tool description.npm run typecheck-- clean.npm run build:mcp-- clean.npm run docs:drift-check-- clean.gh[pousr]_/github_pat_/sk-/gts_/AKIA/private-key/TOKEN=/SECRET=patterns -- zero matches.packages/gittensory-mcp/**currently sits outside vitest'scoverage.includeglob, socodecov/patchcannot measure this change yet -- treating the tests above as the enforced house standard regardless. The outercatchfor "gittensory-miner genuinely unresolvable" stays/* v8 ignore */, unreproducible in this monorepo's workspace-hoisted test environment.npm run test:coveragelocally (shared/resource-contended machine); relying on the targeted test run above plusnpm run typecheck/build:mcp.Fixes #5157.