feat(tools,core): OS sandbox (#2808) + speculative tool dispatch (#2290, #2409)#3068
Merged
feat(tools,core): OS sandbox (#2808) + speculative tool dispatch (#2290, #2409)#3068
Conversation
This was
linked to
issues
Apr 16, 2026
…, #2409) Adds platform-native subprocess isolation (ShellExecutor sandbox) and two complementary speculative tool dispatch strategies to reduce tool-call latency. ## OS-level subprocess sandbox (issue #2808) - macOS: rewrites command as `sandbox-exec -f <profile>.sb -- <cmd>`. Profile generated per-call from SandboxPolicy (deny-default, explicit allow_read/allow_write paths, optional network). NamedTempFile pool prevents per-call leaks; no FFI, no sandbox_init. - Linux (feature = "sandbox"): rewrites as `bwrap <ns-flags> <bind-mounts> --seccomp <fd> -- <cmd>`. Landlock FS rules applied on a throw-away thread. seccomp BPF denylist (16 privilege-escalation syscalls) compiled once, dual-arch. OwnedFd slot prevents raw fd leak between wrap() and spawn(). - NoopSandbox fallback logs WARN and passes through unchanged. - SandboxPolicy paths canonicalized at construction (symlink/.. bypass fix). - macOS profile never grants /private/tmp, /var/folders, or /private/etc. - Wired at all three bootstrap sites: agent_setup.rs, daemon.rs, acp.rs. ## Speculative tool dispatch (issues #2290, #2409) - Decoding-level (SpeculationMode::Decoding, #2290): PartialJsonParser streams SSE input_json_delta events and fires the tool call as soon as required schema fields are present. Operates on raw bytes; serde_json::from_slice for UTF-8-safe string decoding (fixes Cyrillic/CJK/emoji corruption from b-as-char Latin-1 cast). - Pattern-level (SpeculationMode::Pattern, #2409 PASTE): PatternStore (SQLite) records invocation sequences and predicts next tool. Temporal decay in Rust via f64::powf (avoids SQLite pow() requiring SQLITE_ENABLE_MATH_FUNCTIONS). - SpeculationEngine: synchronous try_dispatch with pure requires_confirmation check (no double side-effects). Sweeper shares the same CacheInner Arc. cancel_for cancels by tool_id. Migration 074 adds SQLite + Postgres schemas.
5ef1c8f to
fb72e34
Compare
…ortable build_sandbox
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
#2808): platform-native isolation for all shell commands viaShellExecutor.with_sandbox(). macOS usessandbox-execSeatbelt, Linux usesbwrap+ Landlock + seccomp BPF, other platforms fall back toNoopSandbox.#2290,#2409):SpeculationEnginewith two strategies — decoding-level (fire on first complete JSON fields from SSE stream) and pattern-level PASTE (SQLite-backed invocation history predicts next tool).OS sandbox details
sandbox-execSeatbelt.sbprofile generated per-callsandboxfeature)bwrap+ Landlock + seccompNoopSandboxSecurity invariants:
SandboxPolicy::canonicalized()strips symlinks and..at construction/private/tmp,/var/folders,/private/etc#[cfg(target_arch)]— correct on both x86_64 and aarch64OwnedFdslot inLinuxSandboxkeeps BPF fd alive fromwrap()tospawn()NamedTempFilepool inMacosSandbox— no per-callmem::forgetConfig (
[tools.sandbox]):Speculative dispatch details
SpeculationMode::Decoding(research(performance): speculative tool calls — overlap LLM decoding with execution, 100s tok/s latency gain (arXiv:2512.15834) #2290):PartialJsonParser(byte-level structural state machine) extracts top-level JSON leaves from partial SSE stream; dispatches when required fields completeSpeculationMode::Pattern(research(performance): PASTE application-level speculative tool execution — 48.5% latency reduction, 1.8x throughput (arXiv:2603.18897) #2409 PASTE):PatternStore(SQLite) records(skill, prev_tool) → next_toolsequences; scores via temporal decay (Rustf64::powf, not SQLitepow()) + Wilson lower boundrequires_confirmation_erasedpolicy check before dispatch (no double side-effects); sweeper sharesCacheInnerArc;cancel_forcancels in-flight handles by tool_id074_tool_patterns: SQLite + Postgres schemas for PASTE tablesConfig (
[tools.speculative]):Test plan
cargo build --features sandbox— no errorscargo +nightly fmt --check— cleancargo clippy --workspace --features sandbox -- -D warnings— cleancargo nextest run --workspace --lib --bins— 8042 passedcargo run --features full -- --config .local/config/testing.tomlwith[tools.sandbox] enabled = trueon macOS — shell tool commands execute insidesandbox-execWARN OS sandbox unavailablelogged whensandbox-execabsent andstrict = falseCloses #2808, #2290, #2409