docs: function Gagarin (options) {
    "use strict";
  
    var write = process.stdout.write.bind(process.stdout);
    var listOfFrameworks = [];
    var numberOfLinesPrinted = 0;
  
    // XXX gagarin user interface is defined here
    require('./interface');
  
    options.settings = tools.getSettings(options.settings);
    options.ui       = 'gagarin';
  
    var factory = !options.parallel ? null : createParallelReporterFactory(function (allStats, elapsed) {
      if (numberOfLinesPrinted > 0) {
        write('\u001b[' + numberOfLinesPrinted + 'A')
      }
      write('  elapsed time: ' + Math.floor(elapsed / 100) / 10 + 's' + '\n\n');
      numberOfLinesPrinted = 2 + table(allStats, write);
    });
  
    function getMocha() {
  
      if (options.parallel === 0 && listOfFrameworks.length > 0) {
        return listOfFrameworks[0];
      }
  
      var mocha = new Mocha(options);
  
      if (factory) {
        // overwrite the default reporter
        mocha._reporter = factory(listOfFrameworks.length);
      }
  
      var reporter = mocha._reporter;
  
      listOfFrameworks.push(mocha);
      return mocha;
  
    }; // getMocha
  
    this.options = options;
  
    this.addFile = function (file) {
      getMocha().addFile(file);
    }
  
    this.runAllFrameworks = function (callback) {
  
      var listOfErrors = [];
  
      var pending = listOfFrameworks.slice(0);
      var counter = 0;
      var running = 0;
  
      if (factory) {
  
        // looks like parallel test runner, so make sure
        // there are no logs which can break the table view
  
        factory.reset();
        process.stdout.write('\n\n');
        write = logs2.block();
        logs.setSilentBuild(true);
      }
  
      listOfFrameworks.forEach(function (mocha) {
        mocha.loadFiles();
        mocha.files = [];
      });
  
      function finish() {
        if (factory) {
          logs2.unblock();
          factory.epilogue();
        }
        callback && callback(listOfErrors, counter);
      }
  
      function maybeFinish (action) {
        if (running <= 0 && pending <= 0) {
          finish();
        } else {
          action && action();
        }
      }
  
      function update() {
        var availableSlots = options.parallel > 0 ? options.parallel : 1;
        if (running >= availableSlots) {
          return false;
        }
        var next = pending.shift();
        if (!next) {
          maybeFinish();
          return false;
        }
        running += 1;
        try {
          next.run(function (numberOfFailures) {
            counter += numberOfFailures;
            running -= 1;
            maybeFinish(function () { // if not ...
              while (update());       // run as many suites as you can
            });
          });
        } catch (err) {
          listOfErrors.push(err);
          running -= 1;
          maybeFinish();
          return false;
        }
        return true;
      }
  
      while (update()); // run as many suites as you can
  
    }
  }