Context
packages/loopover-miner/lib/local-store.js (#4272) was built specifically to extract the ~15 lines of
env-var/config-dir/XDG path-resolution + normalization boilerplate that every local store used to hand-write —
its own header comment names run-state.js, claim-ledger.js, portfolio-queue.js, and event-ledger.js as
the stores it DRY'd, via two exported helpers: resolveLocalStoreDbPath (env-var → LOOPOVER_MINER_CONFIG_DIR
→ XDG_CONFIG_HOME fallback chain) and normalizeLocalStoreDbPath (trim + empty-path validation).
packages/loopover-miner/lib/governor-ledger.js (resolveGovernorLedgerDbPath, lines 24-37, and
normalizeDbPath, lines 40-44), packages/loopover-miner/lib/prediction-ledger.js
(resolvePredictionLedgerDbPath, lines 26-39, and normalizeDbPath, lines 42-46), and
packages/loopover-miner/lib/plan-store.js (resolvePlanStoreDbPath, lines 22-35, and normalizeDbPath, lines
38-42) each still hand-duplicate that exact same ~15-line resolution/normalization logic byte-for-byte, even
though all three files already import { openLocalStoreDb } from "./local-store.js" on their very next line —
they only ever adopted the shared DB-opening helper, never the shared path-resolution/normalization helpers the
same module exports for the same purpose. This is a real drift risk: a future change to the env-var precedence
chain in local-store.js (e.g. a new fallback tier) would silently apply to run-state.js/claim-ledger.js/
portfolio-queue.js/event-ledger.js/every other store already migrated, but NOT to these three, producing
inconsistent path resolution across the package's own local stores with no test able to catch the divergence
(each file's hand-rolled copy currently behaves identically, so nothing fails today, but the duplication itself
is the bug this issue exists to close, matching the exact "claims to mirror but never did" shape #6600 already
fixed for worktree-allocator.js).
Requirements
packages/loopover-miner/lib/governor-ledger.js's resolveGovernorLedgerDbPath MUST be reimplemented as a
thin wrapper calling resolveLocalStoreDbPath("governor-ledger.sqlite3", "LOOPOVER_MINER_GOVERNOR_LEDGER_DB", env) from ./local-store.js, and its normalizeDbPath MUST call normalizeLocalStoreDbPath with the same
invalid_governor_ledger_db_path error message — deleting the hand-rolled homedir/join/env-chain logic
entirely.
packages/loopover-miner/lib/prediction-ledger.js's resolvePredictionLedgerDbPath and normalizeDbPath MUST
be reimplemented the same way, using "prediction-ledger.sqlite3" / "LOOPOVER_MINER_PREDICTION_LEDGER_DB" /
invalid_prediction_ledger_db_path.
packages/loopover-miner/lib/plan-store.js's resolvePlanStoreDbPath and normalizeDbPath MUST be
reimplemented the same way, using "plan-store.sqlite3" / "LOOPOVER_MINER_PLAN_STORE_DB" /
invalid_plan_store_db_path.
- Every one of the three files' now-unused
homedir/join imports (where no longer referenced) MUST be
removed rather than left dangling.
- Behavior MUST be byte-identical: the exact same env var names, the exact same
LOOPOVER_MINER_CONFIG_DIR /
XDG_CONFIG_HOME fallback order, and the exact same default file names as today — this is a pure
DRY/consistency refactor, not a behavior change.
Deliverables
Test Coverage Requirements
99%+ Codecov patch coverage on every changed line and branch across all three files — including both the
explicit-env-var-set and explicit-env-var-unset branches of the shared helper as exercised through each
store's own public resolve*DbPath/normalizeDbPath surface, so a future regression in any of the three
call sites is caught the same way a regression in the shared helper itself already would be.
Expected Outcome
governor-ledger.js, prediction-ledger.js, and plan-store.js resolve and normalize their DB paths through
the same single source of truth (local-store.js) every other migrated store already uses, closing the drift
risk where a future change to the shared resolution logic would silently stop applying to these three files.
Links & Resources
Context
packages/loopover-miner/lib/local-store.js(#4272) was built specifically to extract the ~15 lines ofenv-var/config-dir/XDG path-resolution + normalization boilerplate that every local store used to hand-write —
its own header comment names
run-state.js,claim-ledger.js,portfolio-queue.js, andevent-ledger.jsasthe stores it DRY'd, via two exported helpers:
resolveLocalStoreDbPath(env-var →LOOPOVER_MINER_CONFIG_DIR→
XDG_CONFIG_HOMEfallback chain) andnormalizeLocalStoreDbPath(trim + empty-path validation).packages/loopover-miner/lib/governor-ledger.js(resolveGovernorLedgerDbPath, lines 24-37, andnormalizeDbPath, lines 40-44),packages/loopover-miner/lib/prediction-ledger.js(
resolvePredictionLedgerDbPath, lines 26-39, andnormalizeDbPath, lines 42-46), andpackages/loopover-miner/lib/plan-store.js(resolvePlanStoreDbPath, lines 22-35, andnormalizeDbPath, lines38-42) each still hand-duplicate that exact same ~15-line resolution/normalization logic byte-for-byte, even
though all three files already
import { openLocalStoreDb } from "./local-store.js"on their very next line —they only ever adopted the shared DB-opening helper, never the shared path-resolution/normalization helpers the
same module exports for the same purpose. This is a real drift risk: a future change to the env-var precedence
chain in
local-store.js(e.g. a new fallback tier) would silently apply torun-state.js/claim-ledger.js/portfolio-queue.js/event-ledger.js/every other store already migrated, but NOT to these three, producinginconsistent path resolution across the package's own local stores with no test able to catch the divergence
(each file's hand-rolled copy currently behaves identically, so nothing fails today, but the duplication itself
is the bug this issue exists to close, matching the exact "claims to mirror but never did" shape #6600 already
fixed for
worktree-allocator.js).Requirements
packages/loopover-miner/lib/governor-ledger.js'sresolveGovernorLedgerDbPathMUST be reimplemented as athin wrapper calling
resolveLocalStoreDbPath("governor-ledger.sqlite3", "LOOPOVER_MINER_GOVERNOR_LEDGER_DB", env)from./local-store.js, and itsnormalizeDbPathMUST callnormalizeLocalStoreDbPathwith the sameinvalid_governor_ledger_db_patherror message — deleting the hand-rolledhomedir/join/env-chain logicentirely.
packages/loopover-miner/lib/prediction-ledger.js'sresolvePredictionLedgerDbPathandnormalizeDbPathMUSTbe reimplemented the same way, using
"prediction-ledger.sqlite3"/"LOOPOVER_MINER_PREDICTION_LEDGER_DB"/invalid_prediction_ledger_db_path.packages/loopover-miner/lib/plan-store.js'sresolvePlanStoreDbPathandnormalizeDbPathMUST bereimplemented the same way, using
"plan-store.sqlite3"/"LOOPOVER_MINER_PLAN_STORE_DB"/invalid_plan_store_db_path.homedir/joinimports (where no longer referenced) MUST beremoved rather than left dangling.
LOOPOVER_MINER_CONFIG_DIR/XDG_CONFIG_HOMEfallback order, and the exact same default file names as today — this is a pureDRY/consistency refactor, not a behavior change.
Deliverables
governor-ledger.js,prediction-ledger.js, andplan-store.jseach callingresolveLocalStoreDbPath/normalizeLocalStoreDbPathfromlocal-store.jsinstead of duplicating thelogic inline.
LOOPOVER_MINER_CONFIG_DIR,and
XDG_CONFIG_HOME-fallback resolution paths still produce the exact same results as before therefactor (regression coverage for "no behavior change").
Test Coverage Requirements
99%+ Codecov patch coverage on every changed line and branch across all three files — including both the
explicit-env-var-set and explicit-env-var-unset branches of the shared helper as exercised through each
store's own public
resolve*DbPath/normalizeDbPathsurface, so a future regression in any of the threecall sites is caught the same way a regression in the shared helper itself already would be.
Expected Outcome
governor-ledger.js,prediction-ledger.js, andplan-store.jsresolve and normalize their DB paths throughthe same single source of truth (
local-store.js) every other migrated store already uses, closing the driftrisk where a future change to the shared resolution logic would silently stop applying to these three files.
Links & Resources
packages/loopover-miner/lib/local-store.js(feat(miner-manage): local SQLite schema for run-state, claim ledger, and PR portfolio #4272) — the sharedresolveLocalStoreDbPath/normalizeLocalStoreDbPath/openLocalStoreDbhelpers to adopt.packages/loopover-miner/lib/run-state.js,claim-ledger.js,portfolio-queue.js,event-ledger.js—reference implementations already using the shared helpers correctly.
worktree-allocator.js.