The operator’s self-sync showed 0 positions despite holding several. Root cause was the same past-date class as the topbets 1970 fix: the inactivity filter dropped any position past its end-date, so still-held bets on past-but-unresolved markets (elections) were filtered out. Fixed to filter on redeemable only. Shipped 2026-06-08.

Symptom

The operator’s self-sync / /wallets showed 0 positions even though they were holding several bets.

Root cause

Inactivity filter dropped past-dated-but-held positions

repo::is_position_inactive(position, today) dropped a position if it was redeemable OR past its end-date. So a still-HELD bet on a past-but-unresolved market (e.g. an election whose date has passed but which hasn’t resolved yet) was incorrectly treated as inactive and filtered out. With several such positions, the operator’s whole book filtered to 0.

Same past-date root-cause class as topbets-enddate-1970-fix — past end-date ≠ no longer held.

Fix

Replaced is_position_inactive with is_position_redeemed(position) = position.redeemable only. The self-sync now keeps currently-held positions (redeemable = false, size > 0) regardless of end-date, dropping only resolved + dust. Applied at both sites:

  • the stored sync upsert_positions_for_wallet
  • the live /wallets display fetch_self_overlap_sections_live

Decision — “currently-held only”

Resolved bets stay hidden (intentional)

The chosen semantics are currently-held only: resolved/settled bets are not shown. Widening to surface settled trades is a one-liner if wanted later, but the current intent is “what am I holding right now.”

Cohort/scoring untouched

This only affects the operator’s self book (self-sync + /wallets). The cohort holder queries and the pmv2 scoring path are not touched. (Note the cohort holder queries DO filter redeemable=false — see correctness-pass-six-fix-commits — which is the same “redeemable, not end-date” principle applied there.)