docs: function(type, model, collection, options){
      var shortcircuit = { change: 1, sort: 1, request: 1, destroy: 1, sync: 1, error: 1, invalid: 1, route: 1, dirty: 1 };
      if( shortcircuit[type] || !model.isData ){ return void 0; }
      model || (model = {});
      collection || (collection = {});
      options || (options = {});
      !collection.isData && (options = collection) && (collection = model);
      var path, vector;
  
      // Compute the path to this data object that triggered the event
      // TODO: Figure out a better way to prefix service data paths with their local path name
      vector = path = ((options.service) ? `${options.service}.`: '') + collection.__path().replace(/\.?\[.*\]/ig, '.@each');
  
      // If a reset event on a Model, check for computed properties that depend
      // on each changed attribute's full path.
      if(type === 'reset' && options.previousAttributes){
        _.each(options.previousAttributes, function(value, key){
          vector = path + (path && '.') + key;
          _.each(this.__computedDeps, function(dependants, dependancy){
            startsWith(vector, dependancy) && push.call(TO_CALL, dependants);
          }, this);
        }, this);
      }
  
      // If a reset event on a Collction, check for computed properties that depend
      // on anything inside that collection.
      else if(type === 'reset' && options.previousModels){
        _.each(this.__computedDeps, function(dependants, dependancy){
          startsWith(dependancy, vector) && push.call(TO_CALL, dependants);
        }, this);
      }
  
      // If an add or remove event, check for computed properties that depend on
      // anything inside that collection or that contains that collection.
      else if(type === 'add' || type === 'remove'){
        _.each(this.__computedDeps, function(dependants, dependancy){
          if( startsWith(dependancy, vector) || startsWith(vector, dependancy) ) push.call(TO_CALL, dependants);
        }, this);
      }
  
      // If a change event, trigger anything that depends on that changed path.
      else if(type.indexOf('change:') === 0){
        vector = type.replace('change:', '').replace(/\.?\[.*\]/ig, '.@each');
        _.each(this.__computedDeps, function(dependants, dependancy){
          startsWith(vector, dependancy) && push.call(TO_CALL, dependants);
        }, this);
      }
  
      // Notifies all computed properties in the dependants array to recompute.
      // Push all recomputes to the end of our stack trace so all Computed Properties
      // already queued for recompute get a chance to.
      if(!CALL_TIMEOUT){ CALL_TIMEOUT = setTimeout(_.bind(recomputeCallback, this), 0); }
  
    }