⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
#9525 made withMinerToolErrorHandling
(packages/loopover-miner/bin/loopover-miner-mcp.ts:114-132) the miner server's dispatch-telemetry
chokepoint. Its own doc comment states the design contract:
#9525: the tool name, so this same wrapper doubles as the miner's dispatch-telemetry chokepoint.
REQUIRED -- every registration passes it, and leaving it optional would have made
"instrumented" a property of each call site rather than of the wrapper.
Ten of the eleven tools honour that. loopover_miner_ping does not — its registration passes a bare
async () => minerToolResult(MINER_PING_STATUS) handler that never calls the wrapper, and therefore
never calls recordMinerDispatchTelemetry
(packages/loopover-miner/lib/mcp-dispatch-telemetry.ts:34). No usage_event, no $mcp_tool_call.
The tool this omits is the health check — the one an operator's monitoring hits on a loop and the one
whose call volume is the cheapest signal that the miner MCP server is alive and being used at all. A
usage_event breakdown by tool on the miner surface silently reports zero pings forever.
Nothing catches it: the miner server has no structural test asserting every registration is wrapped
(contrast test/unit/mcp-dispatch-telemetry-sink.test.ts:146, which relies on the remote server's
register wrapper being the single chokepoint), and test/unit/miner-mcp-scaffold.test.ts:104-117
only asserts ping's payload.
Requirements
loopover_miner_ping's handler routes through withMinerToolErrorHandling, exactly like the
other ten, so it emits the same two events. The tool's returned content text and
structuredContent must be byte-identical to today's (MINER_PING_STATUS), asserted by the
existing invariant tests.
- A structural test that cannot be satisfied by hand-listing tool names: it introspects
packages/loopover-miner/bin/loopover-miner-mcp.ts's source and fails if any
server.registerTool( call's handler body does not reach withMinerToolErrorHandling. Model it
on the repo's existing structural rules (test/unit/no-direct-octokit.test.ts).
- A behavioural test that connects to the miner server with a stubbed dispatch-telemetry recorder,
calls every tool name from listToolDefinitions({ locality: ["miner"] }), and asserts each one
produced exactly one telemetry record with the matching tool name. Deriving the name list from
the registry (not a literal array) is required — test/unit/miner-mcp-scaffold.test.ts:91-102 is
the precedent.
⚠️ Required pattern: withMinerToolErrorHandling(run, toolName) at
packages/loopover-miner/bin/loopover-miner-mcp.ts:114-132, used by the other ten registrations.
Adding a bespoke recordMinerDispatchTelemetry(...) call inline in the ping handler, or adding a
second wrapper just for tools that cannot fail, does NOT satisfy this issue — the point is that
"instrumented" is a property of the wrapper, not of the call site.
Deliverables
All Deliverables above are required in a single PR. A PR that satisfies only some of them — for
example wrapping the ping handler without adding the structural test, so the next tool added can
repeat the omission — does not resolve this issue.
Test Coverage Requirements
99%+ Codecov patch coverage, branch-counted, applies: packages/loopover-miner/bin/**/*.ts is
explicitly listed in coverage.include (vitest.config.ts:69-77, which calls
bin/loopover-miner-mcp.ts out by name as "genuinely unit-coverable"). Both the success and the
throw arm of the wrapper as reached from the ping registration need a test, and a named regression
test must assert loopover_miner_ping emits a dispatch telemetry record.
Expected Outcome
All eleven miner tools emit usage_event and $mcp_tool_call; the miner surface's telemetry is
complete rather than 10 of 11; and a future twelfth tool registered without the wrapper fails CI
instead of shipping uninstrumented.
Links & Resources
Context
#9525 made
withMinerToolErrorHandling(
packages/loopover-miner/bin/loopover-miner-mcp.ts:114-132) the miner server's dispatch-telemetrychokepoint. Its own doc comment states the design contract:
Ten of the eleven tools honour that.
loopover_miner_pingdoes not — its registration passes a bareasync () => minerToolResult(MINER_PING_STATUS)handler that never calls the wrapper, and thereforenever calls
recordMinerDispatchTelemetry(
packages/loopover-miner/lib/mcp-dispatch-telemetry.ts:34). Nousage_event, no$mcp_tool_call.The tool this omits is the health check — the one an operator's monitoring hits on a loop and the one
whose call volume is the cheapest signal that the miner MCP server is alive and being used at all. A
usage_eventbreakdown bytoolon theminersurface silently reports zero pings forever.Nothing catches it: the miner server has no structural test asserting every registration is wrapped
(contrast
test/unit/mcp-dispatch-telemetry-sink.test.ts:146, which relies on the remote server'sregisterwrapper being the single chokepoint), andtest/unit/miner-mcp-scaffold.test.ts:104-117only asserts ping's payload.
Requirements
loopover_miner_ping's handler routes throughwithMinerToolErrorHandling, exactly like theother ten, so it emits the same two events. The tool's returned
contenttext andstructuredContentmust be byte-identical to today's (MINER_PING_STATUS), asserted by theexisting invariant tests.
packages/loopover-miner/bin/loopover-miner-mcp.ts's source and fails if anyserver.registerTool(call's handler body does not reachwithMinerToolErrorHandling. Model iton the repo's existing structural rules (
test/unit/no-direct-octokit.test.ts).calls every tool name from
listToolDefinitions({ locality: ["miner"] }), and asserts each oneproduced exactly one telemetry record with the matching
toolname. Deriving the name list fromthe registry (not a literal array) is required —
test/unit/miner-mcp-scaffold.test.ts:91-102isthe precedent.
Deliverables
loopover_miner_ping's registration wraps its handler inwithMinerToolErrorHandlingregisterToolhandler that does not reach the wrapper,with a fixture case proving the test itself detects an unwrapped registration
record each, including
loopover_miner_pingtest/unit/miner-mcp-scaffold.test.ts:104-117stillpass unchanged
All Deliverables above are required in a single PR. A PR that satisfies only some of them — for
example wrapping the ping handler without adding the structural test, so the next tool added can
repeat the omission — does not resolve this issue.
Test Coverage Requirements
99%+ Codecov patch coverage, branch-counted, applies:
packages/loopover-miner/bin/**/*.tsisexplicitly listed in
coverage.include(vitest.config.ts:69-77, which callsbin/loopover-miner-mcp.tsout by name as "genuinely unit-coverable"). Both the success and thethrow arm of the wrapper as reached from the ping registration need a test, and a named regression
test must assert
loopover_miner_pingemits a dispatch telemetry record.Expected Outcome
All eleven miner tools emit
usage_eventand$mcp_tool_call; the miner surface's telemetry iscomplete rather than 10 of 11; and a future twelfth tool registered without the wrapper fails CI
instead of shipping uninstrumented.
Links & Resources
packages/loopover-miner/bin/loopover-miner-mcp.ts:108-132(the wrapper),:219-223(the gap)packages/loopover-miner/lib/mcp-dispatch-telemetry.ts:34-61test/unit/miner-mcp-scaffold.test.ts:91-117,test/unit/miner-posthog.test.ts:252-286test/unit/no-direct-octokit.test.ts(structural-rule precedent)