Review: Per-bot live activity feed -- Turbo Streams

review-1717-2026-07-03 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- Sprint 4, depends on #26 and bots running
  • [x] Repo -- ldraney/prediction-assistant
  • [x] User Story -- Bot Marketplace
  • [x] Context -- detailed background
  • [x] File Targets -- 7 files listed
  • [x] Feature Flag -- None (integral to UI)
  • [x] Acceptance Criteria -- 10 criteria
  • [x] Test Expectations -- listed
  • [x] Constraints -- listed
  • [x] Checklist -- 11 items
  • [x] Related -- dependencies listed
All required sections present per template-issue-feature.

Traceability

  • [x] story:bot-marketplace label -- Bot Marketplace user story
  • [x] story note verified -- found in project-prediction-assistant user-stories section
  • [x] arch:frontend label -- frontend component
  • [ ] arch note MISSING -- [SCOPE] Create architecture note arch-frontend for component frontend
  • [x] Forgejo issue -- #30, open

File Targets

  • [x] app/models/activity_log.rb -- EXISTS but schema diverges from AC (see Recommendations)
  • [x] db/migrate/20260703200001_create_activity_logs.rb -- EXISTS, matches actual model
  • [ ] app/channels/bot_activity_channel.rb -- does not exist yet, to be created
  • [ ] app/views/bots/_activity_feed.html.erb -- does not exist yet, to be created
  • [ ] app/views/activity_logs/_activity_log.html.erb -- does not exist yet, to be created
  • [x] test/models/activity_log_test.rb -- EXISTS with full validation/scope coverage
  • [ ] test/channels/bot_activity_channel_test.rb -- does not exist yet, to be created
Critical mismatch: AC #1 specifies fields that do not match the existing ActivityLog model:
  • AC says user_id -- no User model exists in the app, no user_id on ActivityLog or Strategy
  • AC says bot_type -- actual field is bot_name
  • AC says action values (order_placed, fill_received, position_opened, exit_triggered, error) -- actual values are place_order, cancel_order, fill, partial_fill, error, dry_run, bulk_sweep
  • AC says rationale (text) -- actual fields are message (text) + metadata (jsonb)
  • AC says timestamp -- actual field is created_at (standard Rails timestamps)

Repo Placement

OK -- issue filed on ldraney/prediction-assistant, all file targets in that repo. Single-repo scope.

Dependencies

  • #26 (Bot Detail pages) -- in validation column, merged. Show page exists at app/views/bots/show.html.erb. SATISFIED.
  • #23 (OrderService) -- in validation column. Already creates ActivityLog entries via ActivityLog.create!. SATISFIED.
  • #27 (Pregame Stacker) -- in validation column, merged. SATISFIED.
  • #28 (Bulk Sweep) -- in validation column, merged. SATISFIED.
  • #29 (Edge Learner) -- in backlog (sprint:6). NOT blocking -- feed works with whatever bots exist.
  • #48 (Hotwire conversion) -- in validation column. Turbo/Stimulus/Action Cable are available. SATISFIED.
  • Undocumented: User authentication model -- AC #6 says scope by user_id but no User model exists. Keycloak OIDC is integrated (#57, closed) but no Rails User model has been created. Action Cable Connection has no auth.

Acceptance Criteria

  • AC #1 (model fields) -- STALE, model already exists with different schema. Needs update.
  • AC #2 (Kalshi market link) -- testable, straightforward
  • AC #3 (feed partial on detail page) -- testable, show.html.erb exists to embed it
  • AC #4 (per-bot filtering) -- testable, for_bot scope exists
  • AC #5 (Turbo Streams real-time) -- testable, Action Cable + solid_cable configured
  • AC #6 (channel scoped to user_id + strategy_id) -- PROBLEMATIC: no User model, no user_id. Must scope by strategy_id only for now.
  • AC #7 (pagination) -- testable
  • AC #8 (entry display: rationale) -- STALE: field is message, not rationale
  • AC #9 (entries created by bots/OrderService) -- ALREADY MET: OrderService already creates ActivityLog entries
  • AC #10 (reverse chronological) -- testable, recent scope exists

Blast Radius

  • OrderService already creates ActivityLog entries -- adding after_create broadcast will fire on every trade execution across all bots
  • BulkSweepJob processes many markets rapidly -- broadcasting per-entry could flood the cable. Constraints section mentions throttling but no specific mechanism is prescribed
  • Action Cable uses solid_cable (database-backed pub/sub, not Redis) -- performance under high-frequency broadcasting should be monitored
  • No cross-user leakage concern currently since there is no multi-user model yet

Decomposition Assessment

7 file targets (3 already exist), 10 acceptance criteria (exceeds 5 threshold), 1 repo. Remaining work is 4 new files + 3 modifications. The work is standard Rails patterns (channel, partials, Turbo Streams wiring) that are boilerplate-heavy but not complex. At 2 story points the scope is reasonable for a single agent pass once the AC is corrected, provided AC #9 is marked as pre-existing. No decomposition needed after AC cleanup -- effective AC count drops to 7-8, and the remaining file creation is templated.

Recommendation

  • [BODY] Update AC #1 field list to match existing ActivityLog schema: strategy_id, bot_name (not bot_type), action (place_order, cancel_order, fill, partial_fill, error, dry_run, bulk_sweep), ticker, side, quantity, price, status (success, failure, dry_run, rejected), message (not rationale), metadata (jsonb). Remove user_id and timestamp.
  • [BODY] Update AC #6: remove user_id scoping -- scope BotActivityChannel to strategy_id only. User scoping is a future concern when User model lands.
  • [BODY] Update AC #8: replace "rationale" with "message" to match actual schema.
  • [BODY] Mark AC #9 as pre-existing (OrderService already writes to ActivityLog) or reframe as "verify existing integration".
  • [SCOPE] Create architecture note arch-frontend for component frontend.