docs: function(task) {
  
    // Validate object keys.
    _.each(Object.keys(task), function(key) {
      if (!_.contains(validKeys, key)) {
        throw new TypeError('Invalid task property: ' +
          key + ' ' + pp(task));
      }
    });
  
    // Validate __isTask.
    if (!isTask(task)) {
      throw new TypeError('Invalid task: ' + pp(task));
    }
  
    // Validate path.
    if (!Array.isArray(task.path)) {
      throw new TypeError('Invalid task path: ' + pp(task));
    }
    if (task.path.length === 0) {
      throw new TypeError('Empty task path: ' + pp(task));
    }
    task.path.forEach(function(atom) {
      if (typeof atom !== 'string') {
        throw new TypeError('Invalid task path: ' + pp(task));
      }
    });
  
    // Validate category.
    var cat = task.category;
    if (typeof cat !== 'string' || !_.includes(validCategories, cat)) {
      throw new TypeError('Invalid task category: ' + pp(task));
    }
  
    // Validate description.
    if (typeof task.description !== 'string' || task.description.length === 0) {
      throw new TypeError('Invalid task description: ' + pp(task));
    }
  
    // Validate kind.
    if (typeof task.kind !== 'string') {
      throw new TypeError('Invalid task kind: ' + pp(task));
    }
    parseKind(task.kind);
  
    // Validate options.
    if (!Array.isArray(task.options)) {
      throw new TypeError('Invalid task options: ' + pp(task));
    }
    _.each(task.options, function(option) {
      invariantOption(task, option);
    });
  
    // Validate function.
    if (typeof task.func !== 'function') {
      throw new TypeError('Invalid task function: ' + pp(task));
    }
    if (task.func.length > 1) {
      throw new TypeError('Wrong number of arguments in task function: ' +
        task.func.toString());
    }
  
  }