diff --git a/externals/javelin b/externals/javelin
index 099162f62b..b982d964e2 160000
--- a/externals/javelin
+++ b/externals/javelin
@@ -1 +1 @@
-Subproject commit 099162f62bbb154c2d906cbe3c7ab3e58e89be7e
+Subproject commit b982d964e266ed0a6982cb2b6eda7866c301e118
diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index f54b4aae6e..be49edff3f 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -1,1049 +1,1049 @@
 <?php
 
 /**
  * This file is automatically generated. Use 'celerity_mapper.php' to rebuild
  * it.
  * @generated
  */
 
 celerity_register_resource_map(array(
   'aphront-crumbs-view-css' =>
   array(
     'uri' => '/res/c666a518/rsrc/css/aphront/crumbs-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/crumbs-view.css',
   ),
   'aphront-dark-console-css' =>
   array(
     'uri' => '/res/0417eb95/rsrc/css/aphront/dark-console.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/dark-console.css',
   ),
   'aphront-dialog-view-css' =>
   array(
     'uri' => '/res/9be517dc/rsrc/css/aphront/dialog-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/dialog-view.css',
   ),
   'aphront-error-view-css' =>
   array(
     'uri' => '/res/19b27527/rsrc/css/aphront/error-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/error-view.css',
   ),
   'aphront-form-view-css' =>
   array(
     'uri' => '/res/82eca506/rsrc/css/aphront/form-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/form-view.css',
   ),
   'aphront-headsup-action-list-view-css' =>
   array(
     'uri' => '/res/fe9accb9/rsrc/css/aphront/headsup-action-list-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/headsup-action-list-view.css',
   ),
   'aphront-list-filter-view-css' =>
   array(
     'uri' => '/res/50a790ae/rsrc/css/aphront/list-filter-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/list-filter-view.css',
   ),
   'aphront-pager-view-css' =>
   array(
     'uri' => '/res/73ec8cd5/rsrc/css/aphront/pager-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/pager-view.css',
   ),
   'aphront-panel-view-css' =>
   array(
     'uri' => '/res/8f9f3632/rsrc/css/aphront/panel-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/panel-view.css',
   ),
   'aphront-request-failure-view-css' =>
   array(
     'uri' => '/res/97b8337a/rsrc/css/aphront/request-failure-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/request-failure-view.css',
   ),
   'aphront-side-nav-view-css' =>
   array(
     'uri' => '/res/4f4c5ca8/rsrc/css/aphront/side-nav-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/side-nav-view.css',
   ),
   'aphront-table-view-css' =>
   array(
     'uri' => '/res/f09b7da6/rsrc/css/aphront/table-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/table-view.css',
   ),
   'aphront-tokenizer-control-css' =>
   array(
     'uri' => '/res/190349be/rsrc/css/aphront/tokenizer.css',
     'type' => 'css',
     'requires' =>
     array(
       0 => 'aphront-typeahead-control-css',
     ),
     'disk' => '/rsrc/css/aphront/tokenizer.css',
   ),
   'aphront-typeahead-control-css' =>
   array(
     'uri' => '/res/928df9f0/rsrc/css/aphront/typeahead.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/aphront/typeahead.css',
   ),
   'differential-changeset-view-css' =>
   array(
     'uri' => '/res/32a8bac6/rsrc/css/application/differential/changeset-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/changeset-view.css',
   ),
   'differential-core-view-css' =>
   array(
     'uri' => '/res/525d1a12/rsrc/css/application/differential/core.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/core.css',
   ),
   'differential-revision-add-comment-css' =>
   array(
     'uri' => '/res/aaae14d3/rsrc/css/application/differential/add-comment.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/add-comment.css',
   ),
   'differential-revision-comment-css' =>
   array(
     'uri' => '/res/7185c7fe/rsrc/css/application/differential/revision-comment.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/revision-comment.css',
   ),
   'differential-revision-comment-list-css' =>
   array(
     'uri' => '/res/10b9a829/rsrc/css/application/differential/revision-comment-list.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/revision-comment-list.css',
   ),
   'differential-revision-detail-css' =>
   array(
     'uri' => '/res/a63e2d06/rsrc/css/application/differential/revision-detail.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/revision-detail.css',
   ),
   'differential-revision-history-css' =>
   array(
     'uri' => '/res/755f3da3/rsrc/css/application/differential/revision-history.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/revision-history.css',
   ),
   'differential-table-of-contents-css' =>
   array(
     'uri' => '/res/e68f6f05/rsrc/css/application/differential/table-of-contents.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/differential/table-of-contents.css',
   ),
   'diffusion-commit-view-css' =>
   array(
     'uri' => '/res/8c139192/rsrc/css/application/diffusion/commit-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/diffusion/commit-view.css',
   ),
   'diffusion-source-css' =>
   array(
     'uri' => '/res/7f50817b/rsrc/css/application/diffusion/diffusion-source.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/diffusion/diffusion-source.css',
   ),
   'herald-css' =>
   array(
     'uri' => '/res/211a4b1b/rsrc/css/application/herald/herald.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/herald/herald.css',
   ),
   'herald-rule-editor' =>
   array(
     'uri' => '/res/f3122b0a/rsrc/js/application/herald/HeraldRuleEditor.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'multirow-row-manager',
       1 => 'javelin-install',
       2 => 'javelin-typeahead',
       3 => 'javelin-util',
       4 => 'javelin-dom',
       5 => 'javelin-tokenizer',
       6 => 'javelin-typeahead-preloaded-source',
       7 => 'javelin-stratcom',
       8 => 'javelin-json',
     ),
     'disk' => '/rsrc/js/application/herald/HeraldRuleEditor.js',
   ),
   'herald-test-css' =>
   array(
     'uri' => '/res/28269358/rsrc/css/application/herald/herald-test.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/herald/herald-test.css',
   ),
   'javelin-behavior' =>
   array(
-    'uri' => '/res/dc576a49/rsrc/js/javelin/lib/behavior.js',
+    'uri' => '/res/d7ba2775/rsrc/js/javelin/lib/behavior.js',
     'type' => 'js',
     'requires' =>
     array(
+      0 => 'javelin-magical-init',
     ),
     'disk' => '/rsrc/js/javelin/lib/behavior.js',
   ),
   'javelin-behavior-aphront-basic-tokenizer' =>
   array(
     'uri' => '/res/d48d2732/rsrc/js/application/core/behavior-tokenizer.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-typeahead',
       2 => 'javelin-tokenizer',
       3 => 'javelin-typeahead-preloaded-source',
       4 => 'javelin-dom',
     ),
     'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
   ),
   0 =>
   array(
     'uri' => '/res/e3d992aa/rsrc/js/javelin/docs/Base.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
     ),
     'disk' => '/rsrc/js/javelin/docs/Base.js',
   ),
   'javelin-behavior-dark-console' =>
   array(
     'uri' => '/res/447bd50a/rsrc/js/application/core/behavior-dark-console.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-stratcom',
       2 => 'javelin-util',
       3 => 'javelin-dom',
       4 => 'javelin-request',
     ),
     'disk' => '/rsrc/js/application/core/behavior-dark-console.js',
   ),
   'javelin-behavior-differential-add-reviewers' =>
   array(
     'uri' => '/res/fa2f29c4/rsrc/js/application/differential/behavior-add-reviewers.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-dom',
       2 => 'javelin-tokenizer',
       3 => 'javelin-typeahead',
       4 => 'javelin-typeahead-preloaded-source',
     ),
     'disk' => '/rsrc/js/application/differential/behavior-add-reviewers.js',
   ),
   'javelin-behavior-differential-diff-radios' =>
   array(
     'uri' => '/res/d3365dba/rsrc/js/application/differential/behavior-diff-radios.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-stratcom',
       2 => 'javelin-dom',
     ),
     'disk' => '/rsrc/js/application/differential/behavior-diff-radios.js',
   ),
   'javelin-behavior-differential-edit-inline-comments' =>
   array(
     'uri' => '/res/f18ee6ae/rsrc/js/application/differential/behavior-edit-inline-comments.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-stratcom',
       2 => 'javelin-dom',
       3 => 'javelin-workflow',
       4 => 'javelin-vector',
     ),
     'disk' => '/rsrc/js/application/differential/behavior-edit-inline-comments.js',
   ),
   'javelin-behavior-differential-feedback-preview' =>
   array(
     'uri' => '/res/139c85b8/rsrc/js/application/differential/behavior-comment-preview.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-stratcom',
       2 => 'javelin-dom',
       3 => 'javelin-request',
       4 => 'javelin-util',
     ),
     'disk' => '/rsrc/js/application/differential/behavior-comment-preview.js',
   ),
   'javelin-behavior-differential-populate' =>
   array(
     'uri' => '/res/d4d4fd9d/rsrc/js/application/differential/behavior-populate.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-request',
       2 => 'javelin-util',
       3 => 'javelin-dom',
     ),
     'disk' => '/rsrc/js/application/differential/behavior-populate.js',
   ),
   'javelin-behavior-differential-show-all-comments' =>
   array(
     'uri' => '/res/4d34a1e7/rsrc/js/application/differential/behavior-show-all-comments.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-stratcom',
       2 => 'javelin-dom',
     ),
     'disk' => '/rsrc/js/application/differential/behavior-show-all-comments.js',
   ),
   'javelin-behavior-differential-show-more' =>
   array(
     'uri' => '/res/6af8c5bb/rsrc/js/application/differential/behavior-show-more.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-dom',
       2 => 'javelin-request',
       3 => 'javelin-util',
       4 => 'javelin-stratcom',
     ),
     'disk' => '/rsrc/js/application/differential/behavior-show-more.js',
   ),
   'javelin-behavior-diffusion-jump-to' =>
   array(
     'uri' => '/res/2a8ca30b/rsrc/js/application/diffusion/behavior-jump-to.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-util',
       2 => 'javelin-vector',
       3 => 'javelin-dom',
     ),
     'disk' => '/rsrc/js/application/diffusion/behavior-jump-to.js',
   ),
   'javelin-behavior-diffusion-pull-lastmodified' =>
   array(
     'uri' => '/res/f3e3f3a6/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-dom',
       2 => 'javelin-util',
       3 => 'javelin-request',
     ),
     'disk' => '/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
   ),
   'javelin-behavior-error-log' =>
   array(
     'uri' => '/res/ad4e82d4/rsrc/js/application/core/behavior-error-log.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-dom',
     ),
     'disk' => '/rsrc/js/application/core/behavior-error-log.js',
   ),
   'javelin-behavior-herald-rule-editor' =>
   array(
     'uri' => '/res/f18bcd5e/rsrc/js/application/herald/herald-rule-editor.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'herald-rule-editor',
       1 => 'javelin-behavior',
     ),
     'disk' => '/rsrc/js/application/herald/herald-rule-editor.js',
   ),
   'javelin-behavior-maniphest-transaction-controls' =>
   array(
     'uri' => '/res/f2eae88a/rsrc/js/application/maniphest/behavior-transaction-controls.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-dom',
       2 => 'javelin-tokenizer',
       3 => 'javelin-typeahead',
       4 => 'javelin-typeahead-preloaded-source',
     ),
     'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js',
   ),
   'javelin-behavior-owners-path-editor' =>
   array(
     'uri' => '/res/b379a0d4/rsrc/js/application/owners/owners-path-editor.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'owners-path-editor',
       1 => 'javelin-behavior',
     ),
     'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
   ),
   'javelin-behavior-phabricator-object-selector' =>
   array(
     'uri' => '/res/e899a55e/rsrc/js/application/core/behavior-object-selector.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-dom',
       2 => 'javelin-request',
       3 => 'javelin-util',
       4 => 'javelin-stratcom',
     ),
     'disk' => '/rsrc/js/application/core/behavior-object-selector.js',
   ),
   'javelin-behavior-workflow' =>
   array(
     'uri' => '/res/b5bc59cb/rsrc/js/application/core/behavior-workflow.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-behavior',
       1 => 'javelin-stratcom',
       2 => 'javelin-workflow',
     ),
     'disk' => '/rsrc/js/application/core/behavior-workflow.js',
   ),
   'javelin-dom' =>
   array(
-    'uri' => '/res/21c1392d/rsrc/js/javelin/lib/DOM.js',
+    'uri' => '/res/37590eec/rsrc/js/javelin/lib/DOM.js',
     'type' => 'js',
     'requires' =>
     array(
-      0 => 'javelin-install',
-      1 => 'javelin-util',
-      2 => 'javelin-vector',
-      3 => 'javelin-stratcom',
+      0 => 'javelin-magical-init',
+      1 => 'javelin-install',
+      2 => 'javelin-util',
+      3 => 'javelin-vector',
+      4 => 'javelin-stratcom',
     ),
     'disk' => '/rsrc/js/javelin/lib/DOM.js',
   ),
   'javelin-event' =>
   array(
     'uri' => '/res/807b95e6/rsrc/js/javelin/core/Event.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
     ),
     'disk' => '/rsrc/js/javelin/core/Event.js',
   ),
   'javelin-install' =>
   array(
-    'uri' => '/res/c11fe5b3/rsrc/js/javelin/core/install.js',
+    'uri' => '/res/a46b4e6d/rsrc/js/javelin/core/install.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-util',
+      1 => 'javelin-magical-init',
     ),
     'disk' => '/rsrc/js/javelin/core/install.js',
   ),
   'javelin-json' =>
   array(
     'uri' => '/res/62c8cc8d/rsrc/js/javelin/lib/JSON.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-util',
     ),
     'disk' => '/rsrc/js/javelin/lib/JSON.js',
   ),
   'javelin-magical-init' =>
   array(
-    'uri' => '/res/6d53e259/rsrc/js/javelin/core/init.js',
+    'uri' => '/res/929da242/rsrc/js/javelin/core/init.js',
     'type' => 'js',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/js/javelin/core/init.js',
   ),
   'javelin-mask' =>
   array(
     'uri' => '/res/ba2f665a/rsrc/js/javelin/lib/Mask.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-vector',
       2 => 'javelin-dom',
     ),
     'disk' => '/rsrc/js/javelin/lib/Mask.js',
   ),
   'javelin-request' =>
   array(
     'uri' => '/res/3947083d/rsrc/js/javelin/lib/Request.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-stratcom',
       2 => 'javelin-util',
       3 => 'javelin-behavior',
     ),
     'disk' => '/rsrc/js/javelin/lib/Request.js',
   ),
   'javelin-stratcom' =>
   array(
     'uri' => '/res/3421b115/rsrc/js/javelin/core/Stratcom.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-event',
       2 => 'javelin-util',
       3 => 'javelin-magical-init',
     ),
     'disk' => '/rsrc/js/javelin/core/Stratcom.js',
   ),
   'javelin-tokenizer' =>
   array(
-    'uri' => '/res/74fe92c6/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
+    'uri' => '/res/f45e7c70/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
     'type' => 'js',
     'requires' =>
     array(
-      0 => 'javelin-typeahead',
-      1 => 'javelin-dom',
-      2 => 'javelin-util',
-      3 => 'javelin-stratcom',
-      4 => 'javelin-vector',
-      5 => 'javelin-install',
-      6 => 'javelin-typeahead-preloaded-source',
+      0 => 'javelin-dom',
+      1 => 'javelin-util',
+      2 => 'javelin-stratcom',
+      3 => 'javelin-install',
     ),
     'disk' => '/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
   ),
   'javelin-typeahead' =>
   array(
     'uri' => '/res/5a701345/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-dom',
       2 => 'javelin-vector',
       3 => 'javelin-util',
     ),
     'disk' => '/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
   ),
   'javelin-typeahead-normalizer' =>
   array(
     'uri' => '/res/8d49e2de/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
     ),
     'disk' => '/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
   ),
   'javelin-typeahead-ondemand-source' =>
   array(
     'uri' => '/res/00b46be8/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-util',
       2 => 'javelin-stratcom',
       3 => 'javelin-request',
       4 => 'javelin-typeahead-source',
     ),
     'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
   ),
   'javelin-typeahead-preloaded-source' =>
   array(
     'uri' => '/res/aefaf410/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-util',
       2 => 'javelin-stratcom',
       3 => 'javelin-request',
       4 => 'javelin-typeahead-source',
     ),
     'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
   ),
   'javelin-typeahead-source' =>
   array(
     'uri' => '/res/b1184e7d/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-util',
       2 => 'javelin-dom',
       3 => 'javelin-typeahead-normalizer',
     ),
     'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
   ),
   'javelin-uri' =>
   array(
-    'uri' => '/res/03448af9/rsrc/js/javelin/lib/URI.js',
+    'uri' => '/res/07a16bd9/rsrc/js/javelin/lib/URI.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-util',
+      2 => 'javelin-stratcom',
     ),
     'disk' => '/rsrc/js/javelin/lib/URI.js',
   ),
   'javelin-util' =>
   array(
-    'uri' => '/res/031851eb/rsrc/js/javelin/core/util.js',
+    'uri' => '/res/f32d6b81/rsrc/js/javelin/core/util.js',
     'type' => 'js',
     'requires' =>
     array(
-      0 => 'javelin-magical-init',
     ),
     'disk' => '/rsrc/js/javelin/core/util.js',
   ),
   'javelin-vector' =>
   array(
-    'uri' => '/res/184e9d71/rsrc/js/javelin/lib/Vector.js',
+    'uri' => '/res/12daf99c/rsrc/js/javelin/lib/Vector.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-event',
     ),
     'disk' => '/rsrc/js/javelin/lib/Vector.js',
   ),
   'javelin-workflow' =>
   array(
-    'uri' => '/res/24389bc8/rsrc/js/javelin/lib/Workflow.js',
+    'uri' => '/res/8ddfc3cc/rsrc/js/javelin/lib/Workflow.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-stratcom',
       1 => 'javelin-request',
       2 => 'javelin-dom',
       3 => 'javelin-vector',
       4 => 'javelin-install',
       5 => 'javelin-util',
       6 => 'javelin-mask',
       7 => 'javelin-uri',
     ),
     'disk' => '/rsrc/js/javelin/lib/Workflow.js',
   ),
   'mainphest-task-detail-css' =>
   array(
     'uri' => '/res/e5f3beca/rsrc/css/application/maniphest/task-detail.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/maniphest/task-detail.css',
   ),
   'maniphest-task-summary-css' =>
   array(
     'uri' => '/res/8dc6fb13/rsrc/css/application/maniphest/task-summary.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/maniphest/task-summary.css',
   ),
   'maniphest-transaction-detail-css' =>
   array(
     'uri' => '/res/16725026/rsrc/css/application/maniphest/transaction-detail.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/maniphest/transaction-detail.css',
   ),
   'multirow-row-manager' =>
   array(
     'uri' => '/res/cae26c67/rsrc/js/application/core/MultirowRowManager.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-stratcom',
       2 => 'javelin-dom',
       3 => 'javelin-util',
     ),
     'disk' => '/rsrc/js/application/core/MultirowRowManager.js',
   ),
   'owners-path-editor' =>
   array(
     'uri' => '/res/003f3d3f/rsrc/js/application/owners/OwnersPathEditor.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'multirow-row-manager',
       1 => 'javelin-install',
       2 => 'path-typeahead',
       3 => 'javelin-dom',
       4 => 'javelin-util',
     ),
     'disk' => '/rsrc/js/application/owners/OwnersPathEditor.js',
   ),
   'owners-path-editor-css' =>
   array(
     'uri' => '/res/f40dc6b1/rsrc/css/application/owners/owners-path-editor.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/owners/owners-path-editor.css',
   ),
   'path-typeahead' =>
   array(
     'uri' => '/res/594d2576/rsrc/js/application/herald/PathTypeahead.js',
     'type' => 'js',
     'requires' =>
     array(
       0 => 'javelin-install',
       1 => 'javelin-typeahead',
       2 => 'javelin-dom',
       3 => 'javelin-request',
       4 => 'javelin-typeahead-ondemand-source',
       5 => 'javelin-util',
     ),
     'disk' => '/rsrc/js/application/herald/PathTypeahead.js',
   ),
   'phabricator-core-buttons-css' =>
   array(
     'uri' => '/res/53b4f712/rsrc/css/core/buttons.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/core/buttons.css',
   ),
   'phabricator-core-css' =>
   array(
     'uri' => '/res/6eebb99b/rsrc/css/core/core.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/core/core.css',
   ),
   'phabricator-directory-css' =>
   array(
     'uri' => '/res/6a000601/rsrc/css/application/directory/phabricator-directory.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/directory/phabricator-directory.css',
   ),
   'phabricator-object-selector-css' =>
   array(
     'uri' => '/res/52a7e289/rsrc/css/application/objectselector/object-selector.css',
     'type' => 'css',
     'requires' =>
     array(
       0 => 'aphront-dialog-view-css',
     ),
     'disk' => '/rsrc/css/application/objectselector/object-selector.css',
   ),
   'phabricator-profile-css' =>
   array(
     'uri' => '/res/259ad37f/rsrc/css/application/people/profile.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/people/profile.css',
   ),
   'phabricator-remarkup-css' =>
   array(
     'uri' => '/res/41748e59/rsrc/css/core/remarkup.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/core/remarkup.css',
   ),
   'phabricator-standard-page-view' =>
   array(
     'uri' => '/res/0d41ea7c/rsrc/css/application/base/standard-page-view.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/base/standard-page-view.css',
   ),
   'phabricator-ui-example-css' =>
   array(
     'uri' => '/res/365a10f1/rsrc/css/application/uiexample/example.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/application/uiexample/example.css',
   ),
   'syntax-highlighting-css' =>
   array(
     'uri' => '/res/fb673ece/rsrc/css/core/syntax.css',
     'type' => 'css',
     'requires' =>
     array(
     ),
     'disk' => '/rsrc/css/core/syntax.css',
   ),
 ), array (
   'packages' =>
   array (
+    '22ec468f' =>
+    array (
+      'name' => 'javelin.pkg.js',
+      'symbols' =>
+      array (
+        0 => 'javelin-util',
+        1 => 'javelin-install',
+        2 => 'javelin-event',
+        3 => 'javelin-stratcom',
+        4 => 'javelin-behavior',
+        5 => 'javelin-request',
+        6 => 'javelin-vector',
+        7 => 'javelin-dom',
+        8 => 'javelin-json',
+        9 => 'javelin-uri',
+      ),
+      'uri' => '/res/pkg/22ec468f/javelin.pkg.js',
+      'type' => 'js',
+    ),
     '3b698834' =>
     array (
       'name' => 'differential.pkg.js',
       'symbols' =>
       array (
         0 => 'javelin-behavior-differential-feedback-preview',
         1 => 'javelin-behavior-differential-edit-inline-comments',
         2 => 'javelin-behavior-differential-populate',
         3 => 'javelin-behavior-differential-show-more',
         4 => 'javelin-behavior-differential-diff-radios',
       ),
       'uri' => '/res/pkg/3b698834/differential.pkg.js',
       'type' => 'js',
     ),
-    '71a78877' =>
-    array (
-      'name' => 'workflow.pkg.js',
-      'symbols' =>
-      array (
-        0 => 'javelin-mask',
-        1 => 'javelin-workflow',
-        2 => 'javelin-behavior-workflow',
-      ),
-      'uri' => '/res/pkg/71a78877/workflow.pkg.js',
-      'type' => 'js',
-    ),
     '8e4ef51b' =>
     array (
       'name' => 'differential.pkg.css',
       'symbols' =>
       array (
         0 => 'differential-core-view-css',
         1 => 'differential-changeset-view-css',
         2 => 'differential-revision-detail-css',
         3 => 'differential-revision-history-css',
         4 => 'differential-table-of-contents-css',
         5 => 'differential-revision-comment-css',
         6 => 'differential-revision-add-comment-css',
         7 => 'differential-revision-comment-list-css',
       ),
       'uri' => '/res/pkg/8e4ef51b/differential.pkg.css',
       'type' => 'css',
     ),
-    'a44a7841' =>
+    '9ceae8e2' =>
     array (
-      'name' => 'typeahead.pkg.js',
+      'name' => 'workflow.pkg.js',
       'symbols' =>
       array (
-        0 => 'javelin-typeahead',
-        1 => 'javelin-typeahead-normalizer',
-        2 => 'javelin-typeahead-source',
-        3 => 'javelin-typeahead-preloaded-source',
-        4 => 'javelin-typeahead-ondemand-source',
-        5 => 'javelin-tokenizer',
-        6 => 'javelin-behavior-aphront-basic-tokenizer',
+        0 => 'javelin-mask',
+        1 => 'javelin-workflow',
+        2 => 'javelin-behavior-workflow',
       ),
-      'uri' => '/res/pkg/a44a7841/typeahead.pkg.js',
+      'uri' => '/res/pkg/9ceae8e2/workflow.pkg.js',
       'type' => 'js',
     ),
     'c4276ad7' =>
     array (
       'name' => 'core.pkg.css',
       'symbols' =>
       array (
         0 => 'phabricator-core-css',
         1 => 'phabricator-core-buttons-css',
         2 => 'phabricator-standard-page-view',
         3 => 'aphront-dialog-view-css',
         4 => 'aphront-form-view-css',
         5 => 'aphront-panel-view-css',
         6 => 'aphront-side-nav-view-css',
         7 => 'aphront-table-view-css',
         8 => 'aphront-crumbs-view-css',
         9 => 'aphront-tokenizer-control-css',
         10 => 'aphront-typeahead-control-css',
         11 => 'aphront-list-filter-view-css',
         12 => 'phabricator-directory-css',
         13 => 'phabricator-remarkup-css',
         14 => 'syntax-highlighting-css',
       ),
       'uri' => '/res/pkg/c4276ad7/core.pkg.css',
       'type' => 'css',
     ),
-    'eadf6ec3' =>
+    'dc82a12d' =>
     array (
-      'name' => 'diffusion.pkg.css',
+      'name' => 'typeahead.pkg.js',
       'symbols' =>
       array (
-        0 => 'diffusion-commit-view-css',
+        0 => 'javelin-typeahead',
+        1 => 'javelin-typeahead-normalizer',
+        2 => 'javelin-typeahead-source',
+        3 => 'javelin-typeahead-preloaded-source',
+        4 => 'javelin-typeahead-ondemand-source',
+        5 => 'javelin-tokenizer',
+        6 => 'javelin-behavior-aphront-basic-tokenizer',
       ),
-      'uri' => '/res/pkg/eadf6ec3/diffusion.pkg.css',
-      'type' => 'css',
+      'uri' => '/res/pkg/dc82a12d/typeahead.pkg.js',
+      'type' => 'js',
     ),
-    'fc6ed8bc' =>
+    'eadf6ec3' =>
     array (
-      'name' => 'javelin.pkg.js',
+      'name' => 'diffusion.pkg.css',
       'symbols' =>
       array (
-        0 => 'javelin-util',
-        1 => 'javelin-install',
-        2 => 'javelin-event',
-        3 => 'javelin-stratcom',
-        4 => 'javelin-behavior',
-        5 => 'javelin-request',
-        6 => 'javelin-vector',
-        7 => 'javelin-dom',
-        8 => 'javelin-json',
-        9 => 'javelin-uri',
+        0 => 'diffusion-commit-view-css',
       ),
-      'uri' => '/res/pkg/fc6ed8bc/javelin.pkg.js',
-      'type' => 'js',
+      'uri' => '/res/pkg/eadf6ec3/diffusion.pkg.css',
+      'type' => 'css',
     ),
   ),
   'reverse' =>
   array (
     'aphront-crumbs-view-css' => 'c4276ad7',
     'aphront-dialog-view-css' => 'c4276ad7',
     'aphront-form-view-css' => 'c4276ad7',
     'aphront-list-filter-view-css' => 'c4276ad7',
     'aphront-panel-view-css' => 'c4276ad7',
     'aphront-side-nav-view-css' => 'c4276ad7',
     'aphront-table-view-css' => 'c4276ad7',
     'aphront-tokenizer-control-css' => 'c4276ad7',
     'aphront-typeahead-control-css' => 'c4276ad7',
     'differential-changeset-view-css' => '8e4ef51b',
     'differential-core-view-css' => '8e4ef51b',
     'differential-revision-add-comment-css' => '8e4ef51b',
     'differential-revision-comment-css' => '8e4ef51b',
     'differential-revision-comment-list-css' => '8e4ef51b',
     'differential-revision-detail-css' => '8e4ef51b',
     'differential-revision-history-css' => '8e4ef51b',
     'differential-table-of-contents-css' => '8e4ef51b',
     'diffusion-commit-view-css' => 'eadf6ec3',
-    'javelin-behavior' => 'fc6ed8bc',
-    'javelin-behavior-aphront-basic-tokenizer' => 'a44a7841',
+    'javelin-behavior' => '22ec468f',
+    'javelin-behavior-aphront-basic-tokenizer' => 'dc82a12d',
     'javelin-behavior-differential-diff-radios' => '3b698834',
     'javelin-behavior-differential-edit-inline-comments' => '3b698834',
     'javelin-behavior-differential-feedback-preview' => '3b698834',
     'javelin-behavior-differential-populate' => '3b698834',
     'javelin-behavior-differential-show-more' => '3b698834',
-    'javelin-behavior-workflow' => '71a78877',
-    'javelin-dom' => 'fc6ed8bc',
-    'javelin-event' => 'fc6ed8bc',
-    'javelin-install' => 'fc6ed8bc',
-    'javelin-json' => 'fc6ed8bc',
-    'javelin-mask' => '71a78877',
-    'javelin-request' => 'fc6ed8bc',
-    'javelin-stratcom' => 'fc6ed8bc',
-    'javelin-tokenizer' => 'a44a7841',
-    'javelin-typeahead' => 'a44a7841',
-    'javelin-typeahead-normalizer' => 'a44a7841',
-    'javelin-typeahead-ondemand-source' => 'a44a7841',
-    'javelin-typeahead-preloaded-source' => 'a44a7841',
-    'javelin-typeahead-source' => 'a44a7841',
-    'javelin-uri' => 'fc6ed8bc',
-    'javelin-util' => 'fc6ed8bc',
-    'javelin-vector' => 'fc6ed8bc',
-    'javelin-workflow' => '71a78877',
+    'javelin-behavior-workflow' => '9ceae8e2',
+    'javelin-dom' => '22ec468f',
+    'javelin-event' => '22ec468f',
+    'javelin-install' => '22ec468f',
+    'javelin-json' => '22ec468f',
+    'javelin-mask' => '9ceae8e2',
+    'javelin-request' => '22ec468f',
+    'javelin-stratcom' => '22ec468f',
+    'javelin-tokenizer' => 'dc82a12d',
+    'javelin-typeahead' => 'dc82a12d',
+    'javelin-typeahead-normalizer' => 'dc82a12d',
+    'javelin-typeahead-ondemand-source' => 'dc82a12d',
+    'javelin-typeahead-preloaded-source' => 'dc82a12d',
+    'javelin-typeahead-source' => 'dc82a12d',
+    'javelin-uri' => '22ec468f',
+    'javelin-util' => '22ec468f',
+    'javelin-vector' => '22ec468f',
+    'javelin-workflow' => '9ceae8e2',
     'phabricator-core-buttons-css' => 'c4276ad7',
     'phabricator-core-css' => 'c4276ad7',
     'phabricator-directory-css' => 'c4276ad7',
     'phabricator-remarkup-css' => 'c4276ad7',
     'phabricator-standard-page-view' => 'c4276ad7',
     'syntax-highlighting-css' => 'c4276ad7',
   ),
 ));
diff --git a/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php b/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php
index 0843022834..15ca7b92c0 100644
--- a/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php
+++ b/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php
@@ -1,207 +1,211 @@
 <?php
 
 /*
  * Copyright 2011 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 class PhabricatorJavelinLinter extends ArcanistLinter {
 
   private $symbols = array();
 
   const LINT_PRIVATE_ACCESS = 1;
   const LINT_MISSING_DEPENDENCY = 2;
   const LINT_UNNECESSARY_DEPENDENCY = 3;
   const LINT_UNKNOWN_DEPENDENCY = 4;
 
   public function willLintPaths(array $paths) {
     $futures = array();
     foreach ($paths as $path) {
       $future = $this->newSymbolsFuture($path);
       $futures[$path] = $future;
     }
 
     foreach (Futures($futures)->limit(8) as $path => $future) {
       $this->symbols[$path] = $future->resolvex();
     }
   }
 
   public function getLinterName() {
     return 'JAVELIN';
   }
 
   public function getLintSeverityMap() {
     return array();
   }
 
   public function getLintNameMap() {
     return array(
       self::LINT_PRIVATE_ACCESS => 'Private Method/Member Access',
       self::LINT_MISSING_DEPENDENCY => 'Missing Javelin Dependency',
       self::LINT_UNNECESSARY_DEPENDENCY => 'Unnecessary Javelin Dependency',
       self::LINT_UNKNOWN_DEPENDENCY => 'Unknown Javelin Dependency',
     );
   }
 
   public function lintPath($path) {
 
     list($uses, $installs) = $this->getUsedAndInstalledSymbolsForPath($path);
     foreach ($uses as $symbol => $line) {
       $parts = explode('.', $symbol);
       foreach ($parts as $part) {
         if ($part[0] == '_' && $part[1] != '_') {
           $base = implode('.', array_slice($parts, 0, 2));
           if (!array_key_exists($base, $installs)) {
             $this->raiseLintAtLine(
               $line,
               0,
               self::LINT_PRIVATE_ACCESS,
               "This file accesses private symbol '{$symbol}' across file ".
               "boundaries. You may only access private members and methods ".
               "from the file where they are defined.");
           }
           break;
         }
       }
     }
 
     if ($this->getEngine()->getCommitHookMode()) {
       // Don't do the dependency checks in commit-hook mode because we won't
       // have an available working copy.
       return;
     }
 
     $external_classes = array();
     foreach ($uses as $symbol => $line) {
       $parts = explode('.', $symbol);
       $class = implode('.', array_slice($parts, 0, 2));
       if (!array_key_exists($class, $external_classes) &&
           !array_key_exists($class, $installs)) {
         $external_classes[$class] = $line;
       }
     }
 
     $celerity = CelerityResourceMap::getInstance();
 
+    $path = preg_replace(
+      '@^externals/javelin/src/@',
+      'webroot/rsrc/js/javelin/',
+      $path);
     $info = $celerity->lookupFileInformation(substr($path, strlen('webroot')));
 
     $need = $external_classes;
 
     $requires = $info['requires'];
 
     foreach ($requires as $key => $name) {
       $symbol_info = $celerity->lookupSymbolInformation($name);
       if (!$symbol_info) {
         $this->raiseLintAtLine(
           0,
           0,
           self::LINT_UNKNOWN_DEPENDENCY,
           "This file @requires component '{$name}', but it does not ".
           "exist. You may need to rebuild the Celerity map.");
         unset($requires[$key]);
         continue;
       }
 
       $symbol_path = 'webroot'.$symbol_info['disk'];
       list($ignored, $req_install) = $this->getUsedAndInstalledSymbolsForPath(
         $symbol_path);
       if (array_intersect_key($req_install, $external_classes)) {
         $need = array_diff_key($need, $req_install);
         unset($requires[$key]);
       }
     }
 
     foreach ($need as $class => $line) {
       $this->raiseLintAtLine(
         $line,
         0,
         self::LINT_MISSING_DEPENDENCY,
         "This file uses '{$class}' but does not @requires the component ".
         "which installs it. You may need to rebuild the Celerity map.");
     }
 
     foreach ($requires as $component) {
       $this->raiseLintAtLine(
-        $line,
+        0,
         0,
         self::LINT_UNNECESSARY_DEPENDENCY,
         "This file @requires component '{$component}' but does not use ".
         "anything it provides.");
     }
   }
 
   private function loadSymbols($path) {
     if (empty($this->symbols[$path])) {
       $this->symbols[$path] = $this->newSymbolsFuture($path)->resolvex();
     }
     return $this->symbols[$path];
   }
 
   private function newSymbolsFuture($path) {
     $root = dirname(phutil_get_library_root('phabricator'));
 
     $support = $root.'/externals/javelin/support';
     $javelinsymbols = $support.'/javelinsymbols/javelinsymbols';
 
     $future = new ExecFuture($javelinsymbols.' # '.escapeshellarg($path));
     $future->write($this->getData($path));
     return $future;
   }
 
   private function getUsedAndInstalledSymbolsForPath($path) {
     list($symbols) = $this->loadSymbols($path);
 
     $symbols = explode("\n", trim($symbols));
 
     $uses = array();
     $installs = array();
     foreach ($symbols as $line) {
       $matches = null;
       if (!preg_match('/^([?+])([^:]*):(\d+)$/', $line, $matches)) {
         throw new Exception(
           "Received malformed output from `javelinsymbols`.");
       }
       $type = $matches[1];
       $symbol = $matches[2];
       $line = $matches[3];
 
       switch ($type) {
         case '?':
           $uses[$symbol] = $line;
           break;
         case '+':
           $installs['JX.'.$symbol] = $line;
           break;
       }
     }
 
     $contents = $this->getData($path);
 
     $matches = null;
     $count = preg_match_all(
       '/@javelin-installs\W+(\S+)/',
       $contents,
       $matches,
       PREG_PATTERN_ORDER);
 
     if ($count) {
       foreach ($matches[1] as $symbol) {
         $installs[$symbol] = 0;
       }
     }
 
     return array($uses, $installs);
   }
 
 }