docs: function runAsyncBranch (index, currentBranch, options) {
    var { tree, args, signal, state, promise, start, services } = options;
  
    var promises = currentBranch
      .map(action => {
        var actionFunc = tree.actions[action.actionIndex];
        var actionArgs = createActionArgs(args, action, state, true);
        var outputs = action.outputs ? Object.keys(action.outputs) : [];
  
        action.isExecuting = true;
        action.args = merge({}, args);
  
        var nextActionPromise;
        var foundResult = signal.asyncActionResults.find((result) => isEqualArrays(result.outputPath, action.path));
  
        // If actions results provided, you run it in replay mode
        if (foundResult) {
          nextActionPromise = Promise.resolve(foundResult);
        } else {
          var next = createNextAsyncAction(actionFunc, outputs);
          actionFunc.apply(null, actionArgs.concat(next.fn, services));
          nextActionPromise = next.promise;
        }
  
        return nextActionPromise
          .then(result => {
            action.hasExecuted = true;
            action.isExecuting = false;
            action.output = result.args;
  
            // Save short results snippet for replay
            signal.asyncActionResults.push({
              outputPath: action.path,
              path: result.path,
              args: result.args
            });
  
            merge(args, result.args);
  
            if (result.path) {
              action.outputPath = result.path;
              var output = action.outputs[result.path];
  
              return runBranch(0, {
                args, signal, state, start, promise, services,
                tree: {
                  actions: tree.actions,
                  branches: output
                }
              });
            }
          })
          .catch((e) => promise.reject(e));
      });
  
    return Promise.all(promises)
      .then(() => runBranch(index + 1, options));
  }