code: function taskCallback(fn) {
  	return fn.length ? taskAsyncCb : taskSyncCb;
  	function taskAsyncCb(cb) {
  		return taskCb(this || {}, arguments, fn, cb, true);
  	}
  	function taskSyncCb() {
  		return taskCb(this || {}, arguments, fn, null, false);
  	}
  	function taskCb(cxt, args, fn, done, isAsync) {
  		cxt.done = isAsync && typeof done === 'function' ? done : isAsync && typeof cxt.async === 'function' ? cxt
  				.async() : taskSyncDone;
  		if (!rbot.env.usingGrunt) {
  			// set options using either a configuration value or the passed
  			// default value
  			cxt.options = function setOptions(defOpts) {
  				Object.keys(defOpts).forEach(function it(k) {
  					this.options[k] = rbot.config(k) || defOpts[k];
  				}.bind(this));
  				return this.options;
  			}.bind(cxt);
  		}
  		var fna = args;
  		if (cxt.done !== done && cxt.done !== taskSyncDone) {
  			// ensure that the done function still gets passed as the 1st
  			// argument even when the task runner doesn't pass it
  			fna = args ? Array.prototype.slice.call(args, 0) : [];
  			fna.unshift(cxt.done);
  		}
  		return fn.apply(cxt, fna);
  	}
  	function taskSyncDone(success) {
  		rbot.log.verbose('Synchronous task ' + (success ? 'completed' : 'failed'));
  	}
  }
docs: Creates a task callback function that will wrap the passed callback that the
  task runner requires to ensure consistent option behavior between different
  task runners. When the specified function contains arguments the wrapper will
  assume that the associated task will be executed in an asynchronous fashion.
  Relies on the number of arguments defined in the passed function to determine
  synchronicity.
  
  @param fn
  the function that will be wrapped
  @returns a wrapped callback function