Skip to Content
SimulatorsGitHubReview-bot scenarios

Simulators

Review-bot scenarios

github-pulls_bot_pr_broken and github-pulls_bot_pr_queue hold a Kalshi market-maker bot and pull requests that break it in known ways. A review agent reaches the bot only as diffs, exactly as it meets any code in a pull request. Load the first, read the working bot from the merged pull request and the one-line break from the open one:

H='Authorization: Bearer ghp_anything'
R="$RYSTIC_URL/repos/tb-owner/tb-repo"
curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"github-pulls_bot_pr_broken"}' -o /dev/null
curl -s "$R/pulls?state=all" -H "$H" | jq -c '[.[] | {number, state, merged: (.merged_at != null)}]'
# -> [{"number":8,"state":"open","merged":false},{"number":7,"state":"closed","merged":true}]
curl -s "$R/pulls/7/files" -H "$H" | jq -c '[.[] | {filename, additions}]'
# -> [{"filename":"bots/kalshi_mm/bot.py","additions":158}]
curl -s "$R/pulls/7/files" -H "$H" | jq -r '.[0].patch' | head -1
# -> @@ -0,0 +1,158 @@
curl -s "$R/pulls/8/files" -H "$H" | jq -r '.[0].patch' | head -1
# -> @@ -140,7 +140,7 @@ class MarketMaker:
curl -s "$R/check-runs/6508/annotations" -H "$H" | jq -c '[.[] | {path, start_line, annotation_level}]'
# -> [{"path":"bots/kalshi_mm/bot.py","start_line":143,"annotation_level":"failure"}]

Strip the leading + from #7’s patch and you have bot.py; apply #8’s hunk and you have the broken head. #8 carries a red bot-smoke check run that annotates the broken line.

Running the bot

Run either file against a Kalshi simulator. It needs Python’s requests package:

pip install requests
KALSHI_BASE_URL=http://localhost:8081 TICKER=KXDEMO-26-A SESSION_SECONDS=30 python3 bot.py

bot.py rests a bid and an ask behind the touch on one market, re-quotes as the book moves and never crosses. It stops quoting a side once its position reaches MAX_INVENTORY, though a fill can carry it past by up to QUOTE_SIZE. It cancels everything at SESSION_SECONDS (default 30) or on SIGTERM. It reads its settings only from the environment: KALSHI_BASE_URL, TICKER, QUOTE_SIZE, MAX_INVENTORY and the others its docstring lists.

The same files ship as plain text in the release archive: bots/bot.py, bots/variants/*.py and bots/test_bot.py. The container image does not carry them. The scenario’s patches are generated from those files, so the diffs and the plain text cannot disagree.

test_bot.py runs the working bot for 30 seconds against kalshi-twin --scenario tight_book and requires a bid and an ask resting at once, no crossed quote and nothing left resting. It then runs every variant and requires each to fail that. It boots the kalshi-twin that rystic pull installed, or the binary KALSHI_TWIN_BIN names, or uses the simulator already serving at KALSHI_BASE_URL, and loads tight_book before each bot.

The variants

github-pulls_bot_pr_queue holds the same merged bot, then five open pull requests (#11 to #15) that each break it a different way:

Open pull requestVariantWhat breaksResult on the Kalshi simulator
#8 and #11sides_invertedthe buy leg goes out as ask, the sell leg as bid400 invalid_order: post only cross
#12syntax_errordef requote(self) lost its colonthe file does not compile
#13wrong_endpointorders posted to /trade-api/v2/orders404 not_found
#14price_in_cents"38" where "0.38" was meant400 invalid_price
#15missing_required_fieldself_trade_prevention_type dropped from the body400 missing_parameters

Every one of them has its own red check run and line annotation. Use them to test a grader or a review agent: approving any of them means it missed the bug.

Last updated on