feat(tools): tool dependency graph for sequential tool availability#2059
Merged
feat(tools): tool dependency graph for sequential tool availability#2059
Conversation
…2024) Adds `requires` (hard gate) and `prefers` (soft score boost) per-tool dependency rules in `[tools.dependencies]` config block. - `ToolDependencyGraph` with DFS cycle detection: all cycle participants have `requires` cleared to prevent permanent deadlock - Deadlock fallback: when all non-always-on tools would be blocked by unmet dependencies, gates are disabled for the current turn - `apply()` as a composable post-filter step separate from `filter()` - Preference boost capped at `max_total_boost` to prevent score inflation - `completed_tool_ids: HashSet<String>` tracks successful completions session-scoped, cleared on `/clear` - Dependency gates applied after TAFC augmentation (MED-04) - Always-on and name-mentioned tools bypass hard dependency gates - Iteration 1+ in native tool loop re-applies hard gates via `filter_tool_names()` with deadlock fallback - Config: `[tools.dependencies]` with `enabled`, `boost_per_dep` (0.15), `max_total_boost` (0.20), `rules` map per tool - ~25 unit tests covering cycle detection, deadlock fallback, boost cap, always-on bypass, and multi-dep gates
) HIGH-01: detect_cycles() was marking all DFS ancestors of a cycle as cycled, unnecessarily clearing `requires` for tools that only lead to a cycle but are not part of it. Fixed by searching the stack for the cycle entry point and only marking nodes from that position onward. HIGH-02: NameMentioned tools were bypassing hard dependency gates, allowing users to force access to gated tools by mentioning their name in a query. Fixed by restricting gate bypass to AlwaysOn tools only. NameMentioned tools now respect `requires` constraints. Also adds multi-turn integration tests (task #4): - Linear 2-step and 3-step dependency chains - Multi-requires AND gate (both prerequisites needed) - Preference boost accumulation across turns - filter_tool_names unlock/gate semantics - Separate integration test file: crates/zeph-tools/tests/dependency_chains.rs Regression tests added for both HIGH findings.
2cef432 to
0a93ca3
Compare
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
Implements issue #2024 — per-tool
requires(hard gate) andprefers(soft score boost) dependency rules so tools can declare ordering constraints without hardcoding execution sequences.ToolDependencyGraphinzeph-tools: DFS cycle detection clearsrequiresfor all cycle participants;apply()composable post-filter step;filter_tool_names()for iteration-1+ gating; preference boost capped atmax_total_boostrequires, gates are disabled for that turn so the agent is never fully stalledrequiresclearedapply()as composable post-filter (HIGH-03): separated fromfilter()signature; called afterfilter()inassembly.rsmax_total_boostcap (HIGH-04):min(boost_per_dep * met_count, max_total_boost); default 0.20dep_graph.apply()called after TAFC augmentation inrebuild_system_prompt()completed_tool_ids:HashSet<String>inAgent, cleared inclear_history(), populated on successful tool completion innative.rs[tools.dependencies]withenabled,boost_per_dep(0.15),max_total_boost(0.20),rulesmapTest plan
schema_filter.rs: cycle detection, deadlock fallback, boost cap, always-on bypass, multi-dep gates,filter_tool_namescargo +nightly fmt --check— cleancargo clippy --workspace --features full -- -D warnings— cleancargo nextest run --config-file .github/nextest.toml --workspace --features full --lib --bins— 6103 tests passedorigin/mainbefore pushCloses #2024