feat(core): wire SpeculationEngine into agent loop via SpeculativeConfig#3640
Merged
feat(core): wire SpeculationEngine into agent loop via SpeculativeConfig#3640
Conversation
…fig (#3636) SpeculationEngine was fully implemented in crates/zeph-core/src/agent/speculative/ but never instantiated. SpeculativeConfig was read from TOML but silently ignored. - Add `speculation_engine: Option<Arc<SpeculationEngine>>` to `Services`, initialized to `None` (same pattern as taco_compressor, goal_accounting) - Add `with_speculation_engine()` builder method on `Agent<C>` with `#[must_use]` - Add `tool_executor_arc()` getter on `Agent<C>` to expose the composed executor Arc to external wiring after all `add_tool_executor` calls complete - Bootstrap in `src/runner.rs` after all `add_tool_executor` registrations (including scheduler) so the captured executor Arc includes the full tool chain; gated on `mode != Off && !exec_mode.bare` to avoid background tasks in minimal sessions - Call `engine.end_turn()` at every turn boundary via `std::mem::take` (single lock, no TOCTOU) to cancel in-flight handles and reset metrics - Remove `#![allow(dead_code)]` from `crates/zeph-core/src/agent/speculative/mod.rs` Deferred to follow-up PRs: try_dispatch integration (decoding-level streaming hook), PASTE pattern dispatch at skill activation, ToolStartEvent `speculative: true` for committed handles, TUI spinner integration. Closes #3636
This was referenced May 6, 2026
Closed
Closed
bug-ops
added a commit
that referenced
this pull request
May 6, 2026
…ion default (#3647) Fixes two bugs found in the security audit of PR #3640: 1. ErasedToolExecutor::requires_confirmation_erased defaulted to false, allowing speculative dispatch without confirmation for any future executor that opts into is_tool_speculatable_erased but forgets to override the gate. Inverted the default to true (safe-by-default). Added requires_confirmation to ToolExecutor (default false) with a blanket impl delegation. TrustGateExecutor overrides requires_confirmation to mirror check_trust. All existing direct ErasedToolExecutor impls updated to explicitly return false. 2. SpeculationEngine::new (supervisor=None branch) used mem::forget on the sweeper JoinHandle and immediately dropped the AbortHandle, leaking the tokio task until runtime shutdown. Replaced the dummy TaskHandle approach with a SweepHandle enum (Supervised(TaskHandle) | Raw(JoinHandle<()>)) that calls abort(self) in Drop. Closes #3644, Closes #3645
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SpeculationEnginewas fully implemented incrates/zeph-core/src/agent/speculative/but never instantiated;SpeculativeConfigwas read from TOML but silently ignored (feat: wire SpeculationEngine into agent loop via SpeculativeConfig #3636)speculation_engine: Option<Arc<SpeculationEngine>>toServices(same pattern astaco_compressor,goal_accounting)with_speculation_engine()builder method andtool_executor_arc()getter onAgent<C>src/runner.rsafter alladd_tool_executorcalls (critical: ensures the captured executor Arc includes the full tool chain including scheduler); gated onmode != Off && !exec_mode.bareengine.end_turn()at every turn boundary usingstd::mem::take(single lock, no TOCTOU)#![allow(dead_code)]fromcrates/zeph-core/src/agent/speculative/mod.rsDeferred to follow-up PRs
try_dispatchintegration (decoding-level streaming hook into SSEToolStreamevents)ToolStartEvent.speculative: truefor committed handlesFollow-up issues to file
requires_confirmation_erasedunsafe default (security finding — deferred)Test plan
cargo +nightly fmt --check— PASScargo clippy --all-targets --workspace -- -D warnings— PASScargo nextest run --config-file .github/nextest.toml --workspace --lib --bins— 8913/8913 PASScargo build --features full— PASSgit diff origin/main --name-only— only 6 files, all related to feat: wire SpeculationEngine into agent loop via SpeculativeConfig #3636Closes #3636