Re-Review: Bug: Scanner never attaches markets to basketball games
Verdict: APPROVED
Re-review of board item #1850 —
ldraney/botfire#19. Bug type issue. Previous review (review-1850-2026-07-10) returned NEEDS_REFINEMENT due to missing arch-bots architecture note. That note now exists (arch-bots, id 2527) along with the newly created domain model note (arch-domain-bots, id 2541). All previous findings re-verified. Scope is solid and ready for implementation.Template Completeness
- [x] Type — Bug
- [x] Lineage — references spike #18
- [x] Repo —
ldraney/botfire - [x] What Broke — detailed explanation of the skip-existing-games bug in discover_games
- [x] Repro Steps — 5 concrete steps with Rails console commands and Kalshi API queries
- [x] Expected Behavior — clear description of retry behavior for 0-market games
- [x] Environment — Docker Compose on archbox, scanner service path
- [x] Acceptance Criteria — 4 testable criteria
- [x] Related — links to project-botfire and spike #18
Traceability
- [x] story:bot-strategy label — present on board item
- [x] story note verified — found in project-botfire user-stories section: "As a bot operator, I want to identify and exploit profitable trading conditions so that my automated bots generate consistent positive P&L."
- [x] arch:bots label — present on board item
- [x] arch note verified —
arch-bots(Architecture: BotFire Bot Engine) exists in pal-e-docs, active. Additionallyarch-domain-bots(Domain Model: BotFire) created since last review. - [x] Forgejo issue — ldraney/botfire#19, state: open
File Targets
- [x]
app/services/scanner.rb— verified: file exists (258 lines) - [x]
discover_gamesmethod — verified: defined at line 45 - [x]
Game.exists?(milestone_id: m["id"])— verified: line 53, this is the root cause. Games that already exist are rejected fromnew_milestones, so their market discovery is never retried. - [x]
real_game_market?filter — verified: lines 116-122, checks for/GAME/in ticker.KXWNBAGAME-*tickers would pass this filter correctly.
Repo Placement
OK. Issue filed on
ldraney/botfire, fix is in app/services/scanner.rb in the same repo. Single-repo fix.Dependencies
- No blocking dependencies. Item is in backlog with no items it depends on.
- Downstream: item #1851 (Per-sport analytics) would benefit from this fix, as it needs basketball market data to track per-sport performance. Not a blocker.
- Item #1848 (Tighten Live Edge ceiling) is in QA but is independent — it adjusts price thresholds, not sport type discovery.
Acceptance Criteria
4 criteria, all machine-verifiable:
- [x] AC1: Basketball game-winner markets attached — testable via
Market.joins(:game).where(games: { sport_type: "basketball_game" }).count - [x] AC2: Scanner retries for games with 0 markets — testable by observing scanner logs after restart
- [x] AC3: No regression in baseball discovery — testable by checking baseball market counts before/after
- [x] AC4: Market count > 0 after scanner runs — directly testable Rails console query
Blast Radius
- The
reject { |m| Game.exists? }pattern exists only inscanner.rbline 53 — no sibling services share this pattern. - Downstream:
bot_engine.rbqueries markets filtered bysport_typeviabot.watched_sports(lines 77-81). Once basketball markets appear, bots configured to watchbasketball_gamewill start evaluating those markets. This is expected/desired behavior. volatility_bot.rbincludesbasketball_gameinHEDGEABLE_SPORTS(line 13) — but the volatility bot is currently disabled per board item #1840.game_phase.rbalready handlesbasketball_gamesport type (lines 10, 32) — no changes needed there.- Dashboard (
index.html.erbline 190) already mapsbasketball_gameto "Basketball" — no UI changes needed. Bot::SPORT_TYPES(bot.rb line 2) already includesbasketball_game.
Decomposition Assessment
No decomposition needed. 1 primary file target (
scanner.rb), 4 acceptance criteria, estimated under 5 minutes of agent work. Well within the single-pass threshold.Recommendation
No action needed. All traceability requirements satisfied. Scope is complete and verified.