Skip to content

fix(tools): scale adversarial policy timeout by provider type#5881

Merged
bug-ops merged 1 commit into
mainfrom
fix/5870-policy-gate-timeout
Jul 10, 2026
Merged

fix(tools): scale adversarial policy timeout by provider type#5881
bug-ops merged 1 commit into
mainfrom
fix/5870-policy-gate-timeout

Conversation

@bug-ops

@bug-ops bug-ops commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • The fail-closed adversarial policy gate ([tools.adversarial_policy]) used a fixed 3s (5s in testing.toml) timeout for the policy LLM call, well below the 9-32s latency observed with local Ollama models. Every policy check timed out, hit PolicyDecision::Error, and with fail_open = false was denied identically to a genuine policy violation — producing a 100% deny rate on benign tool calls whenever policy_provider pointed at a local model.
  • timeout_ms is now Option<u64> and auto-scales from the resolved policy_provider's kind: 45s for local providers (ollama/candle/compatible — comfortably above the issue's own observed 31928ms worst case), 3s for cloud providers. An explicit timeout_ms still overrides the default.
  • PolicyDecision::Error now carries a timed_out flag so the operator-facing audit log / tracing output can distinguish an infra timeout from a genuine LLM/network error. The message returned to the main LLM's tool-call error is unchanged, preserving the MED-03 opacity requirement (the main LLM cannot tell timeout apart from a real deny).
  • Fixed the same provider-resolved-after-timeout-computed ordering bug in all three gate construction sites (runner.rs, acp.rs, daemon.rs) — the issue referenced only runner.rs.
  • /status's Adv gate: line now also shows the effective timeout_ms.
  • Doc comment, CHANGELOG, and book docs clarify the auto-scaling is keyed on provider type, not endpoint locality — a cloud-typed client pointed at a self-hosted/localhost endpoint still gets the 3s budget and should set timeout_ms explicitly.

Test plan

  • cargo +nightly fmt --check
  • cargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warnings
  • cargo nextest run --config-file .github/nextest.toml --workspace --features "desktop,ide,server,chat,pdf,scheduler" --lib --bins (12443 passed / 0 failed)
  • RUSTFLAGS="-D warnings" RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc --no-deps --workspace --features "desktop,ide,server,chat,pdf,scheduler"
  • cargo test --doc --workspace --features "desktop,ide,server,chat,pdf,scheduler"
  • New unit tests: auto-scaling by provider kind, explicit override preserved, timed_out set correctly on timeout vs. genuine LLM error, MED-03 exact-message invariant on both branches, all three gate-construction sites verified for correct provider-before-timeout ordering

@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate size/L Large PR (201-500 lines) and removed bug Something isn't working labels Jul 10, 2026
@bug-ops
bug-ops enabled auto-merge (squash) July 10, 2026 16:27
@bug-ops
bug-ops force-pushed the fix/5870-policy-gate-timeout branch from 84b0aa4 to 3ee177e Compare July 10, 2026 16:27
@github-actions github-actions Bot added the bug Something isn't working label Jul 10, 2026
The fail-closed adversarial policy gate used a fixed 3s default
timeout for the policy LLM call, well below the 9-32s latency of
local Ollama providers. Every policy check timed out and was denied
as PolicyDecision::Error, which fail_open=false treats identically
to a genuine deny, producing a 100% deny rate on benign tool calls
when policy_provider pointed at a local model.

timeout_ms is now optional and auto-scales from the resolved
policy_provider's kind: 45s for local providers (ollama, candle,
compatible), 3s for cloud providers, with headroom above the
worst-case latency observed for local models. Explicit timeout_ms
values still override the default. PolicyDecision::Error now
carries a timed_out flag so the operator-facing audit log and
tracing output can distinguish a timeout from a genuine LLM/network
error; the message sent back into the main LLM's tool-call error is
unchanged, preserving MED-03's opacity requirement.

Also fixes the same provider-resolved-after-timeout-computed
ordering bug in all three gate construction sites (runner.rs,
acp.rs, daemon.rs), not just the one referenced in the issue.

Closes #5870
@bug-ops
bug-ops force-pushed the fix/5870-policy-gate-timeout branch from 3ee177e to b919856 Compare July 10, 2026 16:37
@bug-ops
bug-ops merged commit 19b4bbe into main Jul 10, 2026
47 checks passed
@bug-ops
bug-ops deleted the fix/5870-policy-gate-timeout branch July 10, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working core zeph-core crate documentation Improvements or additions to documentation rust Rust code changes size/L Large PR (201-500 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant