Context
packages/loopover-miner/lib/calibration-cli.js (loopover-miner calibration [--json], #4849) already builds a read-only report that joins the miner's own local prediction ledger (prediction-ledger.js) with its locally-observed PR outcomes (event-ledger.js's pr_outcome events) via the pure buildCalibrationReport composer, producing per-project merge/close precision. It is strictly local and offline — no network call, no mutation.
This is distinct from the ORB-side loopover_get_outcome_calibration MCP tool already registered in src/mcp/server.ts (line ~1660): that tool is maintainer-authenticated and reads slop-band/recommendation calibration from the hosted review database (D1) for a {owner, repo} the caller has access to. The miner-local calibration report reads a different data source (the miner's own on-disk SQLite ledgers) and needs no maintainer auth or network round-trip at all — a contributor running a self-hosted AMS miner has no way to ask "how accurate have my own gate predictions been?" via MCP today, only via the CLI.
The AMS miner's own stdio MCP server, packages/loopover-miner/bin/loopover-miner-mcp.js, already exposes exactly this shape of capability for sibling local stores — e.g. loopover_miner_get_governor_decisions (read-only projection over governor-ledger.js) and loopover_miner_status (wraps status.js's collectStatus/runDoctorChecks). Calibration has no equivalent tool despite following the identical "thin read-only wrapper around an existing pure aggregator" pattern (see the header comment in calibration-cli.js itself, and the file's own doc comment cross-referencing event-ledger-cli.js's runLedgerMetrics and queue-cli.js's runQueueMetrics as siblings).
Requirements
- Add a new tool
loopover_miner_get_calibration_report to packages/loopover-miner/bin/loopover-miner-mcp.js, registered via server.registerTool(...) alongside the existing nine tools (loopover_miner_ping, loopover_miner_get_portfolio_dashboard, loopover_miner_list_claims, loopover_miner_get_audit_feed, loopover_miner_get_run_state, loopover_miner_list_plans, loopover_miner_get_plan, loopover_miner_get_governor_decisions, loopover_miner_status).
- Input schema: no arguments (mirrors
loopover_miner_get_portfolio_dashboard and loopover_miner_status, which also take {} — the underlying CLI command takes no positional/filter args either).
- Implementation: open the prediction ledger and event ledger (respecting the existing
options.initPredictionLedger / options.initEventLedger injection seams already used by the other tools for testability), call the SAME toPredictionRecords / toOutcomeRecords mapping helpers and buildCalibrationReport composer that calibration-cli.js already uses — do not reimplement the join. Close whichever store(s) this tool itself opened, exactly like the existing tools' finally blocks.
- Description text must state plainly that this is local-only, read-only, and reuses the existing CLI's report builder with no new join/scoring logic — follow the phrasing convention already used by the other 9 tool descriptions (e.g.
loopover_miner_get_governor_decisions's "no new logic, no mutation").
- Output: the same JSON shape
buildCalibrationReport already returns (an object with hasSignal and, when true, per-project rows), passed through unchanged — do not reshape it.
Deliverables
Test Coverage Requirements
99%+ Codecov patch coverage on every changed line and branch in packages/loopover-miner/bin/loopover-miner-mcp.js — both the has-signal and no-signal branches of the underlying buildCalibrationReport result must be exercised by the new test(s), plus the store-ownership (opens-and-closes-only-what-it-opened) invariant the sibling tools already test for.
Expected Outcome
An MCP client connected to the gittensory-miner stdio server (e.g. npx @loopover/miner mcp or the packaged loopover-miner-mcp bin) can call loopover_miner_get_calibration_report and get the same per-project merge/close prediction-accuracy report that loopover-miner calibration --json prints today, without shelling out to the CLI.
Links & Resources
Context
packages/loopover-miner/lib/calibration-cli.js(loopover-miner calibration [--json], #4849) already builds a read-only report that joins the miner's own local prediction ledger (prediction-ledger.js) with its locally-observed PR outcomes (event-ledger.js'spr_outcomeevents) via the purebuildCalibrationReportcomposer, producing per-project merge/close precision. It is strictly local and offline — no network call, no mutation.This is distinct from the ORB-side
loopover_get_outcome_calibrationMCP tool already registered insrc/mcp/server.ts(line ~1660): that tool is maintainer-authenticated and reads slop-band/recommendation calibration from the hosted review database (D1) for a{owner, repo}the caller has access to. The miner-local calibration report reads a different data source (the miner's own on-disk SQLite ledgers) and needs no maintainer auth or network round-trip at all — a contributor running a self-hosted AMS miner has no way to ask "how accurate have my own gate predictions been?" via MCP today, only via the CLI.The AMS miner's own stdio MCP server,
packages/loopover-miner/bin/loopover-miner-mcp.js, already exposes exactly this shape of capability for sibling local stores — e.g.loopover_miner_get_governor_decisions(read-only projection overgovernor-ledger.js) andloopover_miner_status(wrapsstatus.js'scollectStatus/runDoctorChecks). Calibration has no equivalent tool despite following the identical "thin read-only wrapper around an existing pure aggregator" pattern (see the header comment incalibration-cli.jsitself, and the file's own doc comment cross-referencingevent-ledger-cli.js'srunLedgerMetricsandqueue-cli.js'srunQueueMetricsas siblings).Requirements
loopover_miner_get_calibration_reporttopackages/loopover-miner/bin/loopover-miner-mcp.js, registered viaserver.registerTool(...)alongside the existing nine tools (loopover_miner_ping,loopover_miner_get_portfolio_dashboard,loopover_miner_list_claims,loopover_miner_get_audit_feed,loopover_miner_get_run_state,loopover_miner_list_plans,loopover_miner_get_plan,loopover_miner_get_governor_decisions,loopover_miner_status).loopover_miner_get_portfolio_dashboardandloopover_miner_status, which also take{}— the underlying CLI command takes no positional/filter args either).options.initPredictionLedger/options.initEventLedgerinjection seams already used by the other tools for testability), call the SAMEtoPredictionRecords/toOutcomeRecordsmapping helpers andbuildCalibrationReportcomposer thatcalibration-cli.jsalready uses — do not reimplement the join. Close whichever store(s) this tool itself opened, exactly like the existing tools'finallyblocks.loopover_miner_get_governor_decisions's "no new logic, no mutation").buildCalibrationReportalready returns (an object withhasSignaland, when true, per-projectrows), passed through unchanged — do not reshape it.Deliverables
loopover_miner_get_calibration_reporttool registration inpackages/loopover-miner/bin/loopover-miner-mcp.js, with anoptions.initPredictionLedger/options.initEventLedgerinjection seam matching the file's existing conventionpr_outcome), the no-signal case (hasSignal: false, matchingcalibration-cli.js's own "no decided predictions yet" branch), and that the tool opens/closes only the stores it itself opened (mirroring the existing tests forloopover_miner_get_governor_decisions)createMinerMcpServerthat currently documents all 9 tools with their issue numbers)Test Coverage Requirements
99%+ Codecov patch coverage on every changed line and branch in
packages/loopover-miner/bin/loopover-miner-mcp.js— both the has-signal and no-signal branches of the underlyingbuildCalibrationReportresult must be exercised by the new test(s), plus the store-ownership (opens-and-closes-only-what-it-opened) invariant the sibling tools already test for.Expected Outcome
An MCP client connected to the
gittensory-minerstdio server (e.g.npx @loopover/miner mcpor the packagedloopover-miner-mcpbin) can callloopover_miner_get_calibration_reportand get the same per-project merge/close prediction-accuracy report thatloopover-miner calibration --jsonprints today, without shelling out to the CLI.Links & Resources
loopover_miner_get_governor_decisionsinpackages/loopover-miner/bin/loopover-miner-mcp.js(read-only wrapper, no new logic, explicit store-ownershipfinallypattern)packages/loopover-miner/lib/calibration-cli.js(runCalibrationCli,toPredictionRecords,toOutcomeRecords),buildCalibrationReportfrompackages/loopover-miner/lib/calibration.jsloopover_get_outcome_calibrationinsrc/mcp/server.ts— that is the maintainer-authenticated, hosted-review-DB calibration tool; this issue is the miner-local, offline counterpartpayload_jsonby construction #5159/Expose AMS per-repo run-state as a read-only MCP tool (gittensory_miner_get_run_state) #5160/Expose AMS's persisted plan-store as read-only MCP tools (gittensory_miner_list_plans/gittensory_miner_get_plan) #5161 (the sibling miner-mcp tool issues this follows the pattern of)