Context
packages/loopover-engine/src/miner/iterate-loop.ts defines finiteNonNegativeUsage (line 285-293) specifically to guard against malformed driver-reported usage numbers:
A finite, non-negative usage value, else 0. accumulateAttemptUsage (attempt-metering.ts) deliberately THROWS a RangeError on a negative/non-finite input to protect its own direct callers... clamp here too so no current or future driver can crash the loop instead of being governed.
Inside runIterateLoopCore's per-iteration loop (around line 420-434), this guard is applied inconsistently on two adjacent statements reading the exact same driverResult fields:
totalTurnsUsed += driverResult.turnsUsed ?? 0;
totalCostUsd += driverResult.costUsd ?? 0;
// ...
tracker.totals = accumulateAttemptUsage(tracker.totals, {
tokens: finiteNonNegativeUsage(driverResult.tokensUsed),
turns: finiteNonNegativeUsage(driverResult.turnsUsed),
// ...
costUsd: finiteNonNegativeUsage(driverResult.costUsd),
});
tracker.totals (used for budget-ceiling enforcement) correctly clamps turnsUsed/costUsd through finiteNonNegativeUsage before folding them in via accumulateAttemptUsage. The totalTurnsUsed/totalCostUsd accumulators two lines above do not — they only apply ?? 0 (which catches undefined/null but not NaN or a negative number) before a raw +=.
driverResult.turnsUsed/costUsd come from CodingAgentDriverResult, a value a driver implementation reports. The module's own reasoning for the clamp — "no current or future driver can crash the loop" — applies equally to a driver reporting NaN or a negative value here: NaN + x poisons the accumulator for the rest of the loop (NaN is sticky under +=), and a negative value silently understates the running total. Both totalTurnsUsed and totalCostUsd are returned to the caller as IterateLoopResult.totalTurnsUsed/totalCostUsd — a wrong (possibly NaN, possibly under-counted) total silently reaches any log, dashboard, or billing/telemetry consumer that reads the loop result, even though the loop's own budget enforcement (via tracker.totals) stays correct because it's guarded.
Requirements
- Apply
finiteNonNegativeUsage(driverResult.turnsUsed) and finiteNonNegativeUsage(driverResult.costUsd) to the totalTurnsUsed/totalCostUsd accumulator updates, the same guard already used two lines below for tracker.totals.
- Do not change
finiteNonNegativeUsage's own signature or behavior — this is a call-site fix, applying an existing guard consistently, not introducing new clamping logic.
Deliverables
Test Coverage Requirements
This repo's Codecov patch gate is 99%+ hard (branch-counted) on every changed line/branch in src/**/packages/**. The regression test must reproduce the exact NaN-poisoning failure mode described (assert the final totalTurnsUsed/totalCostUsd on IterateLoopResult is a finite, correct number after a malformed-usage iteration, not NaN).
Expected Outcome
A driver reporting a malformed (NaN/negative) turnsUsed or costUsd can no longer silently poison the loop's returned total usage figures — totalTurnsUsed/totalCostUsd are governed by the same guard as the budget-enforcement totals, consistent with the module's own stated defensive intent.
Links & Resources
packages/loopover-engine/src/miner/iterate-loop.ts:285-293 (finiteNonNegativeUsage and its stated purpose), :423-424 (the unguarded accumulator updates), :429-432 (the guarded sibling two lines below, showing the correct pattern).
Context
packages/loopover-engine/src/miner/iterate-loop.tsdefinesfiniteNonNegativeUsage(line 285-293) specifically to guard against malformed driver-reported usage numbers:Inside
runIterateLoopCore's per-iteration loop (around line 420-434), this guard is applied inconsistently on two adjacent statements reading the exact samedriverResultfields:tracker.totals(used for budget-ceiling enforcement) correctly clampsturnsUsed/costUsdthroughfiniteNonNegativeUsagebefore folding them in viaaccumulateAttemptUsage. ThetotalTurnsUsed/totalCostUsdaccumulators two lines above do not — they only apply?? 0(which catchesundefined/nullbut notNaNor a negative number) before a raw+=.driverResult.turnsUsed/costUsdcome fromCodingAgentDriverResult, a value a driver implementation reports. The module's own reasoning for the clamp — "no current or future driver can crash the loop" — applies equally to a driver reportingNaNor a negative value here:NaN + xpoisons the accumulator for the rest of the loop (NaNis sticky under+=), and a negative value silently understates the running total. BothtotalTurnsUsedandtotalCostUsdare returned to the caller asIterateLoopResult.totalTurnsUsed/totalCostUsd— a wrong (possiblyNaN, possibly under-counted) total silently reaches any log, dashboard, or billing/telemetry consumer that reads the loop result, even though the loop's own budget enforcement (viatracker.totals) stays correct because it's guarded.Requirements
finiteNonNegativeUsage(driverResult.turnsUsed)andfiniteNonNegativeUsage(driverResult.costUsd)to thetotalTurnsUsed/totalCostUsdaccumulator updates, the same guard already used two lines below fortracker.totals.finiteNonNegativeUsage's own signature or behavior — this is a call-site fix, applying an existing guard consistently, not introducing new clamping logic.Deliverables
totalTurnsUsed += finiteNonNegativeUsage(driverResult.turnsUsed);(replacing the unguarded?? 0form)totalCostUsd += finiteNonNegativeUsage(driverResult.costUsd);(replacing the unguarded?? 0form)turnsUsed: NaN(or a negativecostUsd) across two iterations does NOT poisonIterateLoopResult.totalTurnsUsed/totalCostUsdwithNaNor a negative running total — the malformed value is treated as 0 for the accumulator, matching howtracker.totalsalready handles itTest Coverage Requirements
This repo's Codecov patch gate is 99%+ hard (branch-counted) on every changed line/branch in
src/**/packages/**. The regression test must reproduce the exactNaN-poisoning failure mode described (assert the finaltotalTurnsUsed/totalCostUsdonIterateLoopResultis a finite, correct number after a malformed-usage iteration, notNaN).Expected Outcome
A driver reporting a malformed (
NaN/negative)turnsUsedorcostUsdcan no longer silently poison the loop's returned total usage figures —totalTurnsUsed/totalCostUsdare governed by the same guard as the budget-enforcement totals, consistent with the module's own stated defensive intent.Links & Resources
packages/loopover-engine/src/miner/iterate-loop.ts:285-293(finiteNonNegativeUsageand its stated purpose),:423-424(the unguarded accumulator updates),:429-432(the guarded sibling two lines below, showing the correct pattern).