docs: function compose(task) {
  
     // Already composed action.
     if (task.action)
        return task.action
  
     // 1. named task.
     if (typeof task === "string")
        return task
  
     // 2. a function directly.
     if (typeof task === "function")
        return task.length ? task : () => Promise.resolve(task())
  
     // 3. task object.
     if (typeof task !== "object")
        throw new Error("A task must be a string, function, or object.")
  
     if (task.watch === true) {
        // Watching task without a valid path.
        if (!task.src)
           throw new Error("No path given to watch.")
        task.watch = task.src
     }
  
  
     let transform
  
     if (task.src)
        transform = () => pipify(task)
  
     // No transform function and no series/parallel.
     if (!transform && !task.series && !task.parallel)
        throw new Error("A task must do something.")
  
     // Both series and parallel.
     if (task.series && task.parallel)
        throw new Error("A task can't have both .series and .parallel properties.")
  
     // Only transform function.
     if (!task.series && !task.parallel) {
        task.action = transform
     }
  
     // Series/parallel sequence of tasks.
     else {
        const sequence = task.series ? "series" : "parallel"
        if (transform)
           task[sequence].push(transform)
        task.action = gulp[sequence](...task[sequence].map(compose))
     }
  
     return task.action
  
  }