docs: 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'));
  	}
  }