run (runtimeFacts = {}, runOptions = {}) {
    debug('engine::run started')
    this.status = RUNNING

    const almanac = runOptions.almanac || new Almanac({
      allowUndefinedFacts: this.allowUndefinedFacts,
      pathResolver: this.pathResolver
    })

    this.facts.forEach(fact => {
      almanac.addFact(fact)
    })
    for (const factId in runtimeFacts) {
      let fact
      if (runtimeFacts[factId] instanceof Fact) {
        fact = runtimeFacts[factId]
      } else {
        fact = new Fact(factId, runtimeFacts[factId])
      }

      almanac.addFact(fact)
      debug('engine::run initialized runtime fact', { id: fact.id, value: fact.value, type: typeof fact.value })
    }
    const orderedSets = this.prioritizeRules()
    let cursor = Promise.resolve()
    // for each rule set, evaluate in parallel,
    // before proceeding to the next priority set.
    return new Promise((resolve, reject) => {
      orderedSets.map((set) => {
        cursor = cursor.then(() => {
          return this.evaluateRules(set, almanac)
        }).catch(reject)
        return cursor
      })
      cursor.then(() => {
        this.status = FINISHED
        debug('engine::run completed')
        const ruleResults = almanac.getResults()
        const { results, failureResults } = ruleResults.reduce((hash, ruleResult) => {
          const group = ruleResult.result ? 'results' : 'failureResults'
          hash[group].push(ruleResult)
          return hash
        }, { results: [], failureResults: [] })

        resolve({
          almanac,
          results,
          failureResults,
          events: almanac.getEvents('success'),
          failureEvents: almanac.getEvents('failure')
        })
      }).catch(reject)
    })
  }
Runs the rules engine
@param  {Object} runtimeFacts - fact values known at runtime
@param  {Object} runOptions - run options
@return {Promise} resolves when the engine has completed running