⚠️ 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
packages/loopover-miner/lib/github-token-resolution.ts:1-10 is explicitly commented "kept in sync by hand -- there is no shared module to import" against loopover-mcp's real config resolution. loopover-mcp's implementation (packages/loopover-mcp/bin/loopover-mcp.ts:368-369) falls back activeProfile.apiUrl ?? config.apiUrl (a top-level/global apiUrl) before hitting its hardcoded default. The miner's hand-copied loopoverApiUrl() (lines 85-93 of the same file) only reads activeLoopoverProfile(env).apiUrl and falls straight to DEFAULT_API_URL ("https://api.loopover.ai") if the profile lacks one -- it never checks the config's global apiUrl field. An operator with a self-hosted ORB API set globally (not per-profile) in ~/.config/loopover/config.json gets correct routing from loopover-mcp but the miner's resolveGitHubToken/resolveLoopoverBackendSession silently talk to the public API instead. The sibling env-file-indirection.ts:1-9 documents an analogous divergence already caught and fixed for ORB in #6284, with a dedicated parity test (test/unit/env-file-indirection-parity.test.ts) -- the same discipline is missing here.
Requirements
Add the config.apiUrl global fallback to loopoverApiUrl() in packages/loopover-miner/lib/github-token-resolution.ts, matching loopover-mcp's real precedence order (activeProfile.apiUrl ?? config.apiUrl ?? DEFAULT_API_URL) exactly, and add a parity test mirroring test/unit/env-file-indirection-parity.test.ts's precedent (asserting both implementations resolve identically for a matrix of profile/global/absent combinations).
Deliverables
All of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
packages/loopover-miner/** -- 99%+ patch coverage, all three precedence branches (profile-set, global-only, neither).
Expected Outcome
An operator with a self-hosted API URL configured only at the global config level gets correctly-routed miner behavior, matching loopover-mcp's already-correct resolution.
Links & Resources
packages/loopover-miner/lib/github-token-resolution.ts:1-10,85-93
packages/loopover-mcp/bin/loopover-mcp.ts:368-369
packages/loopover-miner/lib/env-file-indirection.ts:1-9
test/unit/env-file-indirection-parity.test.ts
Context
packages/loopover-miner/lib/github-token-resolution.ts:1-10is explicitly commented "kept in sync by hand -- there is no shared module to import" againstloopover-mcp's real config resolution.loopover-mcp's implementation (packages/loopover-mcp/bin/loopover-mcp.ts:368-369) falls backactiveProfile.apiUrl ?? config.apiUrl(a top-level/global apiUrl) before hitting its hardcoded default. The miner's hand-copiedloopoverApiUrl()(lines 85-93 of the same file) only readsactiveLoopoverProfile(env).apiUrland falls straight toDEFAULT_API_URL("https://api.loopover.ai") if the profile lacks one -- it never checks the config's globalapiUrlfield. An operator with a self-hosted ORB API set globally (not per-profile) in~/.config/loopover/config.jsongets correct routing fromloopover-mcpbut the miner'sresolveGitHubToken/resolveLoopoverBackendSessionsilently talk to the public API instead. The siblingenv-file-indirection.ts:1-9documents an analogous divergence already caught and fixed for ORB in #6284, with a dedicated parity test (test/unit/env-file-indirection-parity.test.ts) -- the same discipline is missing here.Requirements
Add the
config.apiUrlglobal fallback toloopoverApiUrl()inpackages/loopover-miner/lib/github-token-resolution.ts, matchingloopover-mcp's real precedence order (activeProfile.apiUrl ?? config.apiUrl ?? DEFAULT_API_URL) exactly, and add a parity test mirroringtest/unit/env-file-indirection-parity.test.ts's precedent (asserting both implementations resolve identically for a matrix of profile/global/absent combinations).Deliverables
loopoverApiUrl()checks the globalconfig.apiUrlbefore falling back toDEFAULT_API_URLenv-file-indirection-parity.test.ts's structure) assertingloopoverApiUrl()andloopover-mcp's equivalent resolve identically across profile-set / global-set-only / neither-set casesAll of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
packages/loopover-miner/**-- 99%+ patch coverage, all three precedence branches (profile-set, global-only, neither).Expected Outcome
An operator with a self-hosted API URL configured only at the global config level gets correctly-routed miner behavior, matching
loopover-mcp's already-correct resolution.Links & Resources
packages/loopover-miner/lib/github-token-resolution.ts:1-10,85-93packages/loopover-mcp/bin/loopover-mcp.ts:368-369packages/loopover-miner/lib/env-file-indirection.ts:1-9test/unit/env-file-indirection-parity.test.ts