Skip to content

feat(autopilot-svm) PR08: Solana seam implementations and a single auction cycle - #4750

Merged
squadgazzz merged 4 commits into
mainfrom
ilya/be-184-pr08-seam-implementations-single-auction-cycle
Aug 20, 2026
Merged

feat(autopilot-svm) PR08: Solana seam implementations and a single auction cycle#4750
squadgazzz merged 4 commits into
mainfrom
ilya/be-184-pr08-seam-implementations-single-auction-cycle

Conversation

@squadgazzz

@squadgazzz squadgazzz commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Description

The chain-generic loop from #4709 gets its Solana implementations, and the whole thing runs one real cycle end to end: wake on a new slot, cut the auction from the indexer-written tables, fan it out to the drivers, rank with the generic arbitrator (winner-selection instantiated with chain_types::Solana, max_winners = 1), and dispatch /settle to the winner's driver.

Two deviations from the Linear issue text worth noting here explicitly:

  • The trigger is chain-driven (slot polling via cow-solana-rpc, which gains its first helper, slot()), not a solana_new_order NOTIFY. On a 400ms-slot chain the next tip wake is at most half a second away, so an order notify buys nothing, and the auction dedupe already suppresses no-change cycles.
  • The arbitrator prices every auction token at the native denominator (1:1 to lamports), so scores compare raw surplus. Native price estimation does not exist yet. Ranking within one token pair is exact, comparisons across pairs are not, which covers the demo.

Known demo-scope stubs, each marked in code: the observer only logs (no competition tables exist), auction ids are process-local unix seconds (no auctions table), solve/submission deadlines are consts until the config PR, and the tip observed after ranking equals the cut tip (the trigger only polls inside next_cycle), which stays inert while the submission deadline is only logged.

Changes

  • domain/cycle.rs binds the loop vocabulary: tip = slot, uid = intent hash, plus driver attribution that survives ranking ((solver, solution id) back to the driver index)
  • domain/arbitrator.rs runs the generic fair-combinatorial arbitrator, marking auction orders via empty fee-policy entries
  • infra/trigger.rs polls the slot and wakes the loop once per new one
  • infra/provider.rs cuts auctions from solana.orders (the freshness check against the indexer watermark waits for BE-203, today the watermark stalls between settlements and would false-alarm)
  • infra/competition.rs fans /solve out to all drivers and joins wire solutions against the auction for limits and sides
  • The solve deadline is enforced on the fan-out, a driver answering past it is dropped for the cycle
  • infra/executor.rs dispatches /settle to each winner's driver, detached
  • Duplicate (solver, solution id) pairs are dropped before ranking, a collision would misdispatch the settlement
  • The auction carries the slot it was cut at, excluded from the dedupe equality like the id

How to test

New DB-backed mock-cycle test (the BE-184 checkpoint): a seeded open order, a canned axum driver, one run_cycle, and the /settle request asserted, plus stage asserts that localize a failure to cut, solve, or ranking.

@linear-code

linear-code Bot commented Aug 18, 2026

Copy link
Copy Markdown

BE-184

Base automatically changed from ilya/be-183-pr07-driver-client to main August 18, 2026 08:50
@squadgazzz

Copy link
Copy Markdown
Contributor Author

@claude , review, please

@claude

claude Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @squadgazzz's task in 4m 35s —— View job


Review

Solid, well-documented PR — the seam implementations map cleanly onto the generic loop's traits, the code comments carry the rationale, and the deliberate stubs (native 1:1 pricing, log-only observer, const deadlines, process-local auction ids) are all called out in code and in the description. Nice touches: the (solver, solution id) dedup aligning with the arbitrator's internal SolutionKey, the join helper handling path-prefixed driver URLs, the DB-backed cycle test with stage probes, and the corrupt-row-skip in auction assembly.

Three points raised inline, none blocking:

  1. provider.rs — the "reports when the indexed state trails the tip" behavior from the description doesn't appear to be wired: sync_to_tip is a no-op and db::last_indexed_slot is unused, so an auction can be cut from a slot the indexer hasn't reached yet with no warning. sync_to_tip looks like the intended home.
  2. competition.rs — the solve fan-out is bounded only by the 30s HTTP client timeout, not SOLVE_DEADLINE_SLOTS; a slow driver can stall the sequential loop and late responses are still ranked. Fine to defer, but the solve deadline isn't enforced on our side today.
  3. trigger.rs (minor) — current_tip doesn't advance mid-cycle since polling only runs inside next_cycle, so the deadline the loop derives "after ranking" is really the cut tip. Inert for now since deadlines are only logged.

Also observed (no change requested): dto::Solution.score and db::settlements_by_auction are deserialized/defined but unused yet — expected given they're staged for later PRs and covered by #![expect(dead_code)].
· branch ilya/be-184-pr08-seam-implementations-single-auction-cycle

Comment thread crates/autopilot-svm/src/infra/provider.rs
Comment thread crates/autopilot-svm/src/infra/competition.rs
Comment thread crates/autopilot-svm/src/infra/trigger.rs
@squadgazzz
squadgazzz marked this pull request as ready for review August 18, 2026 13:42
@squadgazzz
squadgazzz requested a review from a team as a code owner August 18, 2026 13:42
@squadgazzz
squadgazzz requested a review from tilacog August 18, 2026 13:42
@claude

claude Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @squadgazzz's task in 4m 21s —— View job


Re-review

  • Gather context (read all 18 changed files + run_loop.rs and winner-selection seams)
  • Review domain layer (cycle, arbitrator, auction)
  • Review infra layer (provider, competition, executor, trigger, observer, db, driver)
  • Review tests
  • Verify the three prior review points

All three points from my earlier review are now resolved on this branch:

  1. Solve deadline enforcement (competition.rs) — the fan-out is now bounded by tokio::time::timeout(SLOT_DURATION * SOLVE_DEADLINE_SLOTS, …) per driver via join_all, so late/hung drivers are dropped and one driver can no longer hold the loop for the 30s HTTP ceiling. ✅ (da51d5ee2)
  2. Indexer staleness / sync_to_tip (provider.rs) — the freshness guard is now explicitly deferred to BE-203 and the PR description no longer claims the provider reports the trailing watermark; the stub is marked. ✅ (1026ef120)
  3. current_tip freshness (trigger.rs) — now carries a TODO documenting that the tip doesn't advance mid-cycle until background polling lands, so the "after ranking" tip equals the cut tip. ✅

I re-verified the trickier seams and they hold up:

  • The arbitrator only filters/marks the input solutions (no synthetic combined solutions), and it preserves solver/id, so the (solver, solution id) → driver-index attribution in executor.rs can't miss a legitimate winner.
  • compute_order_score needs the buy token's native price; arbitrator.rs seeds both sell and buy tokens at NATIVE_PRICE_DENOMINATOR, so no missing-price path, and wrapped_native is only used for token-pair grouping (no price lookup), so the test's throwaway wrapped_native is safe.
  • The finalized_slot/singleton defaults in solana.indexer_state make the test's slot-only insert valid.

No new blocking issues found — nothing I'd hold the PR on, so no inline comments this round. One minor, non-blocking note for awareness (no change needed for the demo): the enforced timeout in competition.rs is wall-clock measured from the solve() call, while the deadline handed to drivers is the slot auction.tip + SOLVE_DEADLINE_SLOTS. Because cut+dedupe elapse between observing the tip and calling solve, our local cutoff sits slightly later than the slot deadline the driver was given, so a response landing just past its stated slot deadline is still accepted. The gap is sub-millisecond in practice and disappears once deadlines become tip-aligned + configurable, so it's inert here — just flagging that "the deadline sent to the drivers is also enforced here" is an approximation rather than an exact match.

Nice work on the follow-ups.
· branch ilya/be-184-pr08-seam-implementations-single-auction-cycle

Comment thread crates/autopilot-svm/src/tests.rs Outdated
Comment thread crates/autopilot-svm/src/tests.rs Outdated
Comment thread crates/autopilot-svm/src/tests.rs
Comment thread crates/autopilot-svm/src/tests.rs Outdated
Comment thread crates/autopilot-svm/src/tests.rs
Comment thread crates/autopilot-svm/src/infra/db.rs Outdated
Comment thread crates/autopilot-svm/src/infra/competition.rs Outdated
Comment thread crates/autopilot-svm/src/infra/competition.rs
Comment thread crates/autopilot-svm/src/infra/competition.rs Outdated
Comment thread crates/autopilot-svm/src/infra/competition.rs Outdated
@squadgazzz
squadgazzz force-pushed the ilya/be-184-pr08-seam-implementations-single-auction-cycle branch from 8f29d7e to 5c1b874 Compare August 19, 2026 11:14

@jmg-duarte jmg-duarte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚀

@squadgazzz
squadgazzz added this pull request to the merge queue Aug 20, 2026
@squadgazzz
squadgazzz removed this pull request from the merge queue due to a manual request Aug 20, 2026
@squadgazzz
squadgazzz enabled auto-merge August 20, 2026 09:55
@squadgazzz
squadgazzz added this pull request to the merge queue Aug 20, 2026
Merged via the queue into main with commit 079cdd6 Aug 20, 2026
38 of 39 checks passed
@squadgazzz
squadgazzz deleted the ilya/be-184-pr08-seam-implementations-single-auction-cycle branch August 20, 2026 10:39
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants