diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php
index 73b46511a..70acf0e67 100644
--- a/src/applications/diffusion/controller/DiffusionCommitController.php
+++ b/src/applications/diffusion/controller/DiffusionCommitController.php
@@ -1,1105 +1,1086 @@
 <?php
 
 final class DiffusionCommitController extends DiffusionController {
 
   const CHANGES_LIMIT = 100;
 
   private $auditAuthorityPHIDs;
   private $highlightedAudits;
 
   public function shouldAllowPublic() {
     return true;
   }
 
   protected function shouldLoadDiffusionRequest() {
     return false;
   }
 
   protected function processDiffusionRequest(AphrontRequest $request) {
     $user = $request->getUser();
     // This controller doesn't use blob/path stuff, just pass the dictionary
     // in directly instead of using the AphrontRequest parsing mechanism.
     $data = $request->getURIMap();
     $data['user'] = $user;
     $drequest = DiffusionRequest::newFromDictionary($data);
     $this->diffusionRequest = $drequest;
 
     if ($request->getStr('diff')) {
       return $this->buildRawDiffResponse($drequest);
     }
 
     $repository = $drequest->getRepository();
     $callsign = $repository->getCallsign();
 
     $content = array();
     $commit = id(new DiffusionCommitQuery())
       ->setViewer($request->getUser())
       ->withRepository($repository)
       ->withIdentifiers(array($drequest->getCommit()))
       ->needCommitData(true)
       ->needAuditRequests(true)
       ->executeOne();
 
     $crumbs = $this->buildCrumbs(array(
       'commit' => true,
     ));
 
     if (!$commit) {
       $exists = $this->callConduitWithDiffusionRequest(
         'diffusion.existsquery',
         array('commit' => $drequest->getCommit()));
       if (!$exists) {
         return new Aphront404Response();
       }
 
       $error = id(new AphrontErrorView())
         ->setTitle(pht('Commit Still Parsing'))
         ->appendChild(
           pht(
             'Failed to load the commit because the commit has not been '.
             'parsed yet.'));
 
       return $this->buildApplicationPage(
         array(
           $crumbs,
           $error,
         ),
         array(
           'title' => pht('Commit Still Parsing'),
         ));
     }
 
 
     $top_anchor = id(new PhabricatorAnchorView())
       ->setAnchorName('top')
       ->setNavigationMarker(true);
 
     $audit_requests = $commit->getAudits();
     $this->auditAuthorityPHIDs =
       PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
 
     $commit_data = $commit->getCommitData();
     $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
     $changesets = null;
     if ($is_foreign) {
       $subpath = $commit_data->getCommitDetail('svn-subpath');
 
       $error_panel = new AphrontErrorView();
       $error_panel->setTitle(pht('Commit Not Tracked'));
       $error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING);
       $error_panel->appendChild(
         pht("This Diffusion repository is configured to track only one ".
         "subdirectory of the entire Subversion repository, and this commit ".
         "didn't affect the tracked subdirectory ('%s'), so no ".
         "information is available.", $subpath));
       $content[] = $error_panel;
       $content[] = $top_anchor;
     } else {
       $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
       $engine->setConfig('viewer', $user);
 
       require_celerity_resource('phabricator-remarkup-css');
 
       $parents = $this->callConduitWithDiffusionRequest(
         'diffusion.commitparentsquery',
         array('commit' => $drequest->getCommit()));
 
       if ($parents) {
         $parents = id(new DiffusionCommitQuery())
           ->setViewer($user)
           ->withRepository($repository)
           ->withIdentifiers($parents)
           ->execute();
       }
 
       $headsup_view = id(new PHUIHeaderView())
         ->setHeader(nonempty($commit->getSummary(), pht('Commit Detail')));
 
       $headsup_actions = $this->renderHeadsupActionList($commit, $repository);
 
       $commit_properties = $this->loadCommitProperties(
         $commit,
         $commit_data,
         $parents,
         $audit_requests);
       $property_list = id(new PHUIPropertyListView())
         ->setHasKeyboardShortcuts(true)
         ->setUser($user)
         ->setObject($commit);
       foreach ($commit_properties as $key => $value) {
         $property_list->addProperty($key, $value);
       }
 
       $message = $commit_data->getCommitMessage();
 
       $revision = $commit->getCommitIdentifier();
       $message = $this->linkBugtraq($message);
 
       $message = $engine->markupText($message);
 
       $property_list->invokeWillRenderEvent();
       $property_list->setActionList($headsup_actions);
 
       $detail_list = new PHUIPropertyListView();
       $detail_list->addSectionHeader(
         pht('Description'),
         PHUIPropertyListView::ICON_SUMMARY);
       $detail_list->addTextContent(
         phutil_tag(
           'div',
           array(
             'class' => 'diffusion-commit-message phabricator-remarkup',
           ),
           $message));
       $content[] = $top_anchor;
 
       $object_box = id(new PHUIObjectBoxView())
         ->setHeader($headsup_view)
         ->addPropertyList($property_list)
         ->addPropertyList($detail_list);
 
       $content[] = $object_box;
     }
 
     $content[] = $this->buildComments($commit);
 
     $hard_limit = 1000;
 
     if ($commit->isImported()) {
       $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
         $drequest);
       $change_query->setLimit($hard_limit + 1);
       $changes = $change_query->loadChanges();
     } else {
       $changes = array();
     }
 
     $was_limited = (count($changes) > $hard_limit);
     if ($was_limited) {
       $changes = array_slice($changes, 0, $hard_limit);
     }
 
     $content[] = $this->buildMergesTable($commit);
 
     $highlighted_audits = $commit->getAuthorityAudits(
       $user,
       $this->auditAuthorityPHIDs);
 
     $owners_paths = array();
     if ($highlighted_audits) {
       $packages = id(new PhabricatorOwnersPackage())->loadAllWhere(
         'phid IN (%Ls)',
         mpull($highlighted_audits, 'getAuditorPHID'));
       if ($packages) {
         $owners_paths = id(new PhabricatorOwnersPath())->loadAllWhere(
           'repositoryPHID = %s AND packageID IN (%Ld)',
           $repository->getPHID(),
           mpull($packages, 'getID'));
       }
     }
 
     $change_table = new DiffusionCommitChangeTableView();
     $change_table->setDiffusionRequest($drequest);
     $change_table->setPathChanges($changes);
     $change_table->setOwnersPaths($owners_paths);
 
     $count = count($changes);
 
     $bad_commit = null;
     if ($count == 0) {
       $bad_commit = queryfx_one(
         id(new PhabricatorRepository())->establishConnection('r'),
         'SELECT * FROM %T WHERE fullCommitName = %s',
         PhabricatorRepository::TABLE_BADCOMMIT,
         'r'.$callsign.$commit->getCommitIdentifier());
     }
 
     if ($bad_commit) {
       $content[] = $this->renderStatusMessage(
         pht('Bad Commit'),
         $bad_commit['description']);
     } else if ($is_foreign) {
       // Don't render anything else.
     } else if (!$commit->isImported()) {
       $content[] = $this->renderStatusMessage(
         pht('Still Importing...'),
         pht(
           'This commit is still importing. Changes will be visible once '.
           'the import finishes.'));
     } else if (!count($changes)) {
       $content[] = $this->renderStatusMessage(
         pht('Empty Commit'),
         pht(
           'This commit is empty and does not affect any paths.'));
     } else if ($was_limited) {
       $content[] = $this->renderStatusMessage(
         pht('Enormous Commit'),
         pht(
           'This commit is enormous, and affects more than %d files. '.
           'Changes are not shown.',
           $hard_limit));
     } else {
       // The user has clicked "Show All Changes", and we should show all the
       // changes inline even if there are more than the soft limit.
       $show_all_details = $request->getBool('show_all');
 
       $change_panel = new PHUIObjectBoxView();
       $header = new PHUIHeaderView();
       $header->setHeader('Changes ('.number_format($count).')');
       $change_panel->setID('toc');
       if ($count > self::CHANGES_LIMIT && !$show_all_details) {
 
         $icon = id(new PHUIIconView())
           ->setIconFont('fa-files-o');
 
         $button = id(new PHUIButtonView())
           ->setText(pht('Show All Changes'))
           ->setHref('?show_all=true')
           ->setTag('a')
           ->setIcon($icon);
 
         $warning_view = id(new AphrontErrorView())
           ->setSeverity(AphrontErrorView::SEVERITY_WARNING)
           ->setTitle('Very Large Commit')
           ->appendChild(
             pht('This commit is very large. Load each file individually.'));
 
         $change_panel->setErrorView($warning_view);
         $header->addActionLink($button);
       }
 
       $change_panel->appendChild($change_table);
       $change_panel->setHeader($header);
 
       $content[] = $change_panel;
 
       $changesets = DiffusionPathChange::convertToDifferentialChangesets(
         $user,
         $changes);
 
       $vcs = $repository->getVersionControlSystem();
       switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
           $vcs_supports_directory_changes = true;
           break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
           $vcs_supports_directory_changes = false;
           break;
         default:
           throw new Exception('Unknown VCS.');
       }
 
       $references = array();
       foreach ($changesets as $key => $changeset) {
         $file_type = $changeset->getFileType();
         if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
           if (!$vcs_supports_directory_changes) {
             unset($changesets[$key]);
             continue;
           }
         }
 
         $references[$key] = $drequest->generateURI(
           array(
             'action' => 'rendering-ref',
             'path'   => $changeset->getFilename(),
           ));
       }
 
       // TODO: Some parts of the views still rely on properties of the
       // DifferentialChangeset. Make the objects ephemeral to make sure we don't
       // accidentally save them, and then set their ID to the appropriate ID for
       // this application (the path IDs).
       $path_ids = array_flip(mpull($changes, 'getPath'));
       foreach ($changesets as $changeset) {
         $changeset->makeEphemeral();
         $changeset->setID($path_ids[$changeset->getFilename()]);
       }
 
       if ($count <= self::CHANGES_LIMIT || $show_all_details) {
         $visible_changesets = $changesets;
       } else {
         $visible_changesets = array();
         $inlines = PhabricatorAuditInlineComment::loadDraftAndPublishedComments(
           $user,
           $commit->getPHID());
         $path_ids = mpull($inlines, null, 'getPathID');
         foreach ($changesets as $key => $changeset) {
           if (array_key_exists($changeset->getID(), $path_ids)) {
             $visible_changesets[$key] = $changeset;
           }
         }
       }
 
       $change_list_title = DiffusionView::nameCommit(
         $repository,
         $commit->getCommitIdentifier());
       $change_list = new DifferentialChangesetListView();
       $change_list->setTitle($change_list_title);
       $change_list->setChangesets($changesets);
       $change_list->setVisibleChangesets($visible_changesets);
       $change_list->setRenderingReferences($references);
       $change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
       $change_list->setRepository($repository);
       $change_list->setUser($user);
 
       // TODO: Try to setBranch() to something reasonable here?
 
       $change_list->setStandaloneURI(
         '/diffusion/'.$callsign.'/diff/');
       $change_list->setRawFileURIs(
         // TODO: Implement this, somewhat tricky if there's an octopus merge
         // or whatever?
         null,
         '/diffusion/'.$callsign.'/diff/?view=r');
 
       $change_list->setInlineCommentControllerURI(
         '/diffusion/inline/edit/'.phutil_escape_uri($commit->getPHID()).'/');
 
       $change_references = array();
       foreach ($changesets as $key => $changeset) {
         $change_references[$changeset->getID()] = $references[$key];
       }
       $change_table->setRenderingReferences($change_references);
 
       $content[] = $change_list->render();
     }
 
     $content[] = $this->renderAddCommentPanel($commit, $audit_requests);
 
     $commit_id = 'r'.$callsign.$commit->getCommitIdentifier();
     $short_name = DiffusionView::nameCommit(
       $repository,
       $commit->getCommitIdentifier());
 
     $prefs = $user->loadPreferences();
     $pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
     $pref_collapse = PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED;
     $show_filetree = $prefs->getPreference($pref_filetree);
     $collapsed = $prefs->getPreference($pref_collapse);
 
     if ($changesets && $show_filetree) {
       $nav = id(new DifferentialChangesetFileTreeSideNavBuilder())
         ->setAnchorName('top')
         ->setTitle($short_name)
         ->setBaseURI(new PhutilURI('/'.$commit_id))
         ->build($changesets)
         ->setCrumbs($crumbs)
         ->setCollapsed((bool)$collapsed)
         ->appendChild($content);
       $content = $nav;
     } else {
       $content = array($crumbs, $content);
     }
 
     return $this->buildApplicationPage(
       $content,
       array(
         'title' => $commit_id,
         'pageObjects' => array($commit->getPHID()),
       ));
   }
 
   private function loadCommitProperties(
     PhabricatorRepositoryCommit $commit,
     PhabricatorRepositoryCommitData $data,
     array $parents,
     array $audit_requests) {
 
     assert_instances_of($parents, 'PhabricatorRepositoryCommit');
     $viewer = $this->getRequest()->getUser();
     $commit_phid = $commit->getPHID();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
 
     $edge_query = id(new PhabricatorEdgeQuery())
       ->withSourcePHIDs(array($commit_phid))
       ->withEdgeTypes(array(
         DiffusionCommitHasTaskEdgeType::EDGECONST,
         DiffusionCommitHasRevisionEdgeType::EDGECONST,
         DiffusionCommitRevertsCommitEdgeType::EDGECONST,
         DiffusionCommitRevertedByCommitEdgeType::EDGECONST,
       ));
 
     $edges = $edge_query->execute();
 
     $task_phids = array_keys(
       $edges[$commit_phid][DiffusionCommitHasTaskEdgeType::EDGECONST]);
     $revision_phid = key(
       $edges[$commit_phid][DiffusionCommitHasRevisionEdgeType::EDGECONST]);
 
     $reverts_phids = array_keys(
       $edges[$commit_phid][DiffusionCommitRevertsCommitEdgeType::EDGECONST]);
     $reverted_by_phids = array_keys(
       $edges[$commit_phid][DiffusionCommitRevertedByCommitEdgeType::EDGECONST]);
 
     $phids = $edge_query->getDestinationPHIDs(array($commit_phid));
 
     if ($data->getCommitDetail('authorPHID')) {
       $phids[] = $data->getCommitDetail('authorPHID');
     }
     if ($data->getCommitDetail('reviewerPHID')) {
       $phids[] = $data->getCommitDetail('reviewerPHID');
     }
     if ($data->getCommitDetail('committerPHID')) {
       $phids[] = $data->getCommitDetail('committerPHID');
     }
     if ($parents) {
       foreach ($parents as $parent) {
         $phids[] = $parent->getPHID();
       }
     }
 
     // NOTE: We should never normally have more than a single push log, but
     // it can occur naturally if a commit is pushed, then the branch it was
     // on is deleted, then the commit is pushed again (or through other similar
     // chains of events). This should be rare, but does not indicate a bug
     // or data issue.
 
     // NOTE: We never query push logs in SVN because the commiter is always
     // the pusher and the commit time is always the push time; the push log
     // is redundant and we save a query by skipping it.
 
     $push_logs = array();
     if ($repository->isHosted() && !$repository->isSVN()) {
       $push_logs = id(new PhabricatorRepositoryPushLogQuery())
         ->setViewer($viewer)
         ->withRepositoryPHIDs(array($repository->getPHID()))
         ->withNewRefs(array($commit->getCommitIdentifier()))
         ->withRefTypes(array(PhabricatorRepositoryPushLog::REFTYPE_COMMIT))
         ->execute();
       foreach ($push_logs as $log) {
         $phids[] = $log->getPusherPHID();
       }
     }
 
     $handles = array();
     if ($phids) {
       $handles = $this->loadViewerHandles($phids);
     }
 
     $props = array();
 
     if ($commit->getAuditStatus()) {
       $status = PhabricatorAuditCommitStatusConstants::getStatusName(
         $commit->getAuditStatus());
       $tag = id(new PHUITagView())
         ->setType(PHUITagView::TYPE_STATE)
         ->setName($status);
 
       switch ($commit->getAuditStatus()) {
         case PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT:
           $tag->setBackgroundColor(PHUITagView::COLOR_ORANGE);
           break;
         case PhabricatorAuditCommitStatusConstants::CONCERN_RAISED:
           $tag->setBackgroundColor(PHUITagView::COLOR_RED);
           break;
         case PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED:
           $tag->setBackgroundColor(PHUITagView::COLOR_BLUE);
           break;
         case PhabricatorAuditCommitStatusConstants::FULLY_AUDITED:
           $tag->setBackgroundColor(PHUITagView::COLOR_GREEN);
           break;
       }
 
       $props['Status'] = $tag;
     }
 
     if ($audit_requests) {
       $user_requests = array();
       $other_requests = array();
       foreach ($audit_requests as $audit_request) {
         if ($audit_request->isUser()) {
           $user_requests[] = $audit_request;
         } else {
           $other_requests[] = $audit_request;
         }
       }
 
       if ($user_requests) {
         $props['Auditors'] = $this->renderAuditStatusView(
           $user_requests);
       }
 
       if ($other_requests) {
         $props['Project/Package Auditors'] = $this->renderAuditStatusView(
           $other_requests);
       }
     }
 
     $author_phid = $data->getCommitDetail('authorPHID');
     $author_name = $data->getAuthorName();
 
     if (!$repository->isSVN()) {
       $authored_info = id(new PHUIStatusItemView());
       // TODO: In Git, a distinct authorship date is available. When present,
       // we should show it here.
 
       if ($author_phid) {
         $authored_info->setTarget($handles[$author_phid]->renderLink());
       } else if (strlen($author_name)) {
         $authored_info->setTarget($author_name);
       }
 
       $props['Authored'] = id(new PHUIStatusListView())
         ->addItem($authored_info);
     }
 
     $committed_info = id(new PHUIStatusItemView())
       ->setNote(phabricator_datetime($commit->getEpoch(), $viewer));
 
     $committer_phid = $data->getCommitDetail('committerPHID');
     $committer_name = $data->getCommitDetail('committer');
     if ($committer_phid) {
       $committed_info->setTarget($handles[$committer_phid]->renderLink());
     } else if (strlen($committer_name)) {
       $committed_info->setTarget($committer_name);
     } else if ($author_phid) {
       $committed_info->setTarget($handles[$author_phid]->renderLink());
     } else if (strlen($author_name)) {
       $committed_info->setTarget($author_name);
     }
 
     $props['Committed'] = id(new PHUIStatusListView())
       ->addItem($committed_info);
 
     if ($push_logs) {
       $pushed_list = new PHUIStatusListView();
 
       foreach ($push_logs as $push_log) {
         $pushed_item = id(new PHUIStatusItemView())
           ->setTarget($handles[$push_log->getPusherPHID()]->renderLink())
           ->setNote(phabricator_datetime($push_log->getEpoch(), $viewer));
         $pushed_list->addItem($pushed_item);
       }
 
       $props['Pushed'] = $pushed_list;
     }
 
     $reviewer_phid = $data->getCommitDetail('reviewerPHID');
     if ($reviewer_phid) {
       $props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
     }
 
     if ($revision_phid) {
       $props['Differential Revision'] = $handles[$revision_phid]->renderLink();
     }
 
     if ($parents) {
       $parent_links = array();
       foreach ($parents as $parent) {
         $parent_links[] = $handles[$parent->getPHID()]->renderLink();
       }
       $props['Parents'] = phutil_implode_html(" \xC2\xB7 ", $parent_links);
     }
 
     $props['Branches'] = phutil_tag(
       'span',
       array(
         'id' => 'commit-branches',
       ),
       pht('Unknown'));
     $props['Tags'] = phutil_tag(
       'span',
       array(
         'id' => 'commit-tags',
       ),
       pht('Unknown'));
 
     $callsign = $repository->getCallsign();
     $root = '/diffusion/'.$callsign.'/commit/'.$commit->getCommitIdentifier();
     Javelin::initBehavior(
       'diffusion-commit-branches',
       array(
         $root.'/branches/' => 'commit-branches',
         $root.'/tags/' => 'commit-tags',
       ));
 
     $refs = $this->buildRefs($drequest);
     if ($refs) {
       $props['References'] = $refs;
     }
 
     if ($reverts_phids) {
       $this->loadHandles($reverts_phids);
       $props[pht('Reverts')] = $this->renderHandlesForPHIDs($reverts_phids);
     }
 
     if ($reverted_by_phids) {
       $this->loadHandles($reverted_by_phids);
       $props[pht('Reverted By')] = $this->renderHandlesForPHIDs(
         $reverted_by_phids);
     }
 
     if ($task_phids) {
       $task_list = array();
       foreach ($task_phids as $phid) {
         $task_list[] = $handles[$phid]->renderLink();
       }
       $task_list = phutil_implode_html(phutil_tag('br'), $task_list);
       $props['Tasks'] = $task_list;
     }
 
     return $props;
   }
 
   private function buildComments(PhabricatorRepositoryCommit $commit) {
     $timeline = $this->buildTransactionTimeline(
       $commit,
       new PhabricatorAuditTransactionQuery());
-    $xactions = $timeline->getTransactions();
-
-    $path_ids = array();
-    foreach ($xactions as $xaction) {
-      if ($xaction->hasComment()) {
-        $path_id = $xaction->getComment()->getPathID();
-        if ($path_id) {
-          $path_ids[] = $path_id;
-        }
-      }
-    }
-
-    $path_map = array();
-    if ($path_ids) {
-      $path_map = id(new DiffusionPathQuery())
-        ->withPathIDs($path_ids)
-        ->execute();
-      $path_map = ipull($path_map, 'path', 'id');
-    }
-
-    return $timeline->setPathMap($path_map);
+    $commit->willRenderTimeline($timeline, $this->getRequest());
+    return $timeline;
   }
 
   private function renderAddCommentPanel(
     PhabricatorRepositoryCommit $commit,
     array $audit_requests) {
     assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
 
     $request = $this->getRequest();
     $user = $request->getUser();
 
     if (!$user->isLoggedIn()) {
       return id(new PhabricatorApplicationTransactionCommentView())
         ->setUser($user)
         ->setRequestURI($request->getRequestURI());
     }
 
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
 
     $pane_id = celerity_generate_unique_node_id();
     Javelin::initBehavior(
       'differential-keyboard-navigation',
       array(
         'haunt' => $pane_id,
       ));
 
     $draft = id(new PhabricatorDraft())->loadOneWhere(
       'authorPHID = %s AND draftKey = %s',
       $user->getPHID(),
       'diffusion-audit-'.$commit->getID());
     if ($draft) {
       $draft = $draft->getDraft();
     } else {
       $draft = null;
     }
 
     $actions = $this->getAuditActions($commit, $audit_requests);
 
     $form = id(new AphrontFormView())
       ->setUser($user)
       ->setAction('/audit/addcomment/')
       ->addHiddenInput('commit', $commit->getPHID())
       ->appendChild(
         id(new AphrontFormSelectControl())
           ->setLabel(pht('Action'))
           ->setName('action')
           ->setID('audit-action')
           ->setOptions($actions))
       ->appendChild(
         id(new AphrontFormTokenizerControl())
           ->setLabel(pht('Add Auditors'))
           ->setName('auditors')
           ->setControlID('add-auditors')
           ->setControlStyle('display: none')
           ->setID('add-auditors-tokenizer')
           ->setDisableBehavior(true))
       ->appendChild(
         id(new AphrontFormTokenizerControl())
           ->setLabel(pht('Add CCs'))
           ->setName('ccs')
           ->setControlID('add-ccs')
           ->setControlStyle('display: none')
           ->setID('add-ccs-tokenizer')
           ->setDisableBehavior(true))
       ->appendChild(
         id(new PhabricatorRemarkupControl())
           ->setLabel(pht('Comments'))
           ->setName('content')
           ->setValue($draft)
           ->setID('audit-content')
           ->setUser($user))
       ->appendChild(
         id(new AphrontFormSubmitControl())
           ->setValue(pht('Submit')));
 
     $header = new PHUIHeaderView();
     $header->setHeader(
       $is_serious ? pht('Audit Commit') : pht('Creative Accounting'));
 
     require_celerity_resource('phabricator-transaction-view-css');
 
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     $auditor_source = new DiffusionAuditorDatasource();
 
     Javelin::initBehavior(
       'differential-add-reviewers-and-ccs',
       array(
         'dynamic' => array(
           'add-auditors-tokenizer' => array(
             'actions' => array('add_auditors' => 1),
             'src' => $auditor_source->getDatasourceURI(),
             'row' => 'add-auditors',
             'placeholder' => $auditor_source->getPlaceholderText(),
           ),
           'add-ccs-tokenizer' => array(
             'actions' => array('add_ccs' => 1),
             'src' => $mailable_source->getDatasourceURI(),
             'row' => 'add-ccs',
             'placeholder' => $mailable_source->getPlaceholderText(),
           ),
         ),
         'select' => 'audit-action',
       ));
 
     Javelin::initBehavior('differential-feedback-preview', array(
       'uri'       => '/audit/preview/'.$commit->getID().'/',
       'preview'   => 'audit-preview',
       'content'   => 'audit-content',
       'action'    => 'audit-action',
       'previewTokenizers' => array(
         'auditors' => 'add-auditors-tokenizer',
         'ccs'      => 'add-ccs-tokenizer',
       ),
       'inline'     => 'inline-comment-preview',
       'inlineuri'  => '/diffusion/inline/preview/'.$commit->getPHID().'/',
     ));
 
     $loading = phutil_tag_div(
       'aphront-panel-preview-loading-text',
       pht('Loading preview...'));
 
     $preview_panel = phutil_tag_div(
       'aphront-panel-preview aphront-panel-flush',
       array(
         phutil_tag('div', array('id' => 'audit-preview'), $loading),
         phutil_tag('div', array('id' => 'inline-comment-preview')),
       ));
 
     // TODO: This is pretty awkward, unify the CSS between Diffusion and
     // Differential better.
     require_celerity_resource('differential-core-view-css');
 
     $anchor = id(new PhabricatorAnchorView())
       ->setAnchorName('comment')
       ->setNavigationMarker(true)
       ->render();
 
     $comment_box = id(new PHUIObjectBoxView())
       ->setHeader($header)
       ->appendChild($form);
 
     return phutil_tag(
       'div',
       array(
         'id' => $pane_id,
       ),
       phutil_tag_div(
         'differential-add-comment-panel',
         array($anchor, $comment_box, $preview_panel)));
   }
 
   /**
    * Return a map of available audit actions for rendering into a <select />.
    * This shows the user valid actions, and does not show nonsense/invalid
    * actions (like closing an already-closed commit, or resigning from a commit
    * you have no association with).
    */
   private function getAuditActions(
     PhabricatorRepositoryCommit $commit,
     array $audit_requests) {
     assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
     $user = $this->getRequest()->getUser();
 
     $user_is_author = ($commit->getAuthorPHID() == $user->getPHID());
 
     $user_request = null;
     foreach ($audit_requests as $audit_request) {
       if ($audit_request->getAuditorPHID() == $user->getPHID()) {
         $user_request = $audit_request;
         break;
       }
     }
 
     $actions = array();
     $actions[PhabricatorAuditActionConstants::COMMENT] = true;
     $actions[PhabricatorAuditActionConstants::ADD_CCS] = true;
     $actions[PhabricatorAuditActionConstants::ADD_AUDITORS] = true;
 
     // We allow you to accept your own commits. A use case here is that you
     // notice an issue with your own commit and "Raise Concern" as an indicator
     // to other auditors that you're on top of the issue, then later resolve it
     // and "Accept". You can not accept on behalf of projects or packages,
     // however.
     $actions[PhabricatorAuditActionConstants::ACCEPT]  = true;
     $actions[PhabricatorAuditActionConstants::CONCERN] = true;
 
 
     // To resign, a user must have authority on some request and not be the
     // commit's author.
     if (!$user_is_author) {
       $may_resign = false;
 
       $authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
       foreach ($audit_requests as $request) {
         if (empty($authority_map[$request->getAuditorPHID()])) {
           continue;
         }
         $may_resign = true;
         break;
       }
 
       // If the user has already resigned, don't show "Resign...".
       $status_resigned = PhabricatorAuditStatusConstants::RESIGNED;
       if ($user_request) {
         if ($user_request->getAuditStatus() == $status_resigned) {
           $may_resign = false;
         }
       }
 
       if ($may_resign) {
         $actions[PhabricatorAuditActionConstants::RESIGN] = true;
       }
     }
 
     $status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
     $concern_raised = ($commit->getAuditStatus() == $status_concern);
     $can_close_option = PhabricatorEnv::getEnvConfig(
       'audit.can-author-close-audit');
     if ($can_close_option && $user_is_author && $concern_raised) {
       $actions[PhabricatorAuditActionConstants::CLOSE] = true;
     }
 
     foreach ($actions as $constant => $ignored) {
       $actions[$constant] =
         PhabricatorAuditActionConstants::getActionName($constant);
     }
 
     return $actions;
   }
 
   private function buildMergesTable(PhabricatorRepositoryCommit $commit) {
     $drequest = $this->getDiffusionRequest();
     $limit = 50;
 
     $merges = array();
     try {
       $merges = $this->callConduitWithDiffusionRequest(
         'diffusion.mergedcommitsquery',
         array(
           'commit' => $drequest->getCommit(),
           'limit' => $limit + 1,
         ));
     } catch (ConduitException $ex) {
       if ($ex->getMessage() != 'ERR-UNSUPPORTED-VCS') {
         throw $ex;
       }
     }
 
     if (!$merges) {
       return null;
     }
 
     $caption = null;
     if (count($merges) > $limit) {
       $merges = array_slice($merges, 0, $limit);
       $caption =
         "This commit merges more than {$limit} changes. Only the first ".
         "{$limit} are shown.";
     }
 
     $history_table = new DiffusionHistoryTableView();
     $history_table->setUser($this->getRequest()->getUser());
     $history_table->setDiffusionRequest($drequest);
     $history_table->setHistory($merges);
     $history_table->loadRevisions();
 
     $phids = $history_table->getRequiredHandlePHIDs();
     $handles = $this->loadViewerHandles($phids);
     $history_table->setHandles($handles);
 
     $panel = new AphrontPanelView();
     $panel->setHeader(pht('Merged Changes'));
     $panel->setCaption($caption);
     $panel->appendChild($history_table);
     $panel->setNoBackground();
 
     return $panel;
   }
 
   private function renderHeadsupActionList(
     PhabricatorRepositoryCommit $commit,
     PhabricatorRepository $repository) {
 
     $request = $this->getRequest();
     $user = $request->getUser();
 
     $actions = id(new PhabricatorActionListView())
       ->setUser($user)
       ->setObject($commit)
       ->setObjectURI($request->getRequestURI());
 
     $can_edit = PhabricatorPolicyFilter::hasCapability(
       $user,
       $commit,
       PhabricatorPolicyCapability::CAN_EDIT);
 
     $uri = '/diffusion/'.$repository->getCallsign().'/commit/'.
            $commit->getCommitIdentifier().'/edit/';
 
     $action = id(new PhabricatorActionView())
       ->setName(pht('Edit Commit'))
       ->setHref($uri)
       ->setIcon('fa-pencil')
       ->setDisabled(!$can_edit)
       ->setWorkflow(!$can_edit);
     $actions->addAction($action);
 
     require_celerity_resource('phabricator-object-selector-css');
     require_celerity_resource('javelin-behavior-phabricator-object-selector');
 
     $maniphest = 'PhabricatorManiphestApplication';
     if (PhabricatorApplication::isClassInstalled($maniphest)) {
       $action = id(new PhabricatorActionView())
         ->setName(pht('Edit Maniphest Tasks'))
         ->setIcon('fa-anchor')
         ->setHref('/search/attach/'.$commit->getPHID().'/TASK/edge/')
         ->setWorkflow(true)
         ->setDisabled(!$can_edit);
       $actions->addAction($action);
     }
 
     $action = id(new PhabricatorActionView())
       ->setName(pht('Download Raw Diff'))
       ->setHref($request->getRequestURI()->alter('diff', true))
       ->setIcon('fa-download');
     $actions->addAction($action);
 
     return $actions;
   }
 
   private function buildRefs(DiffusionRequest $request) {
     // this is git-only, so save a conduit round trip and just get out of
     // here if the repository isn't git
     $type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
     $repository = $request->getRepository();
     if ($repository->getVersionControlSystem() != $type_git) {
       return null;
     }
 
     $results = $this->callConduitWithDiffusionRequest(
       'diffusion.refsquery',
       array('commit' => $request->getCommit()));
     $ref_links = array();
     foreach ($results as $ref_data) {
       $ref_links[] = phutil_tag('a',
         array('href' => $ref_data['href']),
         $ref_data['ref']);
     }
     return phutil_implode_html(', ', $ref_links);
   }
 
   private function buildRawDiffResponse(DiffusionRequest $drequest) {
     $raw_diff = $this->callConduitWithDiffusionRequest(
       'diffusion.rawdiffquery',
       array(
         'commit' => $drequest->getCommit(),
         'path' => $drequest->getPath(),
       ));
 
     $file = PhabricatorFile::buildFromFileDataOrHash(
       $raw_diff,
       array(
         'name' => $drequest->getCommit().'.diff',
         'ttl' => (60 * 60 * 24),
         'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
       ));
 
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
       $file->attachToObject($drequest->getRepository()->getPHID());
     unset($unguarded);
 
     return $file->getRedirectResponse();
   }
 
   private function renderAuditStatusView(array $audit_requests) {
     assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
 
     $phids = mpull($audit_requests, 'getAuditorPHID');
     $this->loadHandles($phids);
 
     $authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
 
     $view = new PHUIStatusListView();
     foreach ($audit_requests as $request) {
       $code = $request->getAuditStatus();
       $item = new PHUIStatusItemView();
       $item->setIcon(
         PhabricatorAuditStatusConstants::getStatusIcon($code),
         PhabricatorAuditStatusConstants::getStatusColor($code),
         PhabricatorAuditStatusConstants::getStatusName($code));
 
       $note = array();
       foreach ($request->getAuditReasons() as $reason) {
         $note[] = phutil_tag('div', array(), $reason);
       }
       $item->setNote($note);
 
       $auditor_phid = $request->getAuditorPHID();
       $target = $this->getHandle($auditor_phid)->renderLink();
       $item->setTarget($target);
 
       if (isset($authority_map[$auditor_phid])) {
         $item->setHighlighted(true);
       }
 
       $view->addItem($item);
     }
 
     return $view;
   }
 
   private function linkBugtraq($corpus) {
     $url = PhabricatorEnv::getEnvConfig('bugtraq.url');
     if (!strlen($url)) {
       return $corpus;
     }
 
     $regexes = PhabricatorEnv::getEnvConfig('bugtraq.logregex');
     if (!$regexes) {
       return $corpus;
     }
 
     $parser = id(new PhutilBugtraqParser())
       ->setBugtraqPattern("[[ {$url} | %BUGID% ]]")
       ->setBugtraqCaptureExpression(array_shift($regexes));
 
     $select = array_shift($regexes);
     if ($select) {
       $parser->setBugtraqSelectExpression($select);
     }
 
     return $parser->processCorpus($corpus);
   }
 
 }
diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
index 1acf43080..cbc24afe0 100644
--- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
@@ -1,412 +1,432 @@
 <?php
 
 final class PhabricatorRepositoryCommit
   extends PhabricatorRepositoryDAO
   implements
     PhabricatorPolicyInterface,
     PhabricatorFlaggableInterface,
     PhabricatorProjectInterface,
     PhabricatorTokenReceiverInterface,
     PhabricatorSubscribableInterface,
     PhabricatorMentionableInterface,
     HarbormasterBuildableInterface,
     PhabricatorCustomFieldInterface,
     PhabricatorApplicationTransactionInterface {
 
   protected $repositoryID;
   protected $phid;
   protected $commitIdentifier;
   protected $epoch;
   protected $mailKey;
   protected $authorPHID;
   protected $auditStatus = PhabricatorAuditCommitStatusConstants::NONE;
   protected $summary = '';
   protected $importStatus = 0;
 
   const IMPORTED_MESSAGE = 1;
   const IMPORTED_CHANGE = 2;
   const IMPORTED_OWNERS = 4;
   const IMPORTED_HERALD = 8;
   const IMPORTED_ALL = 15;
 
   const IMPORTED_CLOSEABLE = 1024;
 
   private $commitData = self::ATTACHABLE;
   private $audits = self::ATTACHABLE;
   private $repository = self::ATTACHABLE;
   private $customFields = self::ATTACHABLE;
 
   public function attachRepository(PhabricatorRepository $repository) {
     $this->repository = $repository;
     return $this;
   }
 
   public function getRepository($assert_attached = true) {
     if ($assert_attached) {
       return $this->assertAttached($this->repository);
     }
     return $this->repository;
   }
 
   public function isPartiallyImported($mask) {
     return (($mask & $this->getImportStatus()) == $mask);
   }
 
   public function isImported() {
     return $this->isPartiallyImported(self::IMPORTED_ALL);
   }
 
   public function writeImportStatusFlag($flag) {
     queryfx(
       $this->establishConnection('w'),
       'UPDATE %T SET importStatus = (importStatus | %d) WHERE id = %d',
       $this->getTableName(),
       $flag,
       $this->getID());
     $this->setImportStatus($this->getImportStatus() | $flag);
     return $this;
   }
 
   protected function getConfiguration() {
     return array(
       self::CONFIG_AUX_PHID   => true,
       self::CONFIG_TIMESTAMPS => false,
       self::CONFIG_COLUMN_SCHEMA => array(
         'commitIdentifier' => 'text40',
         'mailKey' => 'bytes20',
         'authorPHID' => 'phid?',
         'auditStatus' => 'uint32',
         'summary' => 'text80',
         'importStatus' => 'uint32',
       ),
       self::CONFIG_KEY_SCHEMA => array(
         'key_phid' => null,
         'phid' => array(
           'columns' => array('phid'),
           'unique' => true,
         ),
         'repositoryID' => array(
           'columns' => array('repositoryID', 'importStatus'),
         ),
         'authorPHID' => array(
           'columns' => array('authorPHID', 'auditStatus', 'epoch'),
         ),
         'repositoryID_2' => array(
           'columns' => array('repositoryID', 'epoch'),
         ),
         'key_commit_identity' => array(
           'columns' => array('commitIdentifier', 'repositoryID'),
           'unique' => true,
         ),
       ),
     ) + parent::getConfiguration();
   }
 
   public function generatePHID() {
     return PhabricatorPHID::generateNewPHID(
       PhabricatorRepositoryCommitPHIDType::TYPECONST);
   }
 
   public function loadCommitData() {
     if (!$this->getID()) {
       return null;
     }
     return id(new PhabricatorRepositoryCommitData())->loadOneWhere(
       'commitID = %d',
       $this->getID());
   }
 
   public function attachCommitData(
     PhabricatorRepositoryCommitData $data = null) {
     $this->commitData = $data;
     return $this;
   }
 
   public function getCommitData() {
     return $this->assertAttached($this->commitData);
   }
 
   public function attachAudits(array $audits) {
     assert_instances_of($audits, 'PhabricatorRepositoryAuditRequest');
     $this->audits = $audits;
     return $this;
   }
 
   public function getAudits() {
     return $this->assertAttached($this->audits);
   }
 
   public function getAuthorityAudits(
     PhabricatorUser $user,
     array $authority_phids) {
 
     $authority = array_fill_keys($authority_phids, true);
     $audits = $this->getAudits();
     $authority_audits = array();
     foreach ($audits as $audit) {
       $has_authority = !empty($authority[$audit->getAuditorPHID()]);
       if ($has_authority) {
         $commit_author = $this->getAuthorPHID();
 
         // You don't have authority over package and project audits on your
         // own commits.
 
         $auditor_is_user = ($audit->getAuditorPHID() == $user->getPHID());
         $user_is_author = ($commit_author == $user->getPHID());
 
         if ($auditor_is_user || !$user_is_author) {
           $authority_audits[$audit->getID()] = $audit;
         }
       }
     }
     return $authority_audits;
   }
 
   public function save() {
     if (!$this->mailKey) {
       $this->mailKey = Filesystem::readRandomCharacters(20);
     }
     return parent::save();
   }
 
   public function delete() {
     $data = $this->loadCommitData();
     $audits = id(new PhabricatorRepositoryAuditRequest())
       ->loadAllWhere('commitPHID = %s', $this->getPHID());
     $this->openTransaction();
 
       if ($data) {
         $data->delete();
       }
       foreach ($audits as $audit) {
         $audit->delete();
       }
       $result = parent::delete();
 
     $this->saveTransaction();
     return $result;
   }
 
   public function getDateCreated() {
     // This is primarily to make analysis of commits with the Fact engine work.
     return $this->getEpoch();
   }
 
   public function getURI() {
     $repository = $this->getRepository();
     $callsign = $repository->getCallsign();
     $commit_identifier = $this->getCommitIdentifier();
     return '/r'.$callsign.$commit_identifier;
   }
 
   /**
    * Synchronize a commit's overall audit status with the individual audit
    * triggers.
    */
   public function updateAuditStatus(array $requests) {
     assert_instances_of($requests, 'PhabricatorRepositoryAuditRequest');
 
     $any_concern = false;
     $any_accept = false;
     $any_need = false;
 
     foreach ($requests as $request) {
       switch ($request->getAuditStatus()) {
         case PhabricatorAuditStatusConstants::AUDIT_REQUIRED:
           $any_need = true;
           break;
         case PhabricatorAuditStatusConstants::ACCEPTED:
           $any_accept = true;
           break;
         case PhabricatorAuditStatusConstants::CONCERNED:
           $any_concern = true;
           break;
       }
     }
 
     if ($any_concern) {
       $status = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
     } else if ($any_accept) {
       if ($any_need) {
         $status = PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED;
       } else {
         $status = PhabricatorAuditCommitStatusConstants::FULLY_AUDITED;
       }
     } else if ($any_need) {
       $status = PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT;
     } else {
       $status = PhabricatorAuditCommitStatusConstants::NONE;
     }
 
     return $this->setAuditStatus($status);
   }
 
 
 /* -(  PhabricatorPolicyInterface  )----------------------------------------- */
 
   public function getCapabilities() {
     return array(
       PhabricatorPolicyCapability::CAN_VIEW,
       PhabricatorPolicyCapability::CAN_EDIT,
     );
   }
 
   public function getPolicy($capability) {
     switch ($capability) {
       case PhabricatorPolicyCapability::CAN_VIEW:
         return $this->getRepository()->getPolicy($capability);
       case PhabricatorPolicyCapability::CAN_EDIT:
         // TODO: (T603) Who should be able to edit a commit? For now, retain
         // the existing policy.
         return PhabricatorPolicies::POLICY_USER;
     }
   }
 
   public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
     return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
   }
 
   public function describeAutomaticCapability($capability) {
     return pht(
       'Commits inherit the policies of the repository they belong to.');
   }
 
 
 /* -(  PhabricatorTokenReceiverInterface  )---------------------------------- */
 
   public function getUsersToNotifyOfTokenGiven() {
     return array(
       $this->getAuthorPHID(),
     );
   }
 
 /* -( Stuff for serialization )---------------------------------------------- */
 
   /**
    * NOTE: this is not a complete serialization; only the 'protected' fields are
    * involved. This is due to ease of (ab)using the Lisk abstraction to get this
    * done, as well as complexity of the other fields.
    */
   public function toDictionary() {
     return array(
       'repositoryID' => $this->getRepositoryID(),
       'phid' =>  $this->getPHID(),
       'commitIdentifier' =>  $this->getCommitIdentifier(),
       'epoch' => $this->getEpoch(),
       'mailKey' => $this->getMailKey(),
       'authorPHID' => $this->getAuthorPHID(),
       'auditStatus' => $this->getAuditStatus(),
       'summary' => $this->getSummary(),
       'importStatus' => $this->getImportStatus(),
     );
   }
 
   public static function newFromDictionary(array $dict) {
     return id(new PhabricatorRepositoryCommit())
       ->loadFromArray($dict);
   }
 
 
 /* -(  HarbormasterBuildableInterface  )------------------------------------- */
 
 
   public function getHarbormasterBuildablePHID() {
     return $this->getPHID();
   }
 
   public function getHarbormasterContainerPHID() {
     return $this->getRepository()->getPHID();
   }
 
   public function getBuildVariables() {
     $results = array();
 
     $results['buildable.commit'] = $this->getCommitIdentifier();
     $repo = $this->getRepository();
 
     $results['repository.callsign'] = $repo->getCallsign();
     $results['repository.vcs'] = $repo->getVersionControlSystem();
     $results['repository.uri'] = $repo->getPublicCloneURI();
 
     return $results;
   }
 
   public function getAvailableBuildVariables() {
     return array(
       'buildable.commit' => pht('The commit identifier, if applicable.'),
       'repository.callsign' =>
         pht('The callsign of the repository in Phabricator.'),
       'repository.vcs' =>
         pht('The version control system, either "svn", "hg" or "git".'),
       'repository.uri' =>
         pht('The URI to clone or checkout the repository from.'),
     );
   }
 
 
 /* -(  PhabricatorCustomFieldInterface  )------------------------------------ */
 
 
   public function getCustomFieldSpecificationForRole($role) {
     // TODO: We could make this configurable eventually, but just use the
     // defaults for now.
     return array();
   }
 
   public function getCustomFieldBaseClass() {
     return 'PhabricatorCommitCustomField';
   }
 
   public function getCustomFields() {
     return $this->assertAttached($this->customFields);
   }
 
   public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
     $this->customFields = $fields;
     return $this;
   }
 
 
 /* -(  PhabricatorSubscribableInterface  )----------------------------------- */
 
 
   public function isAutomaticallySubscribed($phid) {
 
     // TODO: This should also list auditors, but handling that is a bit messy
     // right now because we are not guaranteed to have the data.
 
     return ($phid == $this->getAuthorPHID());
   }
 
   public function shouldShowSubscribersProperty() {
     return true;
   }
 
   public function shouldAllowSubscription($phid) {
     return true;
   }
 
 
 /* -(  PhabricatorApplicationTransactionInterface  )------------------------- */
 
 
   public function getApplicationTransactionEditor() {
     return new PhabricatorAuditEditor();
   }
 
   public function getApplicationTransactionObject() {
     return $this;
   }
 
   public function getApplicationTransactionTemplate() {
     return new PhabricatorAuditTransaction();
   }
 
   public function willRenderTimeline(
     PhabricatorApplicationTransactionView $timeline,
     AphrontRequest $request) {
 
-    return $timeline;
+    $xactions = $timeline->getTransactions();
+
+    $path_ids = array();
+    foreach ($xactions as $xaction) {
+      if ($xaction->hasComment()) {
+        $path_id = $xaction->getComment()->getPathID();
+        if ($path_id) {
+          $path_ids[] = $path_id;
+        }
+      }
+    }
+
+    $path_map = array();
+    if ($path_ids) {
+      $path_map = id(new DiffusionPathQuery())
+        ->withPathIDs($path_ids)
+        ->execute();
+      $path_map = ipull($path_map, 'path', 'id');
+    }
+
+    return $timeline->setPathMap($path_map);
   }
 
 }