Skip to main content

Outgoing trades

Every day, the core trade_candidates job enumerates and scores every 1-for-1, 2-for-1 and 1-for-2 trade across the league. It runs again just before each scan. Twice a week the trade scan takes the best proposable candidates, up to three per team, re-scores each one live, and stages the best as unsent offers. When the candidate set is missing, empty, malformed or more than 36 hours old, the scan falls back to asking an LLM for packages. In both cases the LLM writes the pitch from score evidence, and nothing goes to the other manager until you approve that exact offer. The Trades page browses the same candidate set in its trade finder.

Which stages hold the offer?​

What is involved?​

ItemValue
Triggertrade-scan CronJob, Wednesday and Friday 13:00 Chicago. Regular-season weeks 1–18 only.
Queuetrade_submissions. The approve route publishes directly, without the outbox.
Tablesexecution_log (scan claim, staged offer with proposal-evaluation-v1 evidence, submit claim); bot_decisions (approval audit)
Scan keyOne attempt per league, team and Chicago calendar date, under an advisory lock. There are no automatic retries, because a new pitch would need a new approval.
Approval keyoffer_key: SHA-256 over league, season, both teams, sorted player ids, the note and the related transaction. Editing any of these needs a new approval.
Duplicate approvalReturns 200 with the original receipt and doesn't publish again.
ESPN writePlaywright fills the form. A guard blocks every non-GET ESPN request until the final click.

What must be true to send?​

LockOpen when
TRADE_DRY_RUNExplicitly false, or unset with DRY_RUN explicitly false
TRADE_SUBMIT_ENABLEDtrue, 1 or yes
ApprovalThe message's offer_key equals the key recomputed from the offer
SelectorsEvery submit selector is marked verified in espn_selectors.json
Counter linkageFor a counter only: COUNTER_LINKAGE_VERIFIED is set

With any lock closed, the builder ticks the boxes, checks them, takes a screenshot and stops at submit_blocked.

What if the result is unclear?​

SituationResult
ESPN returns 5xx or 429, or no responseThe builder reads ESPN's pending trades. An exact match settles it as submitted.
No matchPermanentError. A person checks ESPN. The bot never clicks again on a guess.
Core publish outcome unknownThe approval stays approval_pending and blocks new approvals until someone reconciles it by hand.
Core can't score any packageNothing is staged. An unscored offer is never staged.

Read more​