@@ -827,6 +827,7 @@ async fn test_tool_command_command_type() {
827827 tool_name : "read" . to_string ( ) ,
828828 tool_args : serde_json:: json!( { "file" : "test.rs" } ) ,
829829 skill_registry : None ,
830+ enforce_active_skill_tool_restrictions : false ,
830831 tool_context : test_tool_context ( ) ,
831832 } ;
832833 assert_eq ! ( cmd. command_type( ) , "read" ) ;
@@ -841,11 +842,77 @@ async fn test_tool_command_payload() {
841842 tool_name : "read" . to_string ( ) ,
842843 tool_args : args. clone ( ) ,
843844 skill_registry : None ,
845+ enforce_active_skill_tool_restrictions : false ,
844846 tool_context : test_tool_context ( ) ,
845847 } ;
846848 assert_eq ! ( cmd. payload( ) , args) ;
847849}
848850
851+ #[ tokio:: test]
852+ async fn test_tool_command_ignores_active_skill_restrictions_by_default ( ) {
853+ let registry = crate :: skills:: SkillRegistry :: new ( ) ;
854+ registry. register_unchecked ( Arc :: new ( crate :: skills:: Skill {
855+ name : "read-only" . to_string ( ) ,
856+ description : String :: new ( ) ,
857+ allowed_tools : Some ( "read(*)" . to_string ( ) ) ,
858+ disable_model_invocation : false ,
859+ kind : crate :: skills:: SkillKind :: Instruction ,
860+ content : String :: new ( ) ,
861+ tags : Vec :: new ( ) ,
862+ version : None ,
863+ } ) ) ;
864+
865+ let cmd = ToolCommand {
866+ tool_executor : Arc :: new ( ToolExecutor :: new ( "/tmp" . to_string ( ) ) ) ,
867+ tool_name : "not_a_tool" . to_string ( ) ,
868+ tool_args : serde_json:: json!( { } ) ,
869+ skill_registry : Some ( Arc :: new ( registry) ) ,
870+ enforce_active_skill_tool_restrictions : false ,
871+ tool_context : test_tool_context ( ) ,
872+ } ;
873+
874+ let output = cmd. execute ( ) . await . unwrap ( ) ;
875+ let output = output[ "output" ] . as_str ( ) . unwrap_or_default ( ) ;
876+ assert ! (
877+ !output. contains( "not allowed by any active skill" ) ,
878+ "default mode must let the command reach the tool executor, got: {output}"
879+ ) ;
880+ assert ! (
881+ output. contains( "Unknown tool" ) ,
882+ "default mode should reach the tool executor, got: {output}"
883+ ) ;
884+ }
885+
886+ #[ tokio:: test]
887+ async fn test_tool_command_enforces_active_skill_restrictions_in_legacy_mode ( ) {
888+ let registry = crate :: skills:: SkillRegistry :: new ( ) ;
889+ registry. register_unchecked ( Arc :: new ( crate :: skills:: Skill {
890+ name : "read-only" . to_string ( ) ,
891+ description : String :: new ( ) ,
892+ allowed_tools : Some ( "read(*)" . to_string ( ) ) ,
893+ disable_model_invocation : false ,
894+ kind : crate :: skills:: SkillKind :: Instruction ,
895+ content : String :: new ( ) ,
896+ tags : Vec :: new ( ) ,
897+ version : None ,
898+ } ) ) ;
899+
900+ let cmd = ToolCommand {
901+ tool_executor : Arc :: new ( ToolExecutor :: new ( "/tmp" . to_string ( ) ) ) ,
902+ tool_name : "not_a_tool" . to_string ( ) ,
903+ tool_args : serde_json:: json!( { } ) ,
904+ skill_registry : Some ( Arc :: new ( registry) ) ,
905+ enforce_active_skill_tool_restrictions : true ,
906+ tool_context : test_tool_context ( ) ,
907+ } ;
908+
909+ let err = cmd. execute ( ) . await . unwrap_err ( ) . to_string ( ) ;
910+ assert ! (
911+ err. contains( "not allowed by any active skill" ) ,
912+ "legacy mode must deny before tool execution, got: {err}"
913+ ) ;
914+ }
915+
849916// ========================================================================
850917// AgentLoop with queue builder tests
851918// ========================================================================
0 commit comments