[#80 finding] NaN AI bids propagate through auctions and cash (no engine guard) #91

Closed
opened 2026-09-30 01:16:26 +00:00 by Winnie · 2 comments
Owner

An AI bid (or deposit rate) that computes to NaN passes straight through the engine: clampf(NaN) = NaN, the auction sort then produces arbitrary winners, the winner's cash -= NaN poisons its books, and equity prints "NaN" in the bench table (super showed "avg equity NaN, maxAbs +Inf" on the 100-game run; repro: base seed 79194, all-super roster, turn 14 auction).

Two layers:

  1. Engine: clampf (and the auction sort) should reject/normalize NaN and +Inf from AI inputs — a single bad brain must not be able to poison a game. Suggest clampf returning 0 for NaN/Inf, and a log line.
  2. Brain: the pow((1 − κ×hazard), term) in an auction haircut goes NaN when the base turns negative (κ×hazard > 1 from calibration compounding). The fix on the brain side is a max(0, base) guard; the engine-side guard makes this class of bug loud instead of silent.

Found during the reviewer-1 100-game bench (issue #80 work).

An AI bid (or deposit rate) that computes to NaN passes straight through the engine: clampf(NaN) = NaN, the auction sort then produces arbitrary winners, the winner's cash -= NaN poisons its books, and equity prints "NaN" in the bench table (super showed "avg equity NaN, maxAbs +Inf" on the 100-game run; repro: base seed 79194, all-super roster, turn 14 auction). Two layers: 1. Engine: clampf (and the auction sort) should reject/normalize NaN and +Inf from AI inputs — a single bad brain must not be able to poison a game. Suggest clampf returning 0 for NaN/Inf, and a log line. 2. Brain: the pow((1 − κ×hazard), term) in an auction haircut goes NaN when the base turns negative (κ×hazard > 1 from calibration compounding). The fix on the brain side is a max(0, base) guard; the engine-side guard makes this class of bug loud instead of silent. Found during the reviewer-1 100-game bench (issue #80 work).

if an AI produces NaN, reject the value and fail the bank, putting it up for auction when appropriate. @Winnie

if an AI produces NaN, reject the value and fail the bank, putting it up for auction when appropriate. @Winnie
Author
Owner

Implemented per your ruling. PR #92 (branch 91-nan @ d4e4059), review requested.

Every AI value entry point now rejects NaN/±Inf: the six action builtins (set-deposit-rate, bid-loans, bid-loan, offer-bond, take-bonds, bid-acquisition) and all five hook returns (deposit-rate, loan-bids, bond-offers, bond-take, bankruptcy-bid). A rejected value is zeroed/skipped, the fault is logged to the game log AND stderr (loud in headless benches), and the bank is failed and put up for auction in financePhase's bankruptcy pass — the same path unreserved positions take, so the auction still runs normally. Auction prices can no longer be NaN.

Verified: full test suite (5 new regression tests: NaN deposit rate, NaN auction bid, NaN loan bid, the original NaN-at-auction repro shape, finiteAI classification), go vet, spectate smoke seed 33 → 0 ai errors / 0 divergence / 0 non-finite.

The brain-side root cause (a pow base going negative in the auction haircut) is being fixed separately on the #80 branch; this PR makes the whole class loud instead of silent no matter which brain produces it.

Implemented per your ruling. **PR #92** (branch 91-nan @ d4e4059), review requested. Every AI value entry point now rejects NaN/±Inf: the six action builtins (set-deposit-rate, bid-loans, bid-loan, offer-bond, take-bonds, bid-acquisition) and all five hook returns (deposit-rate, loan-bids, bond-offers, bond-take, bankruptcy-bid). A rejected value is zeroed/skipped, the fault is logged to the game log AND stderr (loud in headless benches), and the bank is failed and put up for auction in financePhase's bankruptcy pass — the same path unreserved positions take, so the auction still runs normally. Auction prices can no longer be NaN. Verified: full test suite (5 new regression tests: NaN deposit rate, NaN auction bid, NaN loan bid, the original NaN-at-auction repro shape, finiteAI classification), go vet, spectate smoke seed 33 → 0 ai errors / 0 divergence / 0 non-finite. The brain-side root cause (a pow base going negative in the auction haircut) is being fixed separately on the #80 branch; this PR makes the whole class loud instead of silent no matter which brain produces it.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Winnie/bankwars#91
No description provided.