⚠️ 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-engine/src/portfolio/queue.ts:59-62's finiteNonNegativeInt returns 0 for any non-finite value, so nextEligibleItems (line 150) with globalWipCap: Infinity returns [] -- the opposite of "uncapped." This contradicts the established convention in the very same codebase: packages/loopover-miner/lib/portfolio-queue-cli.ts:345-348 documents "Unset dimensions stay genuinely uncapped (Infinity), not silently defaulted to 1," and packages/loopover-miner/lib/portfolio-queue-manager.ts:52-56's normalizePortfolioCaps (the function that actually feeds this engine call) performs the identical collapse. Currently latent in production wiring but a proven landmine for any future caller following the established Infinity convention.
Requirements
Change finiteNonNegativeInt (or add a distinct handling path) so Infinity is treated as "uncapped" rather than collapsed to 0, consistent with portfolio-queue-cli.ts's documented convention. Since normalizePortfolioCaps in portfolio-queue-manager.ts performs the identical collapse today, fix both call sites (or fix the shared root cause if one exists) so the Infinity convention holds end-to-end, and add a pinning test proving globalWipCap: Infinity no longer excludes all items.
Deliverables
All of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
packages/loopover-engine/** -- 99%+ patch coverage, branch-counted, covering both the finite-cap and Infinity-uncapped paths.
Expected Outcome
A caller passing Infinity to mean 'uncapped' (following this codebase's own established convention) gets genuinely uncapped behavior instead of a silent full-exclusion bug.
Links & Resources
packages/loopover-engine/src/portfolio/queue.ts:59-62,150
packages/loopover-miner/lib/portfolio-queue-cli.ts:345-348
packages/loopover-miner/lib/portfolio-queue-manager.ts:52-56
Context
packages/loopover-engine/src/portfolio/queue.ts:59-62'sfiniteNonNegativeIntreturns0for any non-finite value, sonextEligibleItems(line 150) withglobalWipCap: Infinityreturns[]-- the opposite of "uncapped." This contradicts the established convention in the very same codebase:packages/loopover-miner/lib/portfolio-queue-cli.ts:345-348documents "Unset dimensions stay genuinely uncapped (Infinity), not silently defaulted to 1," andpackages/loopover-miner/lib/portfolio-queue-manager.ts:52-56'snormalizePortfolioCaps(the function that actually feeds this engine call) performs the identical collapse. Currently latent in production wiring but a proven landmine for any future caller following the established Infinity convention.Requirements
Change
finiteNonNegativeInt(or add a distinct handling path) soInfinityis treated as "uncapped" rather than collapsed to0, consistent withportfolio-queue-cli.ts's documented convention. SincenormalizePortfolioCapsinportfolio-queue-manager.tsperforms the identical collapse today, fix both call sites (or fix the shared root cause if one exists) so the Infinity convention holds end-to-end, and add a pinning test provingglobalWipCap: Infinityno longer excludes all items.Deliverables
finiteNonNegativeInt(or its caller) treatsInfinityas uncapped rather than0normalizePortfolioCapsinportfolio-queue-manager.tsis fixed to match, if it independently performs the same collapsenextEligibleItemswithglobalWipCap: Infinityreturns eligible items rather than an empty arrayAll of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
packages/loopover-engine/**-- 99%+ patch coverage, branch-counted, covering both the finite-cap and Infinity-uncapped paths.Expected Outcome
A caller passing
Infinityto mean 'uncapped' (following this codebase's own established convention) gets genuinely uncapped behavior instead of a silent full-exclusion bug.Links & Resources
packages/loopover-engine/src/portfolio/queue.ts:59-62,150packages/loopover-miner/lib/portfolio-queue-cli.ts:345-348packages/loopover-miner/lib/portfolio-queue-manager.ts:52-56