Skip to content

feat(speculation): generator contract and bestfirst impl - #446

Merged
behinddwalls merged 1 commit into
mainfrom
preetam/speculation-generator
Aug 6, 2026
Merged

feat(speculation): generator contract and bestfirst impl#446
behinddwalls merged 1 commit into
mainfrom
preetam/speculation-generator

Conversation

@behinddwalls

@behinddwalls behinddwalls commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Why?

The standard Speculator needs a ranked stream of candidate speculation paths to fund. Nothing enumerates or ranks the path space today.

What?

Adds submitqueue/extension/speculation/generator — the Generator/Iterator contract — plus the bestfirst implementation and mocks.

The generator is a pure enumerator: Generate takes only the queue’s batches and offers every coherent path, including ones whose builds already ran. Suppressing those belongs to the Allocator, which reconciles candidates against stored path sets by ID. The snapshot is a strict contract: every batch a head’s direct dependencies reference must be present, and a snapshot with a missing dependency, empty or duplicate IDs, or a self or repeated dependency errors instead of opening a stream — any defaulting for a batch that is hard to score belongs to the scorer, not the generator.

bestfirst ranks each path by how likely all its assumptions are to hold and generates lazily in two levels: each head enumerates its own paths through a per-head stream — extend/swap moves over a cheapest-first flip list, worked out only when the head is first pulled — and a global heap holds each head’s current best, so pulling k paths does O(k) work however large the space behind them. Scores are summed log probabilities so wide heads cannot underflow into ties, every score is summed fresh from the head’s best score so the ordering holds in floating point as computed, and the extend/swap tree emits each path exactly once in non-increasing score order. The full algorithm, tie-breaks, derivation, and floating-point constraints live in doc/rfc/submitqueue/speculation-generator-best-first.md; the package README records only operational behavior.

Also clarifies scorer.Scorer’s contract as final success: the probability that the batch ultimately succeeds — reaches its terminal Succeeded state with its changes landed — not merely that its build passes. That is the quantity bestfirst consumes: a path’s assumptions resolve at terminal batch states, and a Merging dependency has already passed its build yet can still fail to land.

Test Plan

./tool/bazel test //submitqueue/extension/speculation/...
make fmt
make lint
make check-tidy
make check-gazelle
make check-mocks — fails only on the pre-existing storage/mock/request_batch_store_mock.go header drift that exists on main; the new generator/mock is up to date

@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch 3 times, most recently from c8ec6b1 to 3fb7e2b Compare July 27, 2026 23:14
@behinddwalls
behinddwalls marked this pull request as ready for review July 27, 2026 23:17
@behinddwalls
behinddwalls requested review from a team and sbalabanov as code owners July 27, 2026 23:17
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch 2 times, most recently from 5e0bdbd to 3fb7e2b Compare July 28, 2026 19:13
Comment thread submitqueue/extension/speculation/generator/README.md Outdated
Comment thread submitqueue/extension/speculation/generator/generator.go Outdated
Comment thread submitqueue/extension/speculation/generator/generator.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst_test.go Outdated
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from 3fb7e2b to 5e2ad89 Compare July 29, 2026 18:12
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from 5e2ad89 to 4c727b2 Compare July 29, 2026 18:24
@behinddwalls
behinddwalls requested a review from sbalabanov July 29, 2026 18:41
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from 4c727b2 to ccb1aa4 Compare July 29, 2026 22:31
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch 3 times, most recently from e9e54ca to ee4ab40 Compare July 29, 2026 23:18
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from ee4ab40 to d5dd68b Compare July 29, 2026 23:18
Base automatically changed from preetam/speculation-speculator to main July 30, 2026 01:19
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from d5dd68b to e3d56b0 Compare July 30, 2026 01:19
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch 7 times, most recently from 727009d to 110a679 Compare August 5, 2026 04:57
@behinddwalls
behinddwalls changed the base branch from main to preetam/speculation-generator-rfc August 5, 2026 05:05
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from 110a679 to 60850bb Compare August 5, 2026 17:05
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch 2 times, most recently from 22e1452 to e4f82f3 Compare August 5, 2026 19:05

@sbalabanov sbalabanov 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.

accepting to unblock, please address comments

Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/scorer/scorer.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/bestfirst.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/head.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/head.go Outdated
Comment thread submitqueue/extension/speculation/generator/bestfirst/head.go Outdated
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from e4f82f3 to 334f49e Compare August 6, 2026 02:15
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch 2 times, most recently from ae9aab0 to 28e0ab5 Compare August 6, 2026 03:04
Base automatically changed from preetam/speculation-generator-rfc to main August 6, 2026 03:17
## Summary

### Why?

The standard Speculator needs a ranked stream of candidate speculation paths to fund. Nothing enumerates or ranks the path space today.

### What?

Adds `submitqueue/extension/speculation/generator` — the Generator/Iterator contract — plus the `bestfirst` implementation and mocks.

The generator is a pure enumerator: `Generate` takes only the queue’s batches and offers every coherent path, including ones whose builds already ran. Suppressing those belongs to the Allocator, which reconciles candidates against stored path sets by ID. The snapshot is a strict contract: every batch a head’s direct dependencies reference must be present, and a snapshot with a missing dependency, empty or duplicate IDs, or a self or repeated dependency errors instead of opening a stream — any defaulting for a batch that is hard to score belongs to the scorer, not the generator.

`bestfirst` ranks each path by how likely all its assumptions are to hold and generates lazily in two levels: each head enumerates its own paths through a per-head stream — extend/swap moves over a cheapest-first flip list, worked out only when the head is first pulled — and a global heap holds each head’s current best, so pulling k paths does O(k) work however large the space behind them. Scores are summed log probabilities so wide heads cannot underflow into ties, every score is summed fresh from the head’s best score so the ordering holds in floating point as computed, and the extend/swap tree emits each path exactly once in non-increasing score order. The full algorithm, tie-breaks, derivation, and floating-point constraints live in `doc/rfc/submitqueue/speculation-generator-best-first.md`; the package README records only operational behavior.

Also clarifies `scorer.Scorer`’s contract as final success: the probability that the batch ultimately succeeds — reaches its terminal Succeeded state with its changes landed — not merely that its build passes. That is the quantity bestfirst consumes: a path’s assumptions resolve at terminal batch states, and a Merging dependency has already passed its build yet can still fail to land.

## Test Plan

✅ `./tool/bazel test //submitqueue/extension/speculation/...`
✅ `make fmt`
✅ `make lint`
✅ `make check-tidy`
✅ `make check-gazelle`
✅ `make check-mocks` — fails only on the pre-existing `storage/mock/request_batch_store_mock.go` header drift that exists on `main`; the new `generator/mock` is up to date
@behinddwalls
behinddwalls force-pushed the preetam/speculation-generator branch from 28e0ab5 to 90bdbe3 Compare August 6, 2026 03:17
@behinddwalls
behinddwalls added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit 63f4f56 Aug 6, 2026
15 checks passed
@behinddwalls
behinddwalls deleted the preetam/speculation-generator branch August 6, 2026 03:32
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.

2 participants