Skip to content

Automation/bot auto pr#197

Open
VirilePeak wants to merge 2 commits intoPolymarket:mainfrom
VirilePeak:automation/bot-auto-pr
Open

Automation/bot auto pr#197
VirilePeak wants to merge 2 commits intoPolymarket:mainfrom
VirilePeak:automation/bot-auto-pr

Conversation

@VirilePeak
Copy link

@VirilePeak VirilePeak commented Feb 9, 2026

Note

High Risk
Touches trade execution and risk gating (including kill-switch persistence) and adds an automated deploy workflow, so misconfiguration or logic errors could affect live trading/deploy safety.

Overview
Adds a new low-latency “fast entry” trading path via FastEntryEngine, including sliding-window dislocation detection, immediate “leg1” entry execution, timing guards for 5m/15m BTC up/down markets, latency logging, and hooks for later confirmation/hedge/exit actions.

Introduces core trade lifecycle infrastructure (PositionManager, RiskManager, LatencyStats, TradeMetricsTracker) with market-level locks, idempotency + persistence, fast-exit A/B logic, kill-switch persistence (data/risk_state.json), and a hard gate that forces entries through src/order_executor.place_entry_order_with_gate() (enforced by Polymarket.execute_order(gate_checked=...)).

Adds a market-data subsystem (adapter/cache/event bus/providers + FastAPI health/metrics/admin routes) and updates docs/settings to reflect debug endpoints and timeframe controls.

Separately, adds/updates repo automation and deployment: new CI workflow, a bot draft-PR workflow, optional SSH/rsync deploy-on-merge using .deployignore, CodeQL monitoring/commenting workflows, dependency-review tweaks, plus .gitignore/requirements platform markers and a handful of helper scripts.

Written by Cursor Bugbot for commit 2dad940. This will update automatically on new commits. Configure here.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welcome to Polymarket Agents. Thank you for creating your first PR. Cheers!

@VirilePeak VirilePeak marked this pull request as ready for review February 9, 2026 19:01
Copy link
Author

@VirilePeak VirilePeak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@VirilePeak
Copy link
Author

Hi maintainers — PR #197 is from a fork and the GitHub Actions workflow is awaiting approval.
Could someone please click “Approve workflows to run” so the checks can execute? Thank you!

Copy link
Author

@VirilePeak VirilePeak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@VirilePeak
Copy link
Author

Hi maintainers — this PR triggers 3 GitHub Actions workflows that are awaiting approval.
Could someone with write access please click “Approve workflows to run” so the checks can execute? Thanks!

@VirilePeak
Copy link
Author

Hi maintainers — this PR adds the automation workflows for bot maintenance/updates.
Security note: the deploy workflow is optional and only runs on merge / required conditions (no secrets are exposed in PR context).
GitHub shows “3 workflows awaiting approval” — could someone with write access please click “Approve workflows to run” so CI can execute?
Happy to split deploy vs. bot-auto PR if you prefer.

* Update README to clarify get-all-markets command usage

* Optimierungen: ngrok Auto-Start, Orphan-Cleanup, Trade-Stat Scripts

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci: add workflow to run lint/tests and open automated draft PRs (semi-automatic)

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(automation): add guide for semi-automatic workflow and secrets

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci(tests): run black, flake8 and pytest; autoformat before PR

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci(deploy): optional SSH/SCP deploy on merge to main (conditional on secrets)

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(automation): add deploy secrets quickstart

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(scripts): add SSH/SCP deploy connection test script

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(automation): document test_deploy_ssh usage in automation README

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci(workflow): quote commit-message to fix YAML

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(position_manager): persist idempotency and cooldown maps to state file to prevent duplicate webhook processing after restart

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(start_server): Projektpfad an PYTHONPATH anhängen statt vorhandenen Wert zu überschreiben — verhindert Verlust benutzerdefinierter PYTHONPATH-Einträge beim Start.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(fast_entry_engine): enhance error handling and logging, improve price drop detection logic, and refactor market token fetching to use httpx directly

* ci(monitor): scheduled watcher to rerun stuck CodeQL runs on automation branch

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci(workflow): remove duplicate flake8 execution in CI workflow

* fix(market_data): improve data fetching logic and enhance error handling for market data retrieval

* fix(ci): resolve YAML nested mapping error in bot-auto-pr.yml

YAML value for 'commit-message' contained a colon causing a nested mapping parse error; changed to block scalar.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): add conditional checks for SSH key and host in deployment workflow

* fix(ci): quote commit-message in workflow to avoid YAML parsing error

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci(summary): hourly automation PR summary (posts comment to automation PR)

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: remove cursor worktree config from repo

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(winrate): add MQ gate, confirmation store, exit safety and tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(start): set WINRATE_UPGRADE env flags for safe paper-mode smoke test

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(start): set CONFIRM_TTL_SECONDS env for compatibility

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(winrate): move confirmation before session/MQ; add MQ gate, confirmation store, exit safety; tests and scripts

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(winrate): load env vars for winrate upgrade; use sig_for_dedupe in confirmation key

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(dedupe): allow duplicates to pass when confirmation pending

Co-authored-by: Cursor <cursoragent@cursor.com>

* debug(dedupe): log confirmation_store keys when duplicate detected

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(webhook): move confirmation to immediately after dedupe acceptance; remove duplicate confirmation block

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(winrate): add ConfirmationStore.handle API (pending/expired/confirmed)

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(winrate): add ConfirmationStore.handle and use stable conf_key (market/token:direction:signal_id) after dedupe

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(winrate): add ConfirmationStore.clear to remove pending keys

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(winrate): clear pending confirmation when confirmed signal later blocked (session/MQ)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(winrate): clear confirmed pending keys on various rejects and after trade create

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(syntax): remove stray escape in logger.exception for confirmation clear

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(winrate): structured conf_key, improve ConfirmationStore.clear logging, dedupe log fixes, time_to_end instrumentation

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(winrate): 5 bugs in confirmation flow - syntax, clear semantics, dedupe logs, slot-drift, orphan expiry

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): use env proxy for secrets in deploy-on-merge workflow if-conditions

Co-authored-by: Cursor <cursoragent@cursor.com>

* Market data: adapter runtime startup, health/metrics routes, tests, CI

Co-authored-by: Cursor <cursoragent@cursor.com>

* Register market-data health/metrics routes (safe, no WS side-effects)

Co-authored-by: Cursor <cursoragent@cursor.com>

* Entry/Risk Gates: settings, RiskManager.check_entry_allowed, integrate in FastEntryEngine, tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* Enforce Entry Gate chokepoint: OrderExecutor + Polymarket check flag + FastEntryEngine wiring + tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* RiskManager: kill-switch cooldown + persistent state file (atomic save/load), tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* Docs: RISK_STATE_PATH note in settings.py (persistence guidance)

Co-authored-by: Cursor <cursoragent@cursor.com>

* archive: rotate legacy trade logs before reset

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: initialize fresh paper_trades/position_state/pending_confirmations (reset stats)

Co-authored-by: Cursor <cursoragent@cursor.com>

* market_data: add REST fallback provider and RTDS provider (parsers + reconnect)

Co-authored-by: Cursor <cursoragent@cursor.com>

* market_data: RTDS provider support + settings + normalizer unit test

Co-authored-by: Cursor <cursoragent@cursor.com>

* tests(market_data): REST provider refresh + adapter subscribe wiring

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: import MarketDataAdapter safely in webhook startup to avoid NameError

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(startup): remove local asyncio import to avoid UnboundLocalError when scheduling market data consumer

Co-authored-by: Cursor <cursoragent@cursor.com>

* health: improve /market-data/health to introspect adapter state when available

Co-authored-by: Cursor <cursoragent@cursor.com>

* health: rely on telemetry gauge for adapter presence to avoid cross-module introspection issues

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(market-data): add market_data_event_consumer to subscribe to adapter EventBus and handle realtime soft-stops

Co-authored-by: Cursor <cursoragent@cursor.com>

* feature: auto-subscribe MarketDataAdapter on paper trade creation (best-effort)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: schedule MarketDataAdapter.subscribe instead of awaiting (avoid 'await' outside async)

Co-authored-by: Cursor <cursoragent@cursor.com>

* log: MarketDataAdapter.subscribe start/complete for better visibility

Co-authored-by: Cursor <cursoragent@cursor.com>

* feature: PositionManager.auto-subscribe MarketDataAdapter on trade creation (best-effort)

Co-authored-by: Cursor <cursoragent@cursor.com>

* log: PositionManager subscribe failure to INFO for visibility

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: ensure smoke_trade schedules MarketDataAdapter.subscribe for test token

Co-authored-by: Cursor <cursoragent@cursor.com>

* feature: auto-subscribe MarketDataAdapter on signal accept (best-effort)

Co-authored-by: Cursor <cursoragent@cursor.com>

* telemetry: update market_data_active_subscriptions gauge on subscribe/unsubscribe

Co-authored-by: Cursor <cursoragent@cursor.com>

* admin: add market-data admin subscribe endpoint (best-effort)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: remove improper 'global _market_data_adapter' causing SyntaxError; ensure subscribe scheduling uses module var

Co-authored-by: Cursor <cursoragent@cursor.com>

* ops: enable RTDS provider by default (MARKET_DATA_RTDS_ENABLED=true) to increase live data coverage

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(market-data): bootstrap/reconcile subscriptions from open trades; reconcile loop + heartbeat

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(market-data): add reconcile logic with refcount + flap guard; auto subscribe/unsubscribe

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(market-data): reconcile unsubscribe + refcount flap-guard unit tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: ensure local src in PYTHONPATH for CI

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(market-data): subscriptions view + configurable reconcile missing_threshold; export reconcile state/desire map

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(market-data): subscriptions view endpoint returns tokens + refcounts + missing cycles

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(logging): correct string quoting in reconcile scheduling logs

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(market-data): secure subscriptions view behind DEBUG_ENDPOINTS + token; add message-flow verification warning (no msgs while subs>0)

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: enable debug endpoints in subscriptions view test

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(docs): note on debug endpoints security; add README usage line

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add trade performance reporting CLI + tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(research): use timezone.utc for portability on Windows

Co-authored-by: Cursor <cursoragent@cursor.com>

* research: treat realized_pnl records as closed when closed_at missing (fallback to opened_at)

Co-authored-by: Cursor <cursoragent@cursor.com>

* research: timezone fallbacks for generate_markdown (avoid tzdata requirement)

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(timeframe): add timeframe settings + helper; timing gates in FastEntryEngine; tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(timeframes): ensure local src on PYTHONPATH for CI

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add BTC Up/Down timeframe 15m/5m usage and env flags to README

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(market-data): robust ws connected checks in polymarket_ws provider; queue subscribes when disconnected (avoid AttributeError)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(provider): split handshake vs subscribe op; add raw message telemetry; add tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(provider): send operation subscribe when websocket already connected

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(market-discovery): add btc_updown finder (slug + events fallback); fix(ws): telemetry counters + flush subscribe op; add tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(market-discovery): derive 5m slug from signal_id when available

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(admin): add debug discover-subscribe endpoint + tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(admin): patch health_routes discovery symbol in tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(admin): bind adapter/telemetry to app.state; use app.state in debug endpoints

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ws): handle batched WS frames and improve parse error telemetry

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(ws): extract dict message handling to _handle_dict_msg and use method for batches

Co-authored-by: Cursor <cursoragent@cursor.com>

* telemetry: count parsed dicts + unknown etype counter and one-sample logging per connection

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ws): add custom_feature flag to subscribe messages; handle best_bid_ask events and message counters

Co-authored-by: Cursor <cursoragent@cursor.com>

* robust(adapter): guard MarketDataAdapter import/instantiation and surface import errors in health route

Co-authored-by: Cursor <cursoragent@cursor.com>

* WS provider: nested payload mapping + unknown sample capture

Co-authored-by: Cursor <cursoragent@cursor.com>

* WS provider: capture raw & parse-error samples, expose getters; admin endpoint returns samples; tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* WS provider: expose debug samples (raw/parse/unknown), adapter passthrough, admin endpoint returns samples; tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* market_data: support Polymarket best_bid_ask as book events; parse floats/timestamps; expose samples; tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* analysis: add paper trade analysis CLI; order_executor: add entry filters A/B and telemetry; settings defaults; bucketing tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* FastExit: implement TP/SL/TimeStop/MaxHold (A/B variant); integrate into engine; settings + telemetry + tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* Conservative sizing enforcement for A/B variant; map best_bid_ask to quote; fast-exit integration; tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* AB router helper + analyze CLI AB-split support + tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* AB: variant entry filter wiring + tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* Subscribe-on-signal + keepalive tokens; reconcile includes pending/keepalive tokens

Co-authored-by: Cursor <cursoragent@cursor.com>

* reconcile: update subscriptions gauge after actions; health uses adapter._subs for active_subscriptions

Co-authored-by: Cursor <cursoragent@cursor.com>

* tests: health uses adapter._subs; add telemetry_helpers + unit tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* rtds/ws: robust ws open check; unsubscribe best-effort; add tests for ws compatibility

Co-authored-by: Cursor <cursoragent@cursor.com>

* tests: adapter.unsubscribe best-effort increments telemetry on provider failure

Co-authored-by: Cursor <cursoragent@cursor.com>

* market_discovery: prefer payload.window_end_ms for slug derivation; add payload-based slug derive helper and tests; webhook: prefer payload-derived slug for pending confirmation subscribe

Co-authored-by: Cursor <cursoragent@cursor.com>

* debug: add NDJSON debug logger + instrumentation points for confirmation/subscribe/paper logs; enable via DEBUG_NDJSON_LOG

Co-authored-by: Cursor <cursoragent@cursor.com>

* debug: auto-subscribe pending confirmation tokens via app.state.market_data_adapter; NDJSON H2a/H2b instrumentation

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix market-data adapter + quote cache + confirm flow

* Add gitignore for local runtime files

* fix: address trading bot issues with discover-subscribe, confirm CLOSE, and caching

- Fix /market-data/admin/discover-subscribe endpoint to fallback to module-level
  _market_data_adapter when app.state is not set (fixes adapter_unavailable issue)
- Fix /confirm endpoint to accept CLOSE action as alias for EXIT
- Fix indentation error in schema.py from_raw method
- Add tests for confirm CLOSE action, quote/price_change caching, and orphan cleanup

Fixes:
1. adapter_unavailable problem in discover-subscribe endpoint
2. /confirm accepts only ADD|HEDGE|EXIT, not CLOSE
3. quote/price_change events best_bid/best_ask caching
4. Trades EXITED through orphan cleanup (verified existing checks)

* Fix: Quote->Cache, Test-Fixes, Confirm-Flow, active_subscriptions

- OrderBookSnapshot.from_raw() already handles best_bid/best_ask fallback correctly
- Fix test_parse_price_change_message: expect 'quote' not 'price_change'
- Fix test_admin_endpoint_returns_samples: add monkeypatch for settings
- Fix test_subscriptions_view_reports_tokens: add monkeypatch for settings
- Fix get_active_trades_summary: include CONFIRMED status for reconcile
- Fix orphan_file_cleanup: remove immediate startup call, add initial delay
- Confirm-Flow: EXIT action already supported in /confirm endpoint

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Trading Bot <bot@example.com>
@github-actions github-actions bot force-pushed the automation/bot-auto-pr branch from 4d935ad to c0c1102 Compare February 17, 2026 04:20
detect_to_ack_ms = t_order_ack - t_detect

# Record latency stats
self.latency_stats.record(detect_to_send_ms, send_to_ack_ms, detect_to_ack_ms)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latency recorder called with wrong arguments

High Severity

FastEntryEngine calls self.latency_stats.record() with three values, but LatencyStats.record accepts only two. This raises a runtime TypeError during successful Leg1 execution and drops into the failure path, so entries can be marked failed after order placement.

Additional Locations (1)

Fix in Cursor Fix in Web

try:
from agents.polymarket.websocket_client import PolymarketWebSocketClient, WEBSOCKETS_AVAILABLE
if WEBSOCKETS_AVAILABLE:
self.ws_client = PolymarketWebSocketClient()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WebSocket mode cannot initialize correctly

Medium Severity

FastEntryEngine imports WEBSOCKETS_AVAILABLE and later calls self.ws_client.start(...), but agents/polymarket/websocket_client.py defines neither WEBSOCKETS_AVAILABLE nor start/stop. The use_websocket path is effectively broken and cannot run as implemented.

Additional Locations (2)

Fix in Cursor Fix in Web


# Log rolling stats every N trades
if self.stats["leg1_filled"] % self.stats_log_interval == 0:
self.latency_stats.log_stats(self.stats["leg1_filled"])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latency stats logging method is missing

Medium Severity

FastEntryEngine calls self.latency_stats.log_stats(...), but LatencyStats does not implement log_stats. Once leg1_filled reaches the logging interval, this raises AttributeError inside _execute_leg1 and diverts the success path into error handling.

Additional Locations (1)

Fix in Cursor Fix in Web

market_id=market_id,
)

self.active_entries[entry_id] = entry
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Active entries never removed from memory

Medium Severity

Each Leg1 attempt is stored in self.active_entries, but there is no removal on fill, failure, timeout, or stop. This creates unbounded in-memory growth and makes get_stats() report ever-increasing active_entries that no longer represent active state.

Fix in Cursor Fix in Web

raise RuntimeError("Direct execute_order calls are forbidden. Use OrderExecutor.place_entry_order_with_gate()")
except Exception:
# If settings import fails, proceed (fail-open)
pass
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entry gate enforcement is silently bypassed

High Severity

execute_order raises when ENTRY_GATE_ENFORCE_POLY is enabled and gate_checked is false, but that RuntimeError is immediately swallowed by the surrounding except Exception. This makes the enforcement path ineffective and still submits the order.

Fix in Cursor Fix in Web

id: check-secrets
run: |
if [ -n "$DEPLOY_HOST" ] && [ -n "$DEPLOY_SSH_KEY" ]; then
echo "has_secrets=true" >> $GITHUB_OUTPUT
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy secret validation misses required fields

Medium Severity

The deploy gate only checks DEPLOY_HOST and DEPLOY_SSH_KEY, but deployment later requires DEPLOY_USER and DEPLOY_TARGET too. The workflow can proceed with incomplete configuration and run rsync with empty destination components, causing avoidable deploy failures.

Additional Locations (1)

Fix in Cursor Fix in Web

if pnl_move >= tp:
telemetry.incr("fast_exit_tp_total", 1)
# perform exit
res = self.exit_trade(trade.trade_id, current_price, "fast_tp", exit_request_id=f"fast_tp_{int(now*1000)}")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fast exit IDs can collide across trades

Medium Severity

evaluate_fast_exit builds exit_request_id values from only reason and timestamp, so simultaneous exits can share the same ID. In exit_trade, idempotency is checked after trade.closing is set, so a collided ID can make a different trade return early as already handled while staying stuck in closing state.

Additional Locations (2)

Fix in Cursor Fix in Web

- name: Run tests (pytest)
run: |
if command -v pytest >/dev/null 2>&1; then
pytest -q || true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test failures do not block PR creation

Medium Severity

The lint and test steps use || true, so failures in black, flake8, or pytest do not fail the test-and-lint job. create-pr still runs via needs, allowing automated PRs to be created even when checks fail.

Fix in Cursor Fix in Web

* Clarify /market-data/health readiness semantics in README

* Remove pysha3 dependency to fix Ubuntu Py3.11 CI builds

* Stabilize market-data adapter init/reconcile and guard dependency-review on forks

* Fix Windows install by removing pysha3-prone dependency

* Fix discover-subscribe/reconcile adapter wiring and add integration coverage

* Add debug config endpoint and webhook decision tracing
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 8 potential issues.

Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before Autofix could start.

timestamp_ms=self._now_ms(),
price=price,
best_bid=best_bid or price,
best_ask=best_ask or price,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Falsy-check on best_bid/best_ask drops valid zero prices

Medium Severity

best_bid or price and best_ask or price use truthiness to fall back to price, but 0.0 is a valid Polymarket price that is falsy. This silently replaces legitimate 0.0 bid/ask values. The code above correctly uses is not None checks, but these lines undo that care.

Fix in Cursor Fix in Web

@dataclass
class OrderBookUpdate:
bids: list[OrderBookLevel]
asks: list[OrderBookLevel]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OrderBookUpdate missing fields used in WebSocket callback

High Severity

OrderBookUpdate only defines bids and asks fields, but the WebSocket callback in FastEntryEngine accesses update.mid_price, update.timestamp_ms, update.best_bid, update.best_ask, and update.token_id. These attributes don't exist on the dataclass, so WebSocket mode will crash with AttributeError on every update.

Additional Locations (1)

Fix in Cursor Fix in Web

from pathlib import Path

def main():
base = Path("c:/Users/sefa1/agents")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded local Windows path in aggregate script

Medium Severity

base = Path("c:/Users/sefa1/agents") is a hardcoded local Windows filesystem path. This script will silently find no files on any other machine, making it non-functional for all other developers and in CI.

Fix in Cursor Fix in Web

"path": "../polymarket_btc_bot/.venv"
}
]
} No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Local workspace file committed with developer-specific paths

Low Severity

This workspace file references relative paths to a sibling directory (../polymarket_btc_bot/polymarket_btc_bot) and a virtual environment (../.venv), which are specific to a developer's local setup. This file and the duplicate newagents.code-workspace / agents.code-workspace appear to be personal IDE configuration that doesn't belong in the repository.

Fix in Cursor Fix in Web

logger.warning(
f"Market {market_id} already locked by trade {existing_trade_id}"
)
return None
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Market lock only blocks PENDING, not other active states

High Severity

The market lock in create_trade only prevents new trades when the existing trade's status is PENDING. If a trade has been confirmed, sized up (ADDED), or hedged (HEDGED), a new trade is created for the same market, overwriting market_locks. This orphans the existing active trade's lock reference, and when the old trade exits it deletes the new trade's lock entry, corrupting state.

Fix in Cursor Fix in Web

else:
return {"ok": False, "scheduled": False, "reason": "adapter_unavailable"}
except Exception as e:
return {"ok": False, "error": str(e)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admin subscribe endpoint missing authentication check

Medium Severity

The /market-data/admin/subscribe endpoint has no DEBUG_ENDPOINTS_ENABLED or token authentication check, unlike the sibling admin endpoints /market-data/subscriptions and /market-data/admin/discover-subscribe which both enforce _require_debug_access. Any unauthenticated caller can trigger subscriptions to arbitrary token IDs.

Fix in Cursor Fix in Web

echo "Deploying to $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_TARGET (port $PORT) using rsync with .deployignore"
# Prefer using .deployignore in repo root to control excludes.
if [ -f .deployignore ]; then
rsync -az --delete --exclude-from='.deployignore' -e "ssh -p $PORT -o StrictHostKeyChecking=yes" . "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_TARGET"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy rsync --delete destroys runtime state files on target

High Severity

The rsync --delete command removes target-side files that aren't in the source checkout and aren't excluded. Runtime state files like position_state.json, paper_trades.jsonl, pending_confirmations.json, and data/risk_state.json are not listed in .deployignore, are not in git (gitignored), and therefore don't exist in the source. Every deploy would wipe all active trade state, paper trade history, risk kill-switch state, and pending confirmations from the production server.

Additional Locations (1)

Fix in Cursor Fix in Web

set_if("MAX_SPREAD_PCT_VARIANT", lambda v: parse_float(v, settings.MAX_SPREAD_PCT_VARIANT))
set_if("MIN_EDGE_CENTS_VARIANT", lambda v: parse_float(v, settings.MIN_EDGE_CENTS_VARIANT))
set_if("MAX_ENTRY_PRICE_VARIANT", lambda v: parse_float(v, settings.MAX_ENTRY_PRICE_VARIANT))
set_if("SUBSCRIBE_KEEPALIVE_SECONDS", lambda v: parse_int(v, getattr(settings, "SUBSCRIBE_KEEPALIVE_SECONDS", 180)))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTC timeframe env vars documented but never loaded

Medium Severity

_load_from_env is missing set_if calls for BTC_UPDOWN_TIMEFRAME_MINUTES, BTC_UPDOWN_ENABLE_5M, and MARKET_DATA_RTDS_ENABLED (among others), even though the README documents them as environment-configurable. Setting BTC_UPDOWN_TIMEFRAME_MINUTES=5 in the environment has no effect — the bot always uses 15-minute markets. Similarly, MARKET_DATA_RTDS_ENABLED=0 cannot disable the RTDS provider, which defaults to enabled.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant