Skip to content

feat(core): wire SpeculationEngine into agent loop via SpeculativeConfig#3640

Merged
bug-ops merged 1 commit intomainfrom
3636-wire-speculation-engine
May 6, 2026
Merged

feat(core): wire SpeculationEngine into agent loop via SpeculativeConfig#3640
bug-ops merged 1 commit intomainfrom
3636-wire-speculation-engine

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

@bug-ops bug-ops commented May 6, 2026

Summary

  • SpeculationEngine was fully implemented in crates/zeph-core/src/agent/speculative/ but never instantiated; SpeculativeConfig was read from TOML but silently ignored (feat: wire SpeculationEngine into agent loop via SpeculativeConfig #3636)
  • Add speculation_engine: Option<Arc<SpeculationEngine>> to Services (same pattern as taco_compressor, goal_accounting)
  • Add with_speculation_engine() builder method and tool_executor_arc() getter on Agent<C>
  • Bootstrap in src/runner.rs after all add_tool_executor calls (critical: ensures the captured executor Arc includes the full tool chain including scheduler); gated on mode != Off && !exec_mode.bare
  • Call engine.end_turn() at every turn boundary using std::mem::take (single lock, no TOCTOU)
  • Remove #![allow(dead_code)] from crates/zeph-core/src/agent/speculative/mod.rs
  • 6 new unit tests; 8913/8913 tests pass

Deferred to follow-up PRs

  • try_dispatch integration (decoding-level streaming hook into SSE ToolStream events)
  • PASTE pattern dispatch at skill activation
  • ToolStartEvent.speculative: true for committed handles
  • TUI spinner integration

Follow-up issues to file

  • requires_confirmation_erased unsafe default (security finding — deferred)
  • Sweeper fallback broken abort path (security finding — deferred)

Test plan

  • cargo +nightly fmt --check — PASS
  • cargo clippy --all-targets --workspace -- -D warnings — PASS
  • cargo nextest run --config-file .github/nextest.toml --workspace --lib --bins — 8913/8913 PASS
  • cargo build --features full — PASS
  • git diff origin/main --name-only — only 6 files, all related to feat: wire SpeculationEngine into agent loop via SpeculativeConfig #3636

Closes #3636

…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
@github-actions github-actions Bot added documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate enhancement New feature or request size/M Medium PR (51-200 lines) labels May 6, 2026
@bug-ops bug-ops enabled auto-merge (squash) May 6, 2026 10:10
@bug-ops bug-ops merged commit 02a6f35 into main May 6, 2026
32 checks passed
@bug-ops bug-ops deleted the 3636-wire-speculation-engine branch May 6, 2026 10:16
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core zeph-core crate documentation Improvements or additions to documentation enhancement New feature or request rust Rust code changes size/M Medium PR (51-200 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: wire SpeculationEngine into agent loop via SpeculativeConfig

1 participant