constructor(root, pkg, ui, cli) {
    logger.info('init root: %s', root);

    this.root = root;
    this.pkg = pkg;
    this.ui = ui;
    this.cli = cli;
    this.addonPackages = Object.create(null);
    this.addons = [];
    this.liveReloadFilterPatterns = [];
    this.configCache = new Map();
    this.hostInfoCache = new HostInfoCache(this);

    /**
      Set when the `Watcher.detectWatchman` helper method finishes running,
      so that other areas of the system can be aware that watchman is being used.

      For example, this information is used in the broccoli build pipeline to know
      if we can watch additional directories "cheaply".

      Contains `enabled` and `version`.

      @private
      @property _watchmanInfo
      @return {Object}
      @default false
    */
    this._watchmanInfo = {
      enabled: false,
      version: null,
      canNestRoots: false,
    };

    let instrumentation = (this._instrumentation = ensureInstrumentation(cli, ui));
    instrumentation.project = this;

    this.emberCLIVersion = emberCLIVersion;

    this._nodeModulesPath = null;

    if (this.cli && this.cli.packageInfoCache) {
      this.packageInfoCache = this.cli.packageInfoCache;
    } else {
      this.packageInfoCache = new PackageInfoCache(this.ui);
    }

    // we're not dealing with NULL_PROJECT (note that it has not
    // be set yet, so we can't compare to that var.)
    this._packageInfo = this.packageInfoCache.loadProject(this);

    // force us to use the real path as the root.
    this.root = this._packageInfo.realPath;

    // XXX Need to decide what to do here about showing errors. For
    // a non-CLI project the cache is local and probably should. For
    // a CLI project the cache is there, but not sure when we'll know
    // about all the errors, because there may be multiple projects.
    if (this.packageInfoCache.hasErrors()) {
      this.packageInfoCache.showErrors();
    }

    if (PerBundleAddonCache.isEnabled()) {
      this.perBundleAddonCache = new PerBundleAddonCache(this);
    }
  }
The Project model is tied to your package.json. It is instantiated
    by giving {{#crossLink "Project/closestSync:method"}}{{/crossLink}}
    the path to your project.

    @class Project
    @constructor
    @param {String} root Root directory for the project
    @param {Object} pkg  Contents of package.json
    @param {UI} ui
    @param {CLI} cli