diff --git a/resources/celerity/map.php b/resources/celerity/map.php
index d09a30d901..8e94ccd067 100644
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -1,2477 +1,2477 @@
 <?php
 
 /**
  * This file is automatically generated. Use 'bin/celerity map' to rebuild it.
  *
  * @generated
  */
 return array(
   'names' => array(
     'conpherence.pkg.css' => '0e3cf785',
     'conpherence.pkg.js' => '020aebcf',
     'core.pkg.css' => '0ae696de',
     'core.pkg.js' => 'ab3502fe',
     'dark-console.pkg.js' => '187792c2',
     'differential.pkg.css' => 'ffb69e3d',
-    'differential.pkg.js' => '442567d7',
+    'differential.pkg.js' => '7747755e',
     'diffusion.pkg.css' => '42c75c37',
     'diffusion.pkg.js' => '78c9885d',
     'maniphest.pkg.css' => '35995d6d',
     'maniphest.pkg.js' => 'c9308721',
     'rsrc/audio/basic/alert.mp3' => '17889334',
     'rsrc/audio/basic/bing.mp3' => 'a817a0c3',
     'rsrc/audio/basic/pock.mp3' => '0fa843d0',
     'rsrc/audio/basic/tap.mp3' => '02d16994',
     'rsrc/audio/basic/ting.mp3' => 'a6b6540e',
     'rsrc/css/aphront/aphront-bars.css' => '4a327b4a',
     'rsrc/css/aphront/dark-console.css' => '7f06cda2',
     'rsrc/css/aphront/dialog-view.css' => '6f4ea703',
     'rsrc/css/aphront/list-filter-view.css' => 'feb64255',
     'rsrc/css/aphront/multi-column.css' => 'fbc00ba3',
     'rsrc/css/aphront/notification.css' => '30240bd2',
     'rsrc/css/aphront/panel-view.css' => '46923d46',
     'rsrc/css/aphront/phabricator-nav-view.css' => '423f92cc',
     'rsrc/css/aphront/table-view.css' => '0bb61df1',
     'rsrc/css/aphront/tokenizer.css' => '34e2a838',
     'rsrc/css/aphront/tooltip.css' => 'e3f2412f',
     'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2',
     'rsrc/css/aphront/typeahead.css' => '8779483d',
     'rsrc/css/application/almanac/almanac.css' => '2e050f4f',
     'rsrc/css/application/auth/auth.css' => 'c2f23d74',
     'rsrc/css/application/base/main-menu-view.css' => 'bcec20f0',
     'rsrc/css/application/base/notification-menu.css' => '4df1ee30',
     'rsrc/css/application/base/phui-theme.css' => '35883b37',
     'rsrc/css/application/base/standard-page-view.css' => 'a374f94c',
     'rsrc/css/application/chatlog/chatlog.css' => 'abdc76ee',
     'rsrc/css/application/conduit/conduit-api.css' => 'ce2cfc41',
     'rsrc/css/application/config/config-options.css' => '16c920ae',
     'rsrc/css/application/config/config-template.css' => '20babf50',
     'rsrc/css/application/config/setup-issue.css' => '5eed85b2',
     'rsrc/css/application/config/unhandled-exception.css' => '9ecfc00d',
     'rsrc/css/application/conpherence/color.css' => 'b17746b0',
     'rsrc/css/application/conpherence/durable-column.css' => '2d57072b',
     'rsrc/css/application/conpherence/header-pane.css' => 'c9a3db8e',
     'rsrc/css/application/conpherence/menu.css' => '67f4680d',
     'rsrc/css/application/conpherence/message-pane.css' => 'd244db1e',
     'rsrc/css/application/conpherence/notification.css' => '6a3d4e58',
     'rsrc/css/application/conpherence/participant-pane.css' => '69e0058a',
     'rsrc/css/application/conpherence/transaction.css' => '3a3f5e7e',
     'rsrc/css/application/contentsource/content-source-view.css' => 'cdf0d579',
     'rsrc/css/application/countdown/timer.css' => 'bff8012f',
     'rsrc/css/application/daemon/bulk-job.css' => '73af99f5',
     'rsrc/css/application/dashboard/dashboard.css' => '5a205b9d',
     'rsrc/css/application/diff/diff-tree-view.css' => 'e2d3e222',
     'rsrc/css/application/diff/inline-comment-summary.css' => '81eb368d',
     'rsrc/css/application/differential/add-comment.css' => '7e5900d9',
     'rsrc/css/application/differential/changeset-view.css' => '60c3d405',
     'rsrc/css/application/differential/core.css' => '7300a73e',
     'rsrc/css/application/differential/phui-inline-comment.css' => '9863a85e',
     'rsrc/css/application/differential/revision-comment.css' => '7dbc8d1d',
     'rsrc/css/application/differential/revision-history.css' => '237a2979',
     'rsrc/css/application/differential/revision-list.css' => '93d2df7d',
     'rsrc/css/application/differential/table-of-contents.css' => 'bba788b9',
     'rsrc/css/application/diffusion/diffusion-icons.css' => '23b31a1b',
     'rsrc/css/application/diffusion/diffusion-readme.css' => 'b68a76e4',
     'rsrc/css/application/diffusion/diffusion-repository.css' => 'b89e8c6c',
     'rsrc/css/application/diffusion/diffusion.css' => 'e46232d6',
     'rsrc/css/application/feed/feed.css' => 'd8b6e3f8',
     'rsrc/css/application/files/global-drag-and-drop.css' => '1d2713a4',
     'rsrc/css/application/flag/flag.css' => '2b77be8d',
     'rsrc/css/application/harbormaster/harbormaster.css' => '8dfe16b2',
     'rsrc/css/application/herald/herald-test.css' => '7e7bbdae',
     'rsrc/css/application/herald/herald.css' => '648d39e2',
     'rsrc/css/application/maniphest/report.css' => '3d53188b',
     'rsrc/css/application/maniphest/task-edit.css' => '272daa84',
     'rsrc/css/application/maniphest/task-summary.css' => '61d1667e',
     'rsrc/css/application/objectselector/object-selector.css' => 'ee77366f',
     'rsrc/css/application/owners/owners-path-editor.css' => 'fa7c13ef',
     'rsrc/css/application/paste/paste.css' => 'b37bcd38',
     'rsrc/css/application/people/people-picture-menu-item.css' => 'fe8e07cf',
     'rsrc/css/application/people/people-profile.css' => '2ea2daa1',
     'rsrc/css/application/phame/phame.css' => 'bb442327',
     'rsrc/css/application/pholio/pholio-edit.css' => '4df55b3b',
     'rsrc/css/application/pholio/pholio-inline-comments.css' => '722b48c2',
     'rsrc/css/application/pholio/pholio.css' => '88ef5ef1',
     'rsrc/css/application/phortune/phortune-credit-card-form.css' => '3b9868a8',
     'rsrc/css/application/phortune/phortune-invoice.css' => '4436b241',
     'rsrc/css/application/phortune/phortune.css' => '508a1a5e',
     'rsrc/css/application/phrequent/phrequent.css' => 'bd79cc67',
     'rsrc/css/application/phriction/phriction-document-css.css' => '03380da0',
     'rsrc/css/application/policy/policy-edit.css' => '8794e2ed',
     'rsrc/css/application/policy/policy-transaction-detail.css' => 'c02b8384',
     'rsrc/css/application/policy/policy.css' => 'ceb56a08',
     'rsrc/css/application/ponder/ponder-view.css' => '05a09d0a',
     'rsrc/css/application/project/project-card-view.css' => 'a9f2c2dd',
     'rsrc/css/application/project/project-triggers.css' => 'cd9c8bb9',
     'rsrc/css/application/project/project-view.css' => '567858b3',
     'rsrc/css/application/releeph/releeph-core.css' => 'f81ff2db',
     'rsrc/css/application/releeph/releeph-preview-branch.css' => '22db5c07',
     'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '0ac1ea31',
     'rsrc/css/application/releeph/releeph-request-typeahead.css' => 'bce37359',
     'rsrc/css/application/search/application-search-view.css' => '0f7c06d8',
     'rsrc/css/application/search/search-results.css' => '9ea70ace',
     'rsrc/css/application/slowvote/slowvote.css' => '1694baed',
     'rsrc/css/application/tokens/tokens.css' => 'ce5a50bd',
     'rsrc/css/application/uiexample/example.css' => 'b4795059',
     'rsrc/css/core/core.css' => 'b3ebd90d',
     'rsrc/css/core/remarkup.css' => '5baa3bd9',
     'rsrc/css/core/syntax.css' => '548567f6',
     'rsrc/css/core/z-index.css' => 'ac3bfcd4',
     'rsrc/css/diviner/diviner-shared.css' => '4bd263b0',
     'rsrc/css/font/font-awesome.css' => '3883938a',
     'rsrc/css/font/font-lato.css' => '23631304',
     'rsrc/css/font/phui-font-icon-base.css' => '303c9b87',
     'rsrc/css/fuel/fuel-grid.css' => '66697240',
     'rsrc/css/fuel/fuel-handle-list.css' => '2c4cbeca',
     'rsrc/css/fuel/fuel-map.css' => 'd6e31510',
     'rsrc/css/fuel/fuel-menu.css' => '21f5d199',
     'rsrc/css/layout/phabricator-source-code-view.css' => '03d7ac28',
     'rsrc/css/phui/button/phui-button-bar.css' => 'a4aa75c4',
     'rsrc/css/phui/button/phui-button-simple.css' => '1ff278aa',
     'rsrc/css/phui/button/phui-button.css' => 'ea704902',
     'rsrc/css/phui/calendar/phui-calendar-day.css' => '9597d706',
     'rsrc/css/phui/calendar/phui-calendar-list.css' => 'ccd7e4e2',
     'rsrc/css/phui/calendar/phui-calendar-month.css' => 'cb758c42',
     'rsrc/css/phui/calendar/phui-calendar.css' => 'f11073aa',
     'rsrc/css/phui/object-item/phui-oi-big-ui.css' => 'fa74cc35',
     'rsrc/css/phui/object-item/phui-oi-color.css' => 'b517bfa0',
     'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc',
     'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e',
     'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'af98a277',
     'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46',
     'rsrc/css/phui/phui-action-list.css' => '1b0085b2',
     'rsrc/css/phui/phui-action-panel.css' => '6c386cbf',
     'rsrc/css/phui/phui-badge.css' => '666e25ad',
     'rsrc/css/phui/phui-basic-nav-view.css' => '56ebd66d',
     'rsrc/css/phui/phui-big-info-view.css' => '362ad37b',
     'rsrc/css/phui/phui-box.css' => '5ed3b8cb',
     'rsrc/css/phui/phui-bulk-editor.css' => '374d5e30',
     'rsrc/css/phui/phui-chart.css' => '14df9ae3',
     'rsrc/css/phui/phui-cms.css' => '8c05c41e',
     'rsrc/css/phui/phui-comment-form.css' => '68a2d99a',
     'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0',
     'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf',
     'rsrc/css/phui/phui-curtain-object-ref-view.css' => '5f752bdb',
     'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6',
     'rsrc/css/phui/phui-document-pro.css' => 'b9613a10',
     'rsrc/css/phui/phui-document-summary.css' => 'b068eed1',
     'rsrc/css/phui/phui-document.css' => '52b748a5',
     'rsrc/css/phui/phui-feed-story.css' => 'a0c05029',
     'rsrc/css/phui/phui-fontkit.css' => '1ec937e5',
     'rsrc/css/phui/phui-form-view.css' => '01b796c0',
     'rsrc/css/phui/phui-form.css' => '1f177cb7',
     'rsrc/css/phui/phui-formation-view.css' => 'd2dec8ed',
     'rsrc/css/phui/phui-head-thing.css' => 'd7f293df',
     'rsrc/css/phui/phui-header-view.css' => '36c86a58',
     'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0',
     'rsrc/css/phui/phui-icon-set-selector.css' => '7aa5f3ec',
     'rsrc/css/phui/phui-icon.css' => '4cbc684a',
     'rsrc/css/phui/phui-image-mask.css' => '62c7f4d2',
     'rsrc/css/phui/phui-info-view.css' => 'a10a909b',
     'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4',
     'rsrc/css/phui/phui-left-right.css' => '68513c34',
     'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
     'rsrc/css/phui/phui-list.css' => '2f253c22',
     'rsrc/css/phui/phui-object-box.css' => 'b8d7eea0',
     'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
     'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
     'rsrc/css/phui/phui-policy-section-view.css' => '139fdc64',
     'rsrc/css/phui/phui-property-list-view.css' => '5adf7078',
     'rsrc/css/phui/phui-remarkup-preview.css' => '91767007',
     'rsrc/css/phui/phui-segment-bar-view.css' => '5166b370',
     'rsrc/css/phui/phui-spacing.css' => 'b05cadc3',
     'rsrc/css/phui/phui-status.css' => '293b5dad',
     'rsrc/css/phui/phui-tag-view.css' => 'fb811341',
     'rsrc/css/phui/phui-timeline-view.css' => '2d32d7a9',
     'rsrc/css/phui/phui-two-column-view.css' => 'f96d319f',
     'rsrc/css/phui/workboards/phui-workboard-color.css' => 'e86de308',
     'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98',
     'rsrc/css/phui/workboards/phui-workcard.css' => '913441b6',
     'rsrc/css/phui/workboards/phui-workpanel.css' => '3ae89b20',
     'rsrc/css/sprite-login.css' => '18b368a6',
     'rsrc/css/sprite-tokens.css' => 'f1896dc5',
     'rsrc/css/syntax/syntax-default.css' => '055fc231',
     'rsrc/externals/d3/d3.min.js' => '9d068042',
     'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '23f8c698',
     'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '70983df0',
     'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => 'cd02f93b',
     'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '351fd46a',
     'rsrc/externals/font/lato/lato-bold.eot' => '7367aa5e',
     'rsrc/externals/font/lato/lato-bold.svg' => '681aa4f5',
     'rsrc/externals/font/lato/lato-bold.ttf' => '66d3c296',
     'rsrc/externals/font/lato/lato-bold.woff' => '89d9fba7',
     'rsrc/externals/font/lato/lato-bold.woff2' => '389fcdb1',
     'rsrc/externals/font/lato/lato-bolditalic.eot' => '03eeb4da',
     'rsrc/externals/font/lato/lato-bolditalic.svg' => 'f56fa11c',
     'rsrc/externals/font/lato/lato-bolditalic.ttf' => '9c3aec21',
     'rsrc/externals/font/lato/lato-bolditalic.woff' => 'bfbd0616',
     'rsrc/externals/font/lato/lato-bolditalic.woff2' => 'bc7d1274',
     'rsrc/externals/font/lato/lato-italic.eot' => '7db5b247',
     'rsrc/externals/font/lato/lato-italic.svg' => 'b1ae496f',
     'rsrc/externals/font/lato/lato-italic.ttf' => '43eed813',
     'rsrc/externals/font/lato/lato-italic.woff' => 'c28975e1',
     'rsrc/externals/font/lato/lato-italic.woff2' => 'fffc0d8c',
     'rsrc/externals/font/lato/lato-regular.eot' => '06e0c291',
     'rsrc/externals/font/lato/lato-regular.svg' => '3ad95f53',
     'rsrc/externals/font/lato/lato-regular.ttf' => 'e2e9c398',
     'rsrc/externals/font/lato/lato-regular.woff' => '0b13d332',
     'rsrc/externals/font/lato/lato-regular.woff2' => '8f846797',
     'rsrc/externals/javelin/core/Event.js' => 'c03f2fb4',
     'rsrc/externals/javelin/core/Stratcom.js' => '0889b835',
     'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '048472d2',
     'rsrc/externals/javelin/core/__tests__/install.js' => '14a7e671',
     'rsrc/externals/javelin/core/__tests__/stratcom.js' => 'a28464bb',
     'rsrc/externals/javelin/core/__tests__/util.js' => 'e29a4354',
     'rsrc/externals/javelin/core/init.js' => '98e6504a',
     'rsrc/externals/javelin/core/init_node.js' => '16961339',
     'rsrc/externals/javelin/core/install.js' => '5902260c',
     'rsrc/externals/javelin/core/util.js' => 'edb4d8c9',
     'rsrc/externals/javelin/docs/Base.js' => '5a401d7d',
     'rsrc/externals/javelin/docs/onload.js' => 'ee58fb62',
     'rsrc/externals/javelin/ext/fx/Color.js' => '78f811c9',
     'rsrc/externals/javelin/ext/fx/FX.js' => '34450586',
     'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => '202a2e85',
     'rsrc/externals/javelin/ext/reactor/core/Reactor.js' => '1c850a26',
     'rsrc/externals/javelin/ext/reactor/core/ReactorNode.js' => '72960bc1',
     'rsrc/externals/javelin/ext/reactor/core/ReactorNodeCalmer.js' => '225bbb98',
     'rsrc/externals/javelin/ext/reactor/dom/RDOM.js' => '6cfa0008',
     'rsrc/externals/javelin/ext/view/HTMLView.js' => 'f8c4e135',
     'rsrc/externals/javelin/ext/view/View.js' => '289bf236',
     'rsrc/externals/javelin/ext/view/ViewInterpreter.js' => '876506b6',
     'rsrc/externals/javelin/ext/view/ViewPlaceholder.js' => 'a9942052',
     'rsrc/externals/javelin/ext/view/ViewRenderer.js' => '9aae2b66',
     'rsrc/externals/javelin/ext/view/ViewVisitor.js' => '308f9fe4',
     'rsrc/externals/javelin/ext/view/__tests__/HTMLView.js' => '6e50a13f',
     'rsrc/externals/javelin/ext/view/__tests__/View.js' => 'd284be5d',
     'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => 'a9f35511',
     'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '3a1b81f6',
     'rsrc/externals/javelin/lib/Cookie.js' => '05d290ef',
     'rsrc/externals/javelin/lib/DOM.js' => '94681e22',
     'rsrc/externals/javelin/lib/History.js' => '030b4f7a',
     'rsrc/externals/javelin/lib/JSON.js' => '541f81c3',
     'rsrc/externals/javelin/lib/Leader.js' => '0d2490ce',
     'rsrc/externals/javelin/lib/Mask.js' => '7c4d8998',
     'rsrc/externals/javelin/lib/Quicksand.js' => 'd3799cb4',
     'rsrc/externals/javelin/lib/Request.js' => '84e6891f',
     'rsrc/externals/javelin/lib/Resource.js' => '740956e1',
     'rsrc/externals/javelin/lib/Routable.js' => '6a18c42e',
     'rsrc/externals/javelin/lib/Router.js' => '32755edb',
     'rsrc/externals/javelin/lib/Scrollbar.js' => 'a43ae2ae',
     'rsrc/externals/javelin/lib/Sound.js' => 'd4cc2d2a',
     'rsrc/externals/javelin/lib/URI.js' => '2e255291',
     'rsrc/externals/javelin/lib/Vector.js' => 'e9c80beb',
     'rsrc/externals/javelin/lib/WebSocket.js' => 'fdc13e4e',
     'rsrc/externals/javelin/lib/Workflow.js' => '945ff654',
     'rsrc/externals/javelin/lib/__tests__/Cookie.js' => 'ca686f71',
     'rsrc/externals/javelin/lib/__tests__/DOM.js' => '4566e249',
     'rsrc/externals/javelin/lib/__tests__/JSON.js' => '710377ae',
     'rsrc/externals/javelin/lib/__tests__/URI.js' => '6fff0c2b',
     'rsrc/externals/javelin/lib/__tests__/behavior.js' => '8426ebeb',
     'rsrc/externals/javelin/lib/behavior.js' => '1b6acc2a',
     'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => '89a1ae3a',
     'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => 'a4356cde',
     'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => 'a241536a',
     'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '22ee68a5',
     'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '23387297',
     'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '5a79f6c3',
     'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '8badee71',
     'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '80bff3af',
     'rsrc/favicons/favicon-16x16.png' => '4c51a03a',
     'rsrc/favicons/mask-icon.svg' => 'db699fe1',
     'rsrc/image/BFCFDA.png' => '74b5c88b',
     'rsrc/image/actions/edit.png' => 'fd987dff',
     'rsrc/image/avatar.png' => '0d17c6c4',
     'rsrc/image/checker_dark.png' => '7fc8fa7b',
     'rsrc/image/checker_light.png' => '3157a202',
     'rsrc/image/checker_lighter.png' => 'c45928c1',
     'rsrc/image/chevron-in.png' => '1aa2f88f',
     'rsrc/image/chevron-out.png' => 'c815e272',
     'rsrc/image/controls/checkbox-checked.png' => '1770d7a0',
     'rsrc/image/controls/checkbox-unchecked.png' => 'e1deba0a',
     'rsrc/image/d5d8e1.png' => '6764616e',
     'rsrc/image/darkload.gif' => '5bd41a89',
     'rsrc/image/divot.png' => '0fbe2453',
     'rsrc/image/examples/hero.png' => '5d8c4b21',
     'rsrc/image/grippy_texture.png' => 'a7d222b5',
     'rsrc/image/icon/fatcow/arrow_branch.png' => '98149d9f',
     'rsrc/image/icon/fatcow/arrow_merge.png' => 'e142f4f8',
     'rsrc/image/icon/fatcow/calendar_edit.png' => '5ff44a08',
     'rsrc/image/icon/fatcow/document_black.png' => 'd3515fa5',
     'rsrc/image/icon/fatcow/flag_blue.png' => '54db2e5c',
     'rsrc/image/icon/fatcow/flag_finish.png' => '2953a51b',
     'rsrc/image/icon/fatcow/flag_ghost.png' => '7d9ada92',
     'rsrc/image/icon/fatcow/flag_green.png' => '010f7161',
     'rsrc/image/icon/fatcow/flag_orange.png' => '6c384ca5',
     'rsrc/image/icon/fatcow/flag_pink.png' => '11ac6b12',
     'rsrc/image/icon/fatcow/flag_purple.png' => 'c4f423a4',
     'rsrc/image/icon/fatcow/flag_red.png' => '9e6d8817',
     'rsrc/image/icon/fatcow/flag_yellow.png' => '906733f4',
     'rsrc/image/icon/fatcow/key_question.png' => 'c10c26db',
     'rsrc/image/icon/fatcow/link.png' => '8edbf327',
     'rsrc/image/icon/fatcow/page_white_edit.png' => '17ef5625',
     'rsrc/image/icon/fatcow/page_white_put.png' => '82430c91',
     'rsrc/image/icon/fatcow/source/conduit.png' => '5b55130c',
     'rsrc/image/icon/fatcow/source/email.png' => '8a32b77f',
     'rsrc/image/icon/fatcow/source/fax.png' => '8bc2a49b',
     'rsrc/image/icon/fatcow/source/mobile.png' => '0a918412',
     'rsrc/image/icon/fatcow/source/tablet.png' => 'fc50b050',
     'rsrc/image/icon/fatcow/source/web.png' => '70433af3',
     'rsrc/image/icon/subscribe.png' => '07ef454e',
     'rsrc/image/icon/tango/attachment.png' => 'bac9032d',
     'rsrc/image/icon/tango/edit.png' => 'e6296206',
     'rsrc/image/icon/tango/go-down.png' => '0b903712',
     'rsrc/image/icon/tango/log.png' => '86b6a6f4',
     'rsrc/image/icon/tango/upload.png' => '3fe6b92d',
     'rsrc/image/icon/unsubscribe.png' => 'db04378a',
     'rsrc/image/lightblue-header.png' => 'e6d483c6',
     'rsrc/image/logo/light-eye.png' => '72337472',
     'rsrc/image/main_texture.png' => '894d03c4',
     'rsrc/image/menu_texture.png' => '896c9ade',
     'rsrc/image/people/harding.png' => '95b2db63',
     'rsrc/image/people/jefferson.png' => 'e883a3a2',
     'rsrc/image/people/lincoln.png' => 'be2c07c5',
     'rsrc/image/people/mckinley.png' => '6af510a0',
     'rsrc/image/people/taft.png' => 'b15ab07e',
     'rsrc/image/people/user0.png' => '4bc64b40',
     'rsrc/image/people/user1.png' => '8063f445',
     'rsrc/image/people/user2.png' => 'd28246c0',
     'rsrc/image/people/user3.png' => 'fb1ac12d',
     'rsrc/image/people/user4.png' => 'fe4fac8f',
     'rsrc/image/people/user5.png' => '3d07065c',
     'rsrc/image/people/user6.png' => 'e4bd47c8',
     'rsrc/image/people/user7.png' => '71d8fe8b',
     'rsrc/image/people/user8.png' => '85f86bf7',
     'rsrc/image/people/user9.png' => '523db8aa',
     'rsrc/image/people/washington.png' => '86159e68',
     'rsrc/image/phrequent_active.png' => 'de66dc50',
     'rsrc/image/phrequent_inactive.png' => '79c61baf',
     'rsrc/image/resize.png' => '9cc83373',
     'rsrc/image/sprite-login-X2.png' => '604545f6',
     'rsrc/image/sprite-login.png' => '7a001a9a',
     'rsrc/image/sprite-tokens-X2.png' => '21621dd9',
     'rsrc/image/sprite-tokens.png' => 'bede2580',
     'rsrc/image/texture/card-gradient.png' => 'e6892cb4',
     'rsrc/image/texture/dark-menu-hover.png' => '390a4fa1',
     'rsrc/image/texture/dark-menu.png' => '542f699c',
     'rsrc/image/texture/grip.png' => 'bc80753a',
     'rsrc/image/texture/panel-header-gradient.png' => '65004dbf',
     'rsrc/image/texture/phlnx-bg.png' => '6c9cd31d',
     'rsrc/image/texture/pholio-background.gif' => '84910bfc',
     'rsrc/image/texture/table_header.png' => '7652d1ad',
     'rsrc/image/texture/table_header_hover.png' => '12ea5236',
     'rsrc/image/texture/table_header_tall.png' => '5cc420c4',
     'rsrc/js/application/aphlict/Aphlict.js' => '022516b4',
     'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'e9a2940f',
     'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => '4e61fa88',
     'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'c3703a16',
     'rsrc/js/application/aphlict/behavior-desktop-notifications-control.js' => '070679fe',
     'rsrc/js/application/calendar/behavior-day-view.js' => '727a5a61',
     'rsrc/js/application/calendar/behavior-event-all-day.js' => '0b1bc990',
     'rsrc/js/application/calendar/behavior-month-view.js' => '158c64e0',
     'rsrc/js/application/config/behavior-reorder-fields.js' => '2539f834',
     'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => 'aec8e38c',
     'rsrc/js/application/conpherence/behavior-conpherence-search.js' => '91befbcc',
     'rsrc/js/application/conpherence/behavior-durable-column.js' => 'fa6f30b2',
     'rsrc/js/application/conpherence/behavior-menu.js' => '8c2ed2bf',
     'rsrc/js/application/conpherence/behavior-participant-pane.js' => '43ba89a2',
     'rsrc/js/application/conpherence/behavior-pontificate.js' => '4ae58b5a',
     'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '5a6f6a06',
     'rsrc/js/application/conpherence/behavior-toggle-widget.js' => '8f959ad0',
     'rsrc/js/application/countdown/timer.js' => '6a162524',
     'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => '3829a3cf',
     'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '9c01e364',
     'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be',
     'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9',
     'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
     'rsrc/js/application/diff/DiffChangeset.js' => 'd7d3ba75',
     'rsrc/js/application/diff/DiffChangesetList.js' => 'cc2c5de5',
-    'rsrc/js/application/diff/DiffInline.js' => 'fdebbba6',
+    'rsrc/js/application/diff/DiffInline.js' => '34ccdeda',
     'rsrc/js/application/diff/DiffInlineContentState.js' => '68e6339d',
     'rsrc/js/application/diff/DiffPathView.js' => '8207abf9',
     'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b',
     'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd',
     'rsrc/js/application/differential/behavior-populate.js' => 'b86ef6c2',
     'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => '94243d89',
     'rsrc/js/application/diffusion/ExternalEditorLinkEngine.js' => '48a8641f',
     'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'b7b73831',
     'rsrc/js/application/diffusion/behavior-commit-branches.js' => '4b671572',
     'rsrc/js/application/diffusion/behavior-commit-graph.js' => 'ac10c917',
     'rsrc/js/application/diffusion/behavior-locate-file.js' => '87428eb2',
     'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'c715c123',
     'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '6a85bc5a',
     'rsrc/js/application/drydock/drydock-live-operation-status.js' => '47a0728b',
     'rsrc/js/application/fact/Chart.js' => '52e3ff03',
     'rsrc/js/application/fact/ChartCurtainView.js' => '86954222',
     'rsrc/js/application/fact/ChartFunctionLabel.js' => '81de1dab',
     'rsrc/js/application/files/behavior-document-engine.js' => '243d6c22',
     'rsrc/js/application/files/behavior-icon-composer.js' => '38a6cedb',
     'rsrc/js/application/files/behavior-launch-icon-composer.js' => 'a17b84f1',
     'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => 'b347a301',
     'rsrc/js/application/herald/HeraldRuleEditor.js' => '2633bef7',
     'rsrc/js/application/herald/PathTypeahead.js' => 'ad486db3',
     'rsrc/js/application/herald/herald-rule-editor.js' => '0922e81d',
     'rsrc/js/application/maniphest/behavior-batch-selector.js' => '139ef688',
     'rsrc/js/application/maniphest/behavior-line-chart.js' => 'ad258e28',
     'rsrc/js/application/maniphest/behavior-list-edit.js' => 'c687e867',
     'rsrc/js/application/owners/OwnersPathEditor.js' => '2a8b62d9',
     'rsrc/js/application/owners/owners-path-editor.js' => 'ff688a7a',
     'rsrc/js/application/passphrase/passphrase-credential-control.js' => '48fe33d0',
     'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '3eed1f2b',
     'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => '5aa1544e',
     'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '02cb4398',
     'rsrc/js/application/phortune/behavior-test-payment-form.js' => '4a7fb02b',
     'rsrc/js/application/phortune/phortune-credit-card-form.js' => 'd12d214f',
     'rsrc/js/application/policy/behavior-policy-control.js' => '0eaa33a9',
     'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '9347f172',
     'rsrc/js/application/projects/WorkboardBoard.js' => 'b46d88c5',
     'rsrc/js/application/projects/WorkboardCard.js' => '0392a5d8',
     'rsrc/js/application/projects/WorkboardCardTemplate.js' => '84f82dad',
     'rsrc/js/application/projects/WorkboardColumn.js' => 'c3d24e63',
     'rsrc/js/application/projects/WorkboardController.js' => 'b9d0c2f3',
     'rsrc/js/application/projects/WorkboardDropEffect.js' => '8e0aa661',
     'rsrc/js/application/projects/WorkboardHeader.js' => '111bfd2d',
     'rsrc/js/application/projects/WorkboardHeaderTemplate.js' => 'ebe83a6b',
     'rsrc/js/application/projects/WorkboardOrderTemplate.js' => '03e8891f',
     'rsrc/js/application/projects/behavior-project-boards.js' => '58cb6a88',
     'rsrc/js/application/projects/behavior-project-create.js' => '34c53422',
     'rsrc/js/application/projects/behavior-reorder-columns.js' => '8ac32fd9',
     'rsrc/js/application/releeph/releeph-preview-branch.js' => '75184d68',
     'rsrc/js/application/releeph/releeph-request-state-change.js' => '9f081f05',
     'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'aa3a100c',
     'rsrc/js/application/repository/repository-crossreference.js' => '44d48cd1',
     'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e5bdb730',
     'rsrc/js/application/search/behavior-reorder-queries.js' => 'b86f297f',
     'rsrc/js/application/transactions/behavior-comment-actions.js' => '4dffaeb2',
     'rsrc/js/application/transactions/behavior-reorder-configs.js' => '4842f137',
     'rsrc/js/application/transactions/behavior-reorder-fields.js' => '0ad8d31f',
     'rsrc/js/application/transactions/behavior-show-older-transactions.js' => '8b5c7d65',
     'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => '2bdadf1a',
     'rsrc/js/application/transactions/behavior-transaction-list.js' => '9cec214e',
     'rsrc/js/application/trigger/TriggerRule.js' => '41b7b4f6',
     'rsrc/js/application/trigger/TriggerRuleControl.js' => '5faf27b9',
     'rsrc/js/application/trigger/TriggerRuleEditor.js' => 'b49fd60c',
     'rsrc/js/application/trigger/TriggerRuleType.js' => '4feea7d3',
     'rsrc/js/application/trigger/trigger-rule-editor.js' => '398fdf13',
     'rsrc/js/application/typeahead/behavior-typeahead-browse.js' => '70245195',
     'rsrc/js/application/typeahead/behavior-typeahead-search.js' => '7b139193',
     'rsrc/js/application/uiexample/gesture-example.js' => '242dedd0',
     'rsrc/js/application/uiexample/notification-example.js' => '29819b75',
     'rsrc/js/core/Busy.js' => '5202e831',
     'rsrc/js/core/DragAndDropFileUpload.js' => '4370900d',
     'rsrc/js/core/DraggableList.js' => '0169e425',
     'rsrc/js/core/Favicon.js' => '7930776a',
     'rsrc/js/core/FileUpload.js' => 'ab85e184',
     'rsrc/js/core/Hovercard.js' => '6199f752',
     'rsrc/js/core/HovercardList.js' => 'de4b4919',
     'rsrc/js/core/KeyboardShortcut.js' => '1a844c06',
     'rsrc/js/core/KeyboardShortcutManager.js' => '81debc48',
     'rsrc/js/core/MultirowRowManager.js' => '5b54c823',
     'rsrc/js/core/Notification.js' => 'a9b91e3f',
     'rsrc/js/core/Prefab.js' => '5793d835',
     'rsrc/js/core/ShapedRequest.js' => '995f5102',
     'rsrc/js/core/TextAreaUtils.js' => 'f340a484',
     'rsrc/js/core/Title.js' => '43bc9360',
     'rsrc/js/core/ToolTip.js' => '83754533',
     'rsrc/js/core/behavior-audio-source.js' => '3dc5ad43',
     'rsrc/js/core/behavior-autofocus.js' => '65bb0011',
     'rsrc/js/core/behavior-badge-view.js' => '92cdd7b6',
     'rsrc/js/core/behavior-bulk-editor.js' => 'aa6d2308',
     'rsrc/js/core/behavior-choose-control.js' => '04f8a1e3',
     'rsrc/js/core/behavior-copy.js' => 'cf32921f',
     'rsrc/js/core/behavior-detect-timezone.js' => '78bc5d94',
     'rsrc/js/core/behavior-device.js' => 'ac2b1e01',
     'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '7ad020a5',
     'rsrc/js/core/behavior-fancy-datepicker.js' => '956f3eeb',
     'rsrc/js/core/behavior-form.js' => '55d7b788',
     'rsrc/js/core/behavior-gesture.js' => 'b58d1a2a',
     'rsrc/js/core/behavior-global-drag-and-drop.js' => '1cab0e9a',
     'rsrc/js/core/behavior-high-security-warning.js' => 'dae2d55b',
     'rsrc/js/core/behavior-history-install.js' => '6a1583a8',
     'rsrc/js/core/behavior-hovercard.js' => '183738e6',
     'rsrc/js/core/behavior-keyboard-pager.js' => '1325b731',
     'rsrc/js/core/behavior-keyboard-shortcuts.js' => '42c44e8b',
     'rsrc/js/core/behavior-lightbox-attachments.js' => '14c7ab36',
     'rsrc/js/core/behavior-line-linker.js' => '0d915ff5',
     'rsrc/js/core/behavior-linked-container.js' => '74446546',
     'rsrc/js/core/behavior-more.js' => '506aa3f4',
     'rsrc/js/core/behavior-object-selector.js' => '98ef467f',
     'rsrc/js/core/behavior-oncopy.js' => 'da8f5259',
     'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '54262396',
     'rsrc/js/core/behavior-read-only-warning.js' => 'b9109f8f',
     'rsrc/js/core/behavior-redirect.js' => '407ee861',
     'rsrc/js/core/behavior-refresh-csrf.js' => '46116c01',
     'rsrc/js/core/behavior-remarkup-load-image.js' => '202bfa3f',
     'rsrc/js/core/behavior-remarkup-preview.js' => 'd8a86cfb',
     'rsrc/js/core/behavior-reorder-applications.js' => 'aa371860',
     'rsrc/js/core/behavior-reveal-content.js' => 'b105a3a6',
     'rsrc/js/core/behavior-scrollbar.js' => '92388bae',
     'rsrc/js/core/behavior-search-typeahead.js' => '1cb7d027',
     'rsrc/js/core/behavior-select-content.js' => 'e8240b50',
     'rsrc/js/core/behavior-select-on-click.js' => '66365ee2',
     'rsrc/js/core/behavior-setup-check-https.js' => '01384686',
     'rsrc/js/core/behavior-time-typeahead.js' => '5803b9e7',
     'rsrc/js/core/behavior-toggle-class.js' => '32db8374',
     'rsrc/js/core/behavior-tokenizer.js' => '3b4899b0',
     'rsrc/js/core/behavior-tooltip.js' => '73ecc1f8',
     'rsrc/js/core/behavior-user-menu.js' => '60cd9241',
     'rsrc/js/core/behavior-watch-anchor.js' => 'a77e2cbd',
     'rsrc/js/core/behavior-workflow.js' => '9623adc1',
     'rsrc/js/core/darkconsole/DarkLog.js' => '3b869402',
     'rsrc/js/core/darkconsole/DarkMessage.js' => '26cd4b73',
     'rsrc/js/core/darkconsole/behavior-dark-console.js' => '457f4d16',
     'rsrc/js/core/phtize.js' => '2f1db1ed',
     'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '5cf0501a',
     'rsrc/js/phui/behavior-phui-file-upload.js' => 'e150bd50',
     'rsrc/js/phui/behavior-phui-selectable-list.js' => 'b26a41e4',
     'rsrc/js/phui/behavior-phui-submenu.js' => 'b5e9bff9',
     'rsrc/js/phui/behavior-phui-tab-group.js' => '242aa08b',
     'rsrc/js/phui/behavior-phui-timer-control.js' => 'f84bcbf4',
     'rsrc/js/phuix/PHUIXActionListView.js' => 'c68f183f',
     'rsrc/js/phuix/PHUIXActionView.js' => 'a8f573a9',
     'rsrc/js/phuix/PHUIXAutocomplete.js' => '2fbe234d',
     'rsrc/js/phuix/PHUIXButtonView.js' => '55a24e84',
     'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'b557770a',
     'rsrc/js/phuix/PHUIXExample.js' => 'c2c500a7',
     'rsrc/js/phuix/PHUIXFormControl.js' => '38c1f3fb',
     'rsrc/js/phuix/PHUIXFormationColumnView.js' => '4bcc1f78',
     'rsrc/js/phuix/PHUIXFormationFlankView.js' => '6648270a',
     'rsrc/js/phuix/PHUIXFormationView.js' => 'cef53b3e',
     'rsrc/js/phuix/PHUIXIconView.js' => 'a5257c4e',
   ),
   'symbols' => array(
     'almanac-css' => '2e050f4f',
     'aphront-bars' => '4a327b4a',
     'aphront-dark-console-css' => '7f06cda2',
     'aphront-dialog-view-css' => '6f4ea703',
     'aphront-list-filter-view-css' => 'feb64255',
     'aphront-multi-column-view-css' => 'fbc00ba3',
     'aphront-panel-view-css' => '46923d46',
     'aphront-table-view-css' => '0bb61df1',
     'aphront-tokenizer-control-css' => '34e2a838',
     'aphront-tooltip-css' => 'e3f2412f',
     'aphront-typeahead-control-css' => '8779483d',
     'application-search-view-css' => '0f7c06d8',
     'auth-css' => 'c2f23d74',
     'bulk-job-css' => '73af99f5',
     'conduit-api-css' => 'ce2cfc41',
     'config-options-css' => '16c920ae',
     'conpherence-color-css' => 'b17746b0',
     'conpherence-durable-column-view' => '2d57072b',
     'conpherence-header-pane-css' => 'c9a3db8e',
     'conpherence-menu-css' => '67f4680d',
     'conpherence-message-pane-css' => 'd244db1e',
     'conpherence-notification-css' => '6a3d4e58',
     'conpherence-participant-pane-css' => '69e0058a',
     'conpherence-thread-manager' => 'aec8e38c',
     'conpherence-transaction-css' => '3a3f5e7e',
     'd3' => '9d068042',
     'diff-tree-view-css' => 'e2d3e222',
     'differential-changeset-view-css' => '60c3d405',
     'differential-core-view-css' => '7300a73e',
     'differential-revision-add-comment-css' => '7e5900d9',
     'differential-revision-comment-css' => '7dbc8d1d',
     'differential-revision-history-css' => '237a2979',
     'differential-revision-list-css' => '93d2df7d',
     'differential-table-of-contents-css' => 'bba788b9',
     'diffusion-css' => 'e46232d6',
     'diffusion-icons-css' => '23b31a1b',
     'diffusion-readme-css' => 'b68a76e4',
     'diffusion-repository-css' => 'b89e8c6c',
     'diviner-shared-css' => '4bd263b0',
     'font-fontawesome' => '3883938a',
     'font-lato' => '23631304',
     'fuel-grid-css' => '66697240',
     'fuel-handle-list-css' => '2c4cbeca',
     'fuel-map-css' => 'd6e31510',
     'fuel-menu-css' => '21f5d199',
     'global-drag-and-drop-css' => '1d2713a4',
     'harbormaster-css' => '8dfe16b2',
     'herald-css' => '648d39e2',
     'herald-rule-editor' => '2633bef7',
     'herald-test-css' => '7e7bbdae',
     'inline-comment-summary-css' => '81eb368d',
     'javelin-aphlict' => '022516b4',
     'javelin-behavior' => '1b6acc2a',
     'javelin-behavior-aphlict-dropdown' => 'e9a2940f',
     'javelin-behavior-aphlict-listen' => '4e61fa88',
     'javelin-behavior-aphlict-status' => 'c3703a16',
     'javelin-behavior-aphront-basic-tokenizer' => '3b4899b0',
     'javelin-behavior-aphront-drag-and-drop-textarea' => '7ad020a5',
     'javelin-behavior-aphront-form-disable-on-submit' => '55d7b788',
     'javelin-behavior-aphront-more' => '506aa3f4',
     'javelin-behavior-audio-source' => '3dc5ad43',
     'javelin-behavior-audit-preview' => 'b7b73831',
     'javelin-behavior-badge-view' => '92cdd7b6',
     'javelin-behavior-bulk-editor' => 'aa6d2308',
     'javelin-behavior-bulk-job-reload' => '3829a3cf',
     'javelin-behavior-calendar-month-view' => '158c64e0',
     'javelin-behavior-choose-control' => '04f8a1e3',
     'javelin-behavior-comment-actions' => '4dffaeb2',
     'javelin-behavior-config-reorder-fields' => '2539f834',
     'javelin-behavior-conpherence-menu' => '8c2ed2bf',
     'javelin-behavior-conpherence-participant-pane' => '43ba89a2',
     'javelin-behavior-conpherence-pontificate' => '4ae58b5a',
     'javelin-behavior-conpherence-search' => '91befbcc',
     'javelin-behavior-countdown-timer' => '6a162524',
     'javelin-behavior-dark-console' => '457f4d16',
     'javelin-behavior-dashboard-async-panel' => '9c01e364',
     'javelin-behavior-dashboard-move-panels' => 'a2ab19be',
     'javelin-behavior-dashboard-query-panel-select' => '1e413dc9',
     'javelin-behavior-dashboard-tab-panel' => '0116d3e8',
     'javelin-behavior-day-view' => '727a5a61',
     'javelin-behavior-desktop-notifications-control' => '070679fe',
     'javelin-behavior-detect-timezone' => '78bc5d94',
     'javelin-behavior-device' => 'ac2b1e01',
     'javelin-behavior-differential-diff-radios' => '925fe8cd',
     'javelin-behavior-differential-populate' => 'b86ef6c2',
     'javelin-behavior-diffusion-commit-branches' => '4b671572',
     'javelin-behavior-diffusion-commit-graph' => 'ac10c917',
     'javelin-behavior-diffusion-locate-file' => '87428eb2',
     'javelin-behavior-diffusion-pull-lastmodified' => 'c715c123',
     'javelin-behavior-document-engine' => '243d6c22',
     'javelin-behavior-doorkeeper-tag' => '6a85bc5a',
     'javelin-behavior-drydock-live-operation-status' => '47a0728b',
     'javelin-behavior-durable-column' => 'fa6f30b2',
     'javelin-behavior-editengine-reorder-configs' => '4842f137',
     'javelin-behavior-editengine-reorder-fields' => '0ad8d31f',
     'javelin-behavior-event-all-day' => '0b1bc990',
     'javelin-behavior-fancy-datepicker' => '956f3eeb',
     'javelin-behavior-global-drag-and-drop' => '1cab0e9a',
     'javelin-behavior-harbormaster-log' => 'b347a301',
     'javelin-behavior-herald-rule-editor' => '0922e81d',
     'javelin-behavior-high-security-warning' => 'dae2d55b',
     'javelin-behavior-history-install' => '6a1583a8',
     'javelin-behavior-icon-composer' => '38a6cedb',
     'javelin-behavior-launch-icon-composer' => 'a17b84f1',
     'javelin-behavior-lightbox-attachments' => '14c7ab36',
     'javelin-behavior-line-chart' => 'ad258e28',
     'javelin-behavior-linked-container' => '74446546',
     'javelin-behavior-maniphest-batch-selector' => '139ef688',
     'javelin-behavior-maniphest-list-editor' => 'c687e867',
     'javelin-behavior-owners-path-editor' => 'ff688a7a',
     'javelin-behavior-passphrase-credential-control' => '48fe33d0',
     'javelin-behavior-phabricator-autofocus' => '65bb0011',
     'javelin-behavior-phabricator-clipboard-copy' => 'cf32921f',
     'javelin-behavior-phabricator-gesture' => 'b58d1a2a',
     'javelin-behavior-phabricator-gesture-example' => '242dedd0',
     'javelin-behavior-phabricator-keyboard-pager' => '1325b731',
     'javelin-behavior-phabricator-keyboard-shortcuts' => '42c44e8b',
     'javelin-behavior-phabricator-line-linker' => '0d915ff5',
     'javelin-behavior-phabricator-notification-example' => '29819b75',
     'javelin-behavior-phabricator-object-selector' => '98ef467f',
     'javelin-behavior-phabricator-oncopy' => 'da8f5259',
     'javelin-behavior-phabricator-remarkup-assist' => '54262396',
     'javelin-behavior-phabricator-reveal-content' => 'b105a3a6',
     'javelin-behavior-phabricator-search-typeahead' => '1cb7d027',
     'javelin-behavior-phabricator-show-older-transactions' => '8b5c7d65',
     'javelin-behavior-phabricator-tooltips' => '73ecc1f8',
     'javelin-behavior-phabricator-transaction-comment-form' => '2bdadf1a',
     'javelin-behavior-phabricator-transaction-list' => '9cec214e',
     'javelin-behavior-phabricator-watch-anchor' => 'a77e2cbd',
     'javelin-behavior-pholio-mock-edit' => '3eed1f2b',
     'javelin-behavior-pholio-mock-view' => '5aa1544e',
     'javelin-behavior-phui-dropdown-menu' => '5cf0501a',
     'javelin-behavior-phui-file-upload' => 'e150bd50',
     'javelin-behavior-phui-hovercards' => '183738e6',
     'javelin-behavior-phui-selectable-list' => 'b26a41e4',
     'javelin-behavior-phui-submenu' => 'b5e9bff9',
     'javelin-behavior-phui-tab-group' => '242aa08b',
     'javelin-behavior-phui-timer-control' => 'f84bcbf4',
     'javelin-behavior-phuix-example' => 'c2c500a7',
     'javelin-behavior-policy-control' => '0eaa33a9',
     'javelin-behavior-policy-rule-editor' => '9347f172',
     'javelin-behavior-project-boards' => '58cb6a88',
     'javelin-behavior-project-create' => '34c53422',
     'javelin-behavior-quicksand-blacklist' => '5a6f6a06',
     'javelin-behavior-read-only-warning' => 'b9109f8f',
     'javelin-behavior-redirect' => '407ee861',
     'javelin-behavior-refresh-csrf' => '46116c01',
     'javelin-behavior-releeph-preview-branch' => '75184d68',
     'javelin-behavior-releeph-request-state-change' => '9f081f05',
     'javelin-behavior-releeph-request-typeahead' => 'aa3a100c',
     'javelin-behavior-remarkup-load-image' => '202bfa3f',
     'javelin-behavior-remarkup-preview' => 'd8a86cfb',
     'javelin-behavior-reorder-applications' => 'aa371860',
     'javelin-behavior-reorder-columns' => '8ac32fd9',
     'javelin-behavior-reorder-profile-menu-items' => 'e5bdb730',
     'javelin-behavior-repository-crossreference' => '44d48cd1',
     'javelin-behavior-scrollbar' => '92388bae',
     'javelin-behavior-search-reorder-queries' => 'b86f297f',
     'javelin-behavior-select-content' => 'e8240b50',
     'javelin-behavior-select-on-click' => '66365ee2',
     'javelin-behavior-setup-check-https' => '01384686',
     'javelin-behavior-stripe-payment-form' => '02cb4398',
     'javelin-behavior-test-payment-form' => '4a7fb02b',
     'javelin-behavior-time-typeahead' => '5803b9e7',
     'javelin-behavior-toggle-class' => '32db8374',
     'javelin-behavior-toggle-widget' => '8f959ad0',
     'javelin-behavior-trigger-rule-editor' => '398fdf13',
     'javelin-behavior-typeahead-browse' => '70245195',
     'javelin-behavior-typeahead-search' => '7b139193',
     'javelin-behavior-user-menu' => '60cd9241',
     'javelin-behavior-view-placeholder' => 'a9942052',
     'javelin-behavior-workflow' => '9623adc1',
     'javelin-chart' => '52e3ff03',
     'javelin-chart-curtain-view' => '86954222',
     'javelin-chart-function-label' => '81de1dab',
     'javelin-color' => '78f811c9',
     'javelin-cookie' => '05d290ef',
     'javelin-diffusion-locate-file-source' => '94243d89',
     'javelin-dom' => '94681e22',
     'javelin-dynval' => '202a2e85',
     'javelin-event' => 'c03f2fb4',
     'javelin-external-editor-link-engine' => '48a8641f',
     'javelin-fx' => '34450586',
     'javelin-history' => '030b4f7a',
     'javelin-install' => '5902260c',
     'javelin-json' => '541f81c3',
     'javelin-leader' => '0d2490ce',
     'javelin-magical-init' => '98e6504a',
     'javelin-mask' => '7c4d8998',
     'javelin-quicksand' => 'd3799cb4',
     'javelin-reactor' => '1c850a26',
     'javelin-reactor-dom' => '6cfa0008',
     'javelin-reactor-node-calmer' => '225bbb98',
     'javelin-reactornode' => '72960bc1',
     'javelin-request' => '84e6891f',
     'javelin-resource' => '740956e1',
     'javelin-routable' => '6a18c42e',
     'javelin-router' => '32755edb',
     'javelin-scrollbar' => 'a43ae2ae',
     'javelin-sound' => 'd4cc2d2a',
     'javelin-stratcom' => '0889b835',
     'javelin-tokenizer' => '89a1ae3a',
     'javelin-typeahead' => 'a4356cde',
     'javelin-typeahead-composite-source' => '22ee68a5',
     'javelin-typeahead-normalizer' => 'a241536a',
     'javelin-typeahead-ondemand-source' => '23387297',
     'javelin-typeahead-preloaded-source' => '5a79f6c3',
     'javelin-typeahead-source' => '8badee71',
     'javelin-typeahead-static-source' => '80bff3af',
     'javelin-uri' => '2e255291',
     'javelin-util' => 'edb4d8c9',
     'javelin-vector' => 'e9c80beb',
     'javelin-view' => '289bf236',
     'javelin-view-html' => 'f8c4e135',
     'javelin-view-interpreter' => '876506b6',
     'javelin-view-renderer' => '9aae2b66',
     'javelin-view-visitor' => '308f9fe4',
     'javelin-websocket' => 'fdc13e4e',
     'javelin-workboard-board' => 'b46d88c5',
     'javelin-workboard-card' => '0392a5d8',
     'javelin-workboard-card-template' => '84f82dad',
     'javelin-workboard-column' => 'c3d24e63',
     'javelin-workboard-controller' => 'b9d0c2f3',
     'javelin-workboard-drop-effect' => '8e0aa661',
     'javelin-workboard-header' => '111bfd2d',
     'javelin-workboard-header-template' => 'ebe83a6b',
     'javelin-workboard-order-template' => '03e8891f',
     'javelin-workflow' => '945ff654',
     'maniphest-report-css' => '3d53188b',
     'maniphest-task-edit-css' => '272daa84',
     'maniphest-task-summary-css' => '61d1667e',
     'multirow-row-manager' => '5b54c823',
     'owners-path-editor' => '2a8b62d9',
     'owners-path-editor-css' => 'fa7c13ef',
     'paste-css' => 'b37bcd38',
     'path-typeahead' => 'ad486db3',
     'people-picture-menu-item-css' => 'fe8e07cf',
     'people-profile-css' => '2ea2daa1',
     'phabricator-action-list-view-css' => '1b0085b2',
     'phabricator-busy' => '5202e831',
     'phabricator-chatlog-css' => 'abdc76ee',
     'phabricator-content-source-view-css' => 'cdf0d579',
     'phabricator-core-css' => 'b3ebd90d',
     'phabricator-countdown-css' => 'bff8012f',
     'phabricator-darklog' => '3b869402',
     'phabricator-darkmessage' => '26cd4b73',
     'phabricator-dashboard-css' => '5a205b9d',
     'phabricator-diff-changeset' => 'd7d3ba75',
     'phabricator-diff-changeset-list' => 'cc2c5de5',
-    'phabricator-diff-inline' => 'fdebbba6',
+    'phabricator-diff-inline' => '34ccdeda',
     'phabricator-diff-inline-content-state' => '68e6339d',
     'phabricator-diff-path-view' => '8207abf9',
     'phabricator-diff-tree-view' => '5d83623b',
     'phabricator-drag-and-drop-file-upload' => '4370900d',
     'phabricator-draggable-list' => '0169e425',
     'phabricator-fatal-config-template-css' => '20babf50',
     'phabricator-favicon' => '7930776a',
     'phabricator-feed-css' => 'd8b6e3f8',
     'phabricator-file-upload' => 'ab85e184',
     'phabricator-flag-css' => '2b77be8d',
     'phabricator-keyboard-shortcut' => '1a844c06',
     'phabricator-keyboard-shortcut-manager' => '81debc48',
     'phabricator-main-menu-view' => 'bcec20f0',
     'phabricator-nav-view-css' => '423f92cc',
     'phabricator-notification' => 'a9b91e3f',
     'phabricator-notification-css' => '30240bd2',
     'phabricator-notification-menu-css' => '4df1ee30',
     'phabricator-object-selector-css' => 'ee77366f',
     'phabricator-phtize' => '2f1db1ed',
     'phabricator-prefab' => '5793d835',
     'phabricator-remarkup-css' => '5baa3bd9',
     'phabricator-search-results-css' => '9ea70ace',
     'phabricator-shaped-request' => '995f5102',
     'phabricator-slowvote-css' => '1694baed',
     'phabricator-source-code-view-css' => '03d7ac28',
     'phabricator-standard-page-view' => 'a374f94c',
     'phabricator-textareautils' => 'f340a484',
     'phabricator-title' => '43bc9360',
     'phabricator-tooltip' => '83754533',
     'phabricator-ui-example-css' => 'b4795059',
     'phabricator-zindex-css' => 'ac3bfcd4',
     'phame-css' => 'bb442327',
     'pholio-css' => '88ef5ef1',
     'pholio-edit-css' => '4df55b3b',
     'pholio-inline-comments-css' => '722b48c2',
     'phortune-credit-card-form' => 'd12d214f',
     'phortune-credit-card-form-css' => '3b9868a8',
     'phortune-css' => '508a1a5e',
     'phortune-invoice-css' => '4436b241',
     'phrequent-css' => 'bd79cc67',
     'phriction-document-css' => '03380da0',
     'phui-action-panel-css' => '6c386cbf',
     'phui-badge-view-css' => '666e25ad',
     'phui-basic-nav-view-css' => '56ebd66d',
     'phui-big-info-view-css' => '362ad37b',
     'phui-box-css' => '5ed3b8cb',
     'phui-bulk-editor-css' => '374d5e30',
     'phui-button-bar-css' => 'a4aa75c4',
     'phui-button-css' => 'ea704902',
     'phui-button-simple-css' => '1ff278aa',
     'phui-calendar-css' => 'f11073aa',
     'phui-calendar-day-css' => '9597d706',
     'phui-calendar-list-css' => 'ccd7e4e2',
     'phui-calendar-month-css' => 'cb758c42',
     'phui-chart-css' => '14df9ae3',
     'phui-cms-css' => '8c05c41e',
     'phui-comment-form-css' => '68a2d99a',
     'phui-comment-panel-css' => 'ec4e31c0',
     'phui-crumbs-view-css' => '614f43cf',
     'phui-curtain-object-ref-view-css' => '5f752bdb',
     'phui-curtain-view-css' => '68c5efb6',
     'phui-document-summary-view-css' => 'b068eed1',
     'phui-document-view-css' => '52b748a5',
     'phui-document-view-pro-css' => 'b9613a10',
     'phui-feed-story-css' => 'a0c05029',
     'phui-font-icon-base-css' => '303c9b87',
     'phui-fontkit-css' => '1ec937e5',
     'phui-form-css' => '1f177cb7',
     'phui-form-view-css' => '01b796c0',
     'phui-formation-view-css' => 'd2dec8ed',
     'phui-head-thing-view-css' => 'd7f293df',
     'phui-header-view-css' => '36c86a58',
     'phui-hovercard' => '6199f752',
     'phui-hovercard-list' => 'de4b4919',
     'phui-hovercard-view-css' => '6ca90fa0',
     'phui-icon-set-selector-css' => '7aa5f3ec',
     'phui-icon-view-css' => '4cbc684a',
     'phui-image-mask-css' => '62c7f4d2',
     'phui-info-view-css' => 'a10a909b',
     'phui-inline-comment-view-css' => '9863a85e',
     'phui-invisible-character-view-css' => 'c694c4a4',
     'phui-left-right-css' => '68513c34',
     'phui-lightbox-css' => '4ebf22da',
     'phui-list-view-css' => '2f253c22',
     'phui-object-box-css' => 'b8d7eea0',
     'phui-oi-big-ui-css' => 'fa74cc35',
     'phui-oi-color-css' => 'b517bfa0',
     'phui-oi-drag-ui-css' => 'da15d3dc',
     'phui-oi-flush-ui-css' => '490e2e2e',
     'phui-oi-list-view-css' => 'af98a277',
     'phui-oi-simple-ui-css' => '6a30fa46',
     'phui-pager-css' => 'd022c7ad',
     'phui-pinboard-view-css' => '1f08f5d8',
     'phui-policy-section-view-css' => '139fdc64',
     'phui-property-list-view-css' => '5adf7078',
     'phui-remarkup-preview-css' => '91767007',
     'phui-segment-bar-view-css' => '5166b370',
     'phui-spacing-css' => 'b05cadc3',
     'phui-status-list-view-css' => '293b5dad',
     'phui-tag-view-css' => 'fb811341',
     'phui-theme-css' => '35883b37',
     'phui-timeline-view-css' => '2d32d7a9',
     'phui-two-column-view-css' => 'f96d319f',
     'phui-workboard-color-css' => 'e86de308',
     'phui-workboard-view-css' => '74fc9d98',
     'phui-workcard-view-css' => '913441b6',
     'phui-workpanel-view-css' => '3ae89b20',
     'phuix-action-list-view' => 'c68f183f',
     'phuix-action-view' => 'a8f573a9',
     'phuix-autocomplete' => '2fbe234d',
     'phuix-button-view' => '55a24e84',
     'phuix-dropdown-menu' => 'b557770a',
     'phuix-form-control-view' => '38c1f3fb',
     'phuix-formation-column-view' => '4bcc1f78',
     'phuix-formation-flank-view' => '6648270a',
     'phuix-formation-view' => 'cef53b3e',
     'phuix-icon-view' => 'a5257c4e',
     'policy-css' => 'ceb56a08',
     'policy-edit-css' => '8794e2ed',
     'policy-transaction-detail-css' => 'c02b8384',
     'ponder-view-css' => '05a09d0a',
     'project-card-view-css' => 'a9f2c2dd',
     'project-triggers-css' => 'cd9c8bb9',
     'project-view-css' => '567858b3',
     'releeph-core' => 'f81ff2db',
     'releeph-preview-branch' => '22db5c07',
     'releeph-request-differential-create-dialog' => '0ac1ea31',
     'releeph-request-typeahead-css' => 'bce37359',
     'setup-issue-css' => '5eed85b2',
     'sprite-login-css' => '18b368a6',
     'sprite-tokens-css' => 'f1896dc5',
     'syntax-default-css' => '055fc231',
     'syntax-highlighting-css' => '548567f6',
     'tokens-css' => 'ce5a50bd',
     'trigger-rule' => '41b7b4f6',
     'trigger-rule-control' => '5faf27b9',
     'trigger-rule-editor' => 'b49fd60c',
     'trigger-rule-type' => '4feea7d3',
     'typeahead-browse-css' => 'b7ed02d2',
     'unhandled-exception-css' => '9ecfc00d',
   ),
   'requires' => array(
     '0116d3e8' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
     ),
     '01384686' => array(
       'javelin-behavior',
       'javelin-uri',
       'phabricator-notification',
     ),
     '0169e425' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-util',
       'javelin-vector',
       'javelin-magical-init',
     ),
     '022516b4' => array(
       'javelin-install',
       'javelin-util',
       'javelin-websocket',
       'javelin-leader',
       'javelin-json',
     ),
     '02cb4398' => array(
       'javelin-behavior',
       'javelin-dom',
       'phortune-credit-card-form',
     ),
     '030b4f7a' => array(
       'javelin-stratcom',
       'javelin-install',
       'javelin-uri',
       'javelin-util',
     ),
     '0392a5d8' => array(
       'javelin-install',
     ),
     '03e8891f' => array(
       'javelin-install',
     ),
     '04f8a1e3' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-workflow',
     ),
     '05d290ef' => array(
       'javelin-install',
       'javelin-util',
     ),
     '070679fe' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-uri',
       'phabricator-notification',
     ),
     '0889b835' => array(
       'javelin-install',
       'javelin-event',
       'javelin-util',
       'javelin-magical-init',
     ),
     '0922e81d' => array(
       'herald-rule-editor',
       'javelin-behavior',
     ),
     '0ad8d31f' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'phabricator-draggable-list',
     ),
     '0d2490ce' => array(
       'javelin-install',
     ),
     '0d915ff5' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-history',
       'javelin-external-editor-link-engine',
     ),
     '0eaa33a9' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'phuix-dropdown-menu',
       'phuix-action-list-view',
       'phuix-action-view',
       'javelin-workflow',
       'phuix-icon-view',
     ),
     '111bfd2d' => array(
       'javelin-install',
     ),
     '1325b731' => array(
       'javelin-behavior',
       'javelin-uri',
       'phabricator-keyboard-shortcut',
     ),
     '139ef688' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-util',
     ),
     '14c7ab36' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-mask',
       'javelin-util',
       'phuix-icon-view',
       'phabricator-busy',
     ),
     '183738e6' => array(
       'javelin-behavior',
       'javelin-behavior-device',
       'javelin-stratcom',
       'javelin-vector',
       'phui-hovercard',
       'phui-hovercard-list',
     ),
     '1a844c06' => array(
       'javelin-install',
       'javelin-util',
       'phabricator-keyboard-shortcut-manager',
     ),
     '1b6acc2a' => array(
       'javelin-magical-init',
       'javelin-util',
     ),
     '1c850a26' => array(
       'javelin-install',
       'javelin-util',
     ),
     '1cab0e9a' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-uri',
       'javelin-mask',
       'phabricator-drag-and-drop-file-upload',
     ),
     '1cb7d027' => array(
       'javelin-behavior',
       'javelin-typeahead-ondemand-source',
       'javelin-typeahead',
       'javelin-dom',
       'javelin-uri',
       'javelin-util',
       'javelin-stratcom',
       'phabricator-prefab',
       'phuix-icon-view',
     ),
     '1e413dc9' => array(
       'javelin-behavior',
       'javelin-dom',
     ),
     '1ff278aa' => array(
       'phui-button-css',
     ),
     '202a2e85' => array(
       'javelin-install',
       'javelin-reactornode',
       'javelin-util',
       'javelin-reactor',
     ),
     '202bfa3f' => array(
       'javelin-behavior',
       'javelin-request',
     ),
     '225bbb98' => array(
       'javelin-install',
       'javelin-reactor',
       'javelin-util',
     ),
     '22ee68a5' => array(
       'javelin-install',
       'javelin-typeahead-source',
       'javelin-util',
     ),
     23387297 => array(
       'javelin-install',
       'javelin-util',
       'javelin-request',
       'javelin-typeahead-source',
     ),
     23631304 => array(
       'phui-fontkit-css',
     ),
     '242aa08b' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     '242dedd0' => array(
       'javelin-stratcom',
       'javelin-behavior',
       'javelin-vector',
       'javelin-dom',
     ),
     '243d6c22' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
     ),
     '2539f834' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-json',
       'phabricator-draggable-list',
     ),
     '2633bef7' => array(
       'multirow-row-manager',
       'javelin-install',
       'javelin-util',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-json',
       'phabricator-prefab',
     ),
     '289bf236' => array(
       'javelin-install',
       'javelin-util',
     ),
     '29819b75' => array(
       'phabricator-notification',
       'javelin-stratcom',
       'javelin-behavior',
     ),
     '2a8b62d9' => array(
       'multirow-row-manager',
       'javelin-install',
       'path-typeahead',
       'javelin-dom',
       'javelin-util',
       'phabricator-prefab',
       'phuix-form-control-view',
     ),
     '2bdadf1a' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-request',
       'phabricator-shaped-request',
     ),
     '2e255291' => array(
       'javelin-install',
       'javelin-util',
       'javelin-stratcom',
     ),
     '2f1db1ed' => array(
       'javelin-util',
     ),
     '2fbe234d' => array(
       'javelin-install',
       'javelin-dom',
       'phuix-icon-view',
       'phabricator-prefab',
     ),
     '308f9fe4' => array(
       'javelin-install',
       'javelin-util',
     ),
     '32755edb' => array(
       'javelin-install',
       'javelin-util',
     ),
     '32db8374' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     34450586 => array(
       'javelin-color',
       'javelin-install',
       'javelin-util',
     ),
     '34c53422' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-workflow',
     ),
+    '34ccdeda' => array(
+      'javelin-dom',
+      'phabricator-diff-inline-content-state',
+    ),
     '34e2a838' => array(
       'aphront-typeahead-control-css',
       'phui-tag-view-css',
     ),
     '3829a3cf' => array(
       'javelin-behavior',
       'javelin-uri',
     ),
     '38a6cedb' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
     ),
     '38c1f3fb' => array(
       'javelin-install',
       'javelin-dom',
     ),
     '398fdf13' => array(
       'javelin-behavior',
       'trigger-rule-editor',
       'trigger-rule',
       'trigger-rule-type',
     ),
     '3ae89b20' => array(
       'phui-workcard-view-css',
     ),
     '3b4899b0' => array(
       'javelin-behavior',
       'phabricator-prefab',
     ),
     '3dc5ad43' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-vector',
       'javelin-dom',
     ),
     '3eed1f2b' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-workflow',
       'javelin-quicksand',
       'phabricator-phtize',
       'phabricator-drag-and-drop-file-upload',
       'phabricator-draggable-list',
     ),
     '407ee861' => array(
       'javelin-behavior',
       'javelin-uri',
     ),
     '42c44e8b' => array(
       'javelin-behavior',
       'javelin-workflow',
       'javelin-json',
       'javelin-dom',
       'phabricator-keyboard-shortcut',
     ),
     '4370900d' => array(
       'javelin-install',
       'javelin-util',
       'javelin-request',
       'javelin-dom',
       'javelin-uri',
       'phabricator-file-upload',
     ),
     '43ba89a2' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-util',
       'phabricator-notification',
       'conpherence-thread-manager',
     ),
     '43bc9360' => array(
       'javelin-install',
     ),
     '44d48cd1' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-uri',
     ),
     '457f4d16' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-util',
       'javelin-dom',
       'javelin-request',
       'phabricator-keyboard-shortcut',
       'phabricator-darklog',
       'phabricator-darkmessage',
     ),
     '46116c01' => array(
       'javelin-request',
       'javelin-behavior',
       'javelin-dom',
       'javelin-router',
       'javelin-util',
       'phabricator-busy',
     ),
     '47a0728b' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-request',
     ),
     '4842f137' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'phabricator-draggable-list',
     ),
     '48a8641f' => array(
       'javelin-install',
     ),
     '48fe33d0' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-util',
       'javelin-uri',
     ),
     '490e2e2e' => array(
       'phui-oi-list-view-css',
     ),
     '4a7fb02b' => array(
       'javelin-behavior',
       'javelin-dom',
       'phortune-credit-card-form',
     ),
     '4ae58b5a' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-workflow',
       'javelin-stratcom',
       'conpherence-thread-manager',
     ),
     '4b671572' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-request',
     ),
     '4bcc1f78' => array(
       'javelin-install',
       'javelin-dom',
     ),
     '4dffaeb2' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'phuix-form-control-view',
       'phuix-icon-view',
       'javelin-behavior-phabricator-gesture',
     ),
     '4e61fa88' => array(
       'javelin-behavior',
       'javelin-aphlict',
       'javelin-stratcom',
       'javelin-request',
       'javelin-uri',
       'javelin-dom',
       'javelin-json',
       'javelin-router',
       'javelin-util',
       'javelin-leader',
       'javelin-sound',
       'phabricator-notification',
     ),
     '4feea7d3' => array(
       'trigger-rule-control',
     ),
     '506aa3f4' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     '5202e831' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-fx',
     ),
     '52e3ff03' => array(
       'phui-chart-css',
       'd3',
       'javelin-chart-curtain-view',
       'javelin-chart-function-label',
     ),
     '541f81c3' => array(
       'javelin-install',
     ),
     54262396 => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'phabricator-phtize',
       'phabricator-textareautils',
       'javelin-workflow',
       'javelin-vector',
       'phuix-autocomplete',
       'javelin-mask',
     ),
     '548567f6' => array(
       'syntax-default-css',
     ),
     '55a24e84' => array(
       'javelin-install',
       'javelin-dom',
     ),
     '55d7b788' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     '5793d835' => array(
       'javelin-install',
       'javelin-util',
       'javelin-dom',
       'javelin-typeahead',
       'javelin-tokenizer',
       'javelin-typeahead-preloaded-source',
       'javelin-typeahead-ondemand-source',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-util',
     ),
     '5803b9e7' => array(
       'javelin-behavior',
       'javelin-util',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-vector',
       'javelin-typeahead-static-source',
     ),
     '58cb6a88' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-vector',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-workboard-controller',
       'javelin-workboard-drop-effect',
     ),
     '5902260c' => array(
       'javelin-util',
       'javelin-magical-init',
     ),
     '5a6f6a06' => array(
       'javelin-behavior',
       'javelin-quicksand',
     ),
     '5a79f6c3' => array(
       'javelin-install',
       'javelin-util',
       'javelin-request',
       'javelin-typeahead-source',
     ),
     '5aa1544e' => array(
       'javelin-behavior',
       'javelin-util',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-vector',
       'javelin-magical-init',
       'javelin-request',
       'javelin-history',
       'javelin-workflow',
       'javelin-mask',
       'javelin-behavior-device',
       'phabricator-keyboard-shortcut',
     ),
     '5b54c823' => array(
       'javelin-install',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-util',
     ),
     '5cf0501a' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'phuix-dropdown-menu',
     ),
     '5d83623b' => array(
       'javelin-dom',
     ),
     '5faf27b9' => array(
       'phuix-form-control-view',
     ),
     '60c3d405' => array(
       'phui-inline-comment-view-css',
     ),
     '60cd9241' => array(
       'javelin-behavior',
     ),
     '6199f752' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-vector',
       'javelin-request',
       'javelin-uri',
     ),
     '65bb0011' => array(
       'javelin-behavior',
       'javelin-dom',
     ),
     '66365ee2' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     '6648270a' => array(
       'javelin-install',
       'javelin-dom',
     ),
     '68e6339d' => array(
       'javelin-dom',
     ),
     '6a1583a8' => array(
       'javelin-behavior',
       'javelin-history',
     ),
     '6a162524' => array(
       'javelin-behavior',
       'javelin-dom',
     ),
     '6a18c42e' => array(
       'javelin-install',
     ),
     '6a30fa46' => array(
       'phui-oi-list-view-css',
     ),
     '6a85bc5a' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-json',
       'javelin-workflow',
       'javelin-magical-init',
     ),
     '6cfa0008' => array(
       'javelin-dom',
       'javelin-dynval',
       'javelin-reactor',
       'javelin-reactornode',
       'javelin-install',
       'javelin-util',
     ),
     70245195 => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
     ),
     '727a5a61' => array(
       'phuix-icon-view',
     ),
     '72960bc1' => array(
       'javelin-install',
       'javelin-reactor',
       'javelin-util',
       'javelin-reactor-node-calmer',
     ),
     '73ecc1f8' => array(
       'javelin-behavior',
       'javelin-behavior-device',
       'javelin-stratcom',
       'phabricator-tooltip',
     ),
     '740956e1' => array(
       'javelin-util',
       'javelin-uri',
       'javelin-install',
     ),
     74446546 => array(
       'javelin-behavior',
       'javelin-dom',
     ),
     '75184d68' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-uri',
       'javelin-request',
     ),
     '78bc5d94' => array(
       'javelin-behavior',
       'javelin-uri',
       'phabricator-notification',
     ),
     '78f811c9' => array(
       'javelin-install',
     ),
     '7930776a' => array(
       'javelin-install',
       'javelin-dom',
     ),
     '7ad020a5' => array(
       'javelin-behavior',
       'javelin-dom',
       'phabricator-drag-and-drop-file-upload',
       'phabricator-textareautils',
     ),
     '7b139193' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
     ),
     '7c4d8998' => array(
       'javelin-install',
       'javelin-dom',
     ),
     '80bff3af' => array(
       'javelin-install',
       'javelin-typeahead-source',
     ),
     '81debc48' => array(
       'javelin-install',
       'javelin-util',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-vector',
     ),
     '8207abf9' => array(
       'javelin-dom',
     ),
     83754533 => array(
       'javelin-install',
       'javelin-util',
       'javelin-dom',
       'javelin-vector',
     ),
     '84e6891f' => array(
       'javelin-install',
       'javelin-stratcom',
       'javelin-util',
       'javelin-behavior',
       'javelin-json',
       'javelin-dom',
       'javelin-resource',
       'javelin-routable',
     ),
     '84f82dad' => array(
       'javelin-install',
     ),
     '87428eb2' => array(
       'javelin-behavior',
       'javelin-diffusion-locate-file-source',
       'javelin-dom',
       'javelin-typeahead',
       'javelin-uri',
     ),
     '876506b6' => array(
       'javelin-view',
       'javelin-install',
       'javelin-dom',
     ),
     '89a1ae3a' => array(
       'javelin-dom',
       'javelin-util',
       'javelin-stratcom',
       'javelin-install',
     ),
     '8ac32fd9' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'phabricator-draggable-list',
     ),
     '8b5c7d65' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'phabricator-busy',
     ),
     '8badee71' => array(
       'javelin-install',
       'javelin-util',
       'javelin-dom',
       'javelin-typeahead-normalizer',
     ),
     '8c2ed2bf' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-behavior-device',
       'javelin-history',
       'javelin-vector',
       'javelin-scrollbar',
       'phabricator-title',
       'phabricator-shaped-request',
       'conpherence-thread-manager',
     ),
     '8e0aa661' => array(
       'javelin-install',
       'javelin-dom',
     ),
     '8f959ad0' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-workflow',
       'javelin-stratcom',
     ),
     '91befbcc' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-workflow',
       'javelin-stratcom',
     ),
     '92388bae' => array(
       'javelin-behavior',
       'javelin-scrollbar',
     ),
     '925fe8cd' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     '92cdd7b6' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     '9347f172' => array(
       'javelin-behavior',
       'multirow-row-manager',
       'javelin-dom',
       'javelin-util',
       'phabricator-prefab',
       'javelin-json',
     ),
     '94243d89' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-typeahead-preloaded-source',
       'javelin-util',
     ),
     '945ff654' => array(
       'javelin-stratcom',
       'javelin-request',
       'javelin-dom',
       'javelin-vector',
       'javelin-install',
       'javelin-util',
       'javelin-mask',
       'javelin-uri',
       'javelin-routable',
     ),
     '94681e22' => array(
       'javelin-magical-init',
       'javelin-install',
       'javelin-util',
       'javelin-vector',
       'javelin-stratcom',
     ),
     '956f3eeb' => array(
       'javelin-behavior',
       'javelin-util',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-vector',
     ),
     '9623adc1' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'javelin-router',
     ),
     '98ef467f' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-request',
       'javelin-util',
     ),
     '995f5102' => array(
       'javelin-install',
       'javelin-util',
       'javelin-request',
       'javelin-router',
     ),
     '9aae2b66' => array(
       'javelin-install',
       'javelin-util',
     ),
     '9c01e364' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-workflow',
     ),
     '9cec214e' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'javelin-uri',
       'phabricator-textareautils',
     ),
     '9f081f05' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-util',
       'phabricator-keyboard-shortcut',
     ),
     'a17b84f1' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-workflow',
     ),
     'a241536a' => array(
       'javelin-install',
     ),
     'a2ab19be' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-stratcom',
       'javelin-workflow',
       'phabricator-draggable-list',
     ),
     'a4356cde' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-vector',
       'javelin-util',
     ),
     'a43ae2ae' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-vector',
     ),
     'a4aa75c4' => array(
       'phui-button-css',
       'phui-button-simple-css',
     ),
     'a5257c4e' => array(
       'javelin-install',
       'javelin-dom',
     ),
     'a77e2cbd' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-vector',
     ),
     'a8f573a9' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-util',
     ),
     'a9942052' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-view-renderer',
       'javelin-install',
     ),
     'a9b91e3f' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-util',
       'phabricator-notification-css',
     ),
     'aa371860' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'phabricator-draggable-list',
     ),
     'aa3a100c' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-typeahead',
       'javelin-typeahead-ondemand-source',
       'javelin-dom',
     ),
     'aa6d2308' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'multirow-row-manager',
       'javelin-json',
       'phuix-form-control-view',
     ),
     'ab85e184' => array(
       'javelin-install',
       'javelin-dom',
       'phabricator-notification',
     ),
     'ac10c917' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
     ),
     'ac2b1e01' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'javelin-vector',
       'javelin-install',
     ),
     'ad258e28' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-chart',
     ),
     'ad486db3' => array(
       'javelin-install',
       'javelin-typeahead',
       'javelin-dom',
       'javelin-request',
       'javelin-typeahead-ondemand-source',
       'javelin-util',
     ),
     'aec8e38c' => array(
       'javelin-dom',
       'javelin-util',
       'javelin-stratcom',
       'javelin-install',
       'javelin-aphlict',
       'javelin-workflow',
       'javelin-router',
       'javelin-behavior-device',
       'javelin-vector',
     ),
     'b105a3a6' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     'b26a41e4' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     'b347a301' => array(
       'javelin-behavior',
     ),
     'b46d88c5' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-util',
       'javelin-stratcom',
       'javelin-workflow',
       'phabricator-draggable-list',
       'javelin-workboard-column',
       'javelin-workboard-header-template',
       'javelin-workboard-card-template',
       'javelin-workboard-order-template',
     ),
     'b49fd60c' => array(
       'multirow-row-manager',
       'trigger-rule',
     ),
     'b517bfa0' => array(
       'phui-oi-list-view-css',
     ),
     'b557770a' => array(
       'javelin-install',
       'javelin-util',
       'javelin-dom',
       'javelin-vector',
       'javelin-stratcom',
     ),
     'b58d1a2a' => array(
       'javelin-behavior',
       'javelin-behavior-device',
       'javelin-stratcom',
       'javelin-vector',
       'javelin-dom',
       'javelin-magical-init',
     ),
     'b5e9bff9' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     'b7b73831' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'phabricator-shaped-request',
     ),
     'b86ef6c2' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'phabricator-tooltip',
       'phabricator-diff-changeset-list',
       'phabricator-diff-changeset',
       'phuix-formation-view',
     ),
     'b86f297f' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'phabricator-draggable-list',
     ),
     'b9109f8f' => array(
       'javelin-behavior',
       'javelin-uri',
       'phabricator-notification',
     ),
     'b9d0c2f3' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-util',
       'javelin-vector',
       'javelin-stratcom',
       'javelin-workflow',
       'phabricator-drag-and-drop-file-upload',
       'javelin-workboard-board',
     ),
     'bcec20f0' => array(
       'phui-theme-css',
     ),
     'c03f2fb4' => array(
       'javelin-install',
     ),
     'c2c500a7' => array(
       'javelin-install',
       'javelin-dom',
       'phuix-button-view',
     ),
     'c3703a16' => array(
       'javelin-behavior',
       'javelin-aphlict',
       'phabricator-phtize',
       'javelin-dom',
     ),
     'c3d24e63' => array(
       'javelin-install',
       'javelin-workboard-card',
       'javelin-workboard-header',
     ),
     'c687e867' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-fx',
       'javelin-util',
     ),
     'c68f183f' => array(
       'javelin-install',
       'javelin-dom',
     ),
     'c715c123' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'javelin-workflow',
       'javelin-json',
     ),
     'cc2c5de5' => array(
       'javelin-install',
       'phuix-button-view',
       'phabricator-diff-tree-view',
     ),
     'cef53b3e' => array(
       'javelin-install',
       'javelin-dom',
       'phuix-formation-column-view',
       'phuix-formation-flank-view',
     ),
     'cf32921f' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
     ),
     'd12d214f' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-json',
       'javelin-workflow',
       'javelin-util',
     ),
     'd3799cb4' => array(
       'javelin-install',
     ),
     'd4cc2d2a' => array(
       'javelin-install',
     ),
     'd7d3ba75' => array(
       'javelin-dom',
       'javelin-util',
       'javelin-stratcom',
       'javelin-install',
       'javelin-workflow',
       'javelin-router',
       'javelin-behavior-device',
       'javelin-vector',
       'phabricator-diff-inline',
       'phabricator-diff-path-view',
       'phuix-button-view',
       'javelin-external-editor-link-engine',
     ),
     'd8a86cfb' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-util',
       'phabricator-shaped-request',
     ),
     'da15d3dc' => array(
       'phui-oi-list-view-css',
     ),
     'da8f5259' => array(
       'javelin-behavior',
       'javelin-dom',
     ),
     'dae2d55b' => array(
       'javelin-behavior',
       'javelin-uri',
       'phabricator-notification',
     ),
     'de4b4919' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-vector',
       'javelin-request',
       'javelin-uri',
       'phui-hovercard',
     ),
     'e150bd50' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
       'phuix-dropdown-menu',
     ),
     'e5bdb730' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-workflow',
       'javelin-dom',
       'phabricator-draggable-list',
     ),
     'e8240b50' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     'e9a2940f' => array(
       'javelin-behavior',
       'javelin-request',
       'javelin-stratcom',
       'javelin-vector',
       'javelin-dom',
       'javelin-uri',
       'javelin-behavior-device',
       'phabricator-title',
       'phabricator-favicon',
     ),
     'e9c80beb' => array(
       'javelin-install',
       'javelin-event',
     ),
     'ebe83a6b' => array(
       'javelin-install',
     ),
     'ec4e31c0' => array(
       'phui-timeline-view-css',
     ),
     'ee77366f' => array(
       'aphront-dialog-view-css',
     ),
     'f340a484' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-vector',
     ),
     'f84bcbf4' => array(
       'javelin-behavior',
       'javelin-stratcom',
       'javelin-dom',
     ),
     'f8c4e135' => array(
       'javelin-install',
       'javelin-dom',
       'javelin-view-visitor',
       'javelin-util',
     ),
     'fa6f30b2' => array(
       'javelin-behavior',
       'javelin-dom',
       'javelin-stratcom',
       'javelin-behavior-device',
       'javelin-scrollbar',
       'javelin-quicksand',
       'phabricator-keyboard-shortcut',
       'conpherence-thread-manager',
     ),
     'fa74cc35' => array(
       'phui-oi-list-view-css',
     ),
     'fdc13e4e' => array(
       'javelin-install',
     ),
-    'fdebbba6' => array(
-      'javelin-dom',
-      'phabricator-diff-inline-content-state',
-    ),
     'ff688a7a' => array(
       'owners-path-editor',
       'javelin-behavior',
     ),
   ),
   'packages' => array(
     'conpherence.pkg.css' => array(
       'conpherence-menu-css',
       'conpherence-color-css',
       'conpherence-message-pane-css',
       'conpherence-notification-css',
       'conpherence-transaction-css',
       'conpherence-participant-pane-css',
       'conpherence-header-pane-css',
     ),
     'conpherence.pkg.js' => array(
       'javelin-behavior-conpherence-menu',
       'javelin-behavior-conpherence-participant-pane',
       'javelin-behavior-conpherence-pontificate',
       'javelin-behavior-toggle-widget',
     ),
     'core.pkg.css' => array(
       'phabricator-core-css',
       'phabricator-zindex-css',
       'phui-button-css',
       'phui-button-simple-css',
       'phui-theme-css',
       'phabricator-standard-page-view',
       'aphront-dialog-view-css',
       'phui-form-view-css',
       'aphront-panel-view-css',
       'aphront-table-view-css',
       'aphront-tokenizer-control-css',
       'aphront-typeahead-control-css',
       'aphront-list-filter-view-css',
       'application-search-view-css',
       'phabricator-remarkup-css',
       'syntax-highlighting-css',
       'syntax-default-css',
       'phui-pager-css',
       'aphront-tooltip-css',
       'phabricator-flag-css',
       'phui-info-view-css',
       'phabricator-main-menu-view',
       'phabricator-notification-css',
       'phabricator-notification-menu-css',
       'phui-lightbox-css',
       'phui-comment-panel-css',
       'phui-header-view-css',
       'phabricator-nav-view-css',
       'phui-basic-nav-view-css',
       'phui-crumbs-view-css',
       'phui-oi-list-view-css',
       'phui-oi-color-css',
       'phui-oi-big-ui-css',
       'phui-oi-drag-ui-css',
       'phui-oi-simple-ui-css',
       'phui-oi-flush-ui-css',
       'global-drag-and-drop-css',
       'phui-spacing-css',
       'phui-form-css',
       'phui-icon-view-css',
       'phabricator-action-list-view-css',
       'phui-property-list-view-css',
       'phui-tag-view-css',
       'phui-list-view-css',
       'font-fontawesome',
       'font-lato',
       'phui-font-icon-base-css',
       'phui-fontkit-css',
       'phui-box-css',
       'phui-object-box-css',
       'phui-timeline-view-css',
       'phui-two-column-view-css',
       'phui-curtain-view-css',
       'sprite-login-css',
       'sprite-tokens-css',
       'tokens-css',
       'auth-css',
       'phui-status-list-view-css',
       'phui-feed-story-css',
       'phabricator-feed-css',
       'phabricator-dashboard-css',
       'aphront-multi-column-view-css',
       'phui-curtain-object-ref-view-css',
       'phui-comment-form-css',
       'phui-head-thing-view-css',
       'conpherence-durable-column-view',
       'phui-button-bar-css',
     ),
     'core.pkg.js' => array(
       'javelin-util',
       'javelin-install',
       'javelin-event',
       'javelin-stratcom',
       'javelin-behavior',
       'javelin-resource',
       'javelin-request',
       'javelin-vector',
       'javelin-dom',
       'javelin-json',
       'javelin-uri',
       'javelin-workflow',
       'javelin-mask',
       'javelin-typeahead',
       'javelin-typeahead-normalizer',
       'javelin-typeahead-source',
       'javelin-typeahead-preloaded-source',
       'javelin-typeahead-ondemand-source',
       'javelin-tokenizer',
       'javelin-history',
       'javelin-router',
       'javelin-routable',
       'javelin-behavior-aphront-basic-tokenizer',
       'javelin-behavior-workflow',
       'javelin-behavior-aphront-form-disable-on-submit',
       'phabricator-keyboard-shortcut-manager',
       'phabricator-keyboard-shortcut',
       'javelin-behavior-phabricator-keyboard-shortcuts',
       'javelin-behavior-refresh-csrf',
       'javelin-behavior-phabricator-watch-anchor',
       'javelin-behavior-phabricator-autofocus',
       'phuix-dropdown-menu',
       'phuix-action-list-view',
       'phuix-action-view',
       'phuix-icon-view',
       'phabricator-phtize',
       'javelin-behavior-phabricator-oncopy',
       'phabricator-tooltip',
       'javelin-behavior-phabricator-tooltips',
       'phabricator-prefab',
       'javelin-behavior-device',
       'javelin-behavior-toggle-class',
       'javelin-behavior-lightbox-attachments',
       'phabricator-busy',
       'javelin-sound',
       'javelin-aphlict',
       'phabricator-notification',
       'javelin-behavior-aphlict-listen',
       'javelin-behavior-phabricator-search-typeahead',
       'javelin-behavior-aphlict-dropdown',
       'javelin-behavior-history-install',
       'javelin-behavior-phabricator-gesture',
       'javelin-behavior-phabricator-remarkup-assist',
       'phabricator-textareautils',
       'phabricator-file-upload',
       'javelin-behavior-global-drag-and-drop',
       'javelin-behavior-phabricator-reveal-content',
       'phui-hovercard',
       'phui-hovercard-list',
       'javelin-behavior-phui-hovercards',
       'javelin-color',
       'javelin-fx',
       'phabricator-draggable-list',
       'javelin-behavior-phabricator-transaction-list',
       'javelin-behavior-phabricator-show-older-transactions',
       'javelin-behavior-phui-dropdown-menu',
       'javelin-behavior-doorkeeper-tag',
       'phabricator-title',
       'javelin-leader',
       'javelin-websocket',
       'javelin-behavior-dashboard-async-panel',
       'javelin-behavior-dashboard-tab-panel',
       'javelin-quicksand',
       'javelin-behavior-quicksand-blacklist',
       'javelin-behavior-high-security-warning',
       'javelin-behavior-read-only-warning',
       'javelin-scrollbar',
       'javelin-behavior-scrollbar',
       'javelin-behavior-durable-column',
       'conpherence-thread-manager',
       'javelin-behavior-detect-timezone',
       'javelin-behavior-setup-check-https',
       'javelin-behavior-aphlict-status',
       'javelin-behavior-user-menu',
       'phabricator-favicon',
       'javelin-behavior-phui-tab-group',
       'javelin-behavior-phui-submenu',
       'phuix-button-view',
       'javelin-behavior-comment-actions',
       'phuix-form-control-view',
       'phuix-autocomplete',
     ),
     'dark-console.pkg.js' => array(
       'javelin-behavior-dark-console',
       'phabricator-darklog',
       'phabricator-darkmessage',
     ),
     'differential.pkg.css' => array(
       'differential-core-view-css',
       'differential-changeset-view-css',
       'differential-revision-history-css',
       'differential-revision-list-css',
       'differential-table-of-contents-css',
       'differential-revision-comment-css',
       'differential-revision-add-comment-css',
       'phabricator-object-selector-css',
       'phabricator-content-source-view-css',
       'inline-comment-summary-css',
       'phui-inline-comment-view-css',
       'diff-tree-view-css',
       'phui-formation-view-css',
     ),
     'differential.pkg.js' => array(
       'phabricator-drag-and-drop-file-upload',
       'phabricator-shaped-request',
       'javelin-behavior-differential-populate',
       'javelin-behavior-differential-diff-radios',
       'javelin-behavior-aphront-drag-and-drop-textarea',
       'javelin-behavior-phabricator-object-selector',
       'javelin-behavior-repository-crossreference',
       'javelin-behavior-aphront-more',
       'phabricator-diff-inline-content-state',
       'phabricator-diff-inline',
       'phabricator-diff-changeset',
       'phabricator-diff-changeset-list',
       'phabricator-diff-tree-view',
       'phabricator-diff-path-view',
       'phuix-formation-view',
       'phuix-formation-column-view',
       'phuix-formation-flank-view',
       'javelin-external-editor-link-engine',
     ),
     'diffusion.pkg.css' => array(
       'diffusion-icons-css',
     ),
     'diffusion.pkg.js' => array(
       'javelin-behavior-diffusion-pull-lastmodified',
       'javelin-behavior-diffusion-commit-graph',
       'javelin-behavior-audit-preview',
     ),
     'maniphest.pkg.css' => array(
       'maniphest-task-summary-css',
     ),
     'maniphest.pkg.js' => array(
       'javelin-behavior-maniphest-batch-selector',
       'javelin-behavior-maniphest-list-editor',
     ),
   ),
 );
diff --git a/src/infrastructure/diff/PhabricatorInlineCommentController.php b/src/infrastructure/diff/PhabricatorInlineCommentController.php
index 693f66066f..2076c1964e 100644
--- a/src/infrastructure/diff/PhabricatorInlineCommentController.php
+++ b/src/infrastructure/diff/PhabricatorInlineCommentController.php
@@ -1,596 +1,588 @@
 <?php
 
 abstract class PhabricatorInlineCommentController
   extends PhabricatorController {
 
   private $containerObject;
 
   abstract protected function createComment();
   abstract protected function newInlineCommentQuery();
   abstract protected function loadCommentForDone($id);
   abstract protected function loadObjectOwnerPHID(
     PhabricatorInlineComment $inline);
   abstract protected function newContainerObject();
 
   final protected function getContainerObject() {
     if ($this->containerObject === null) {
       $object = $this->newContainerObject();
       if (!$object) {
         throw new Exception(
           pht(
             'Failed to load container object for inline comment.'));
       }
       $this->containerObject = $object;
     }
 
     return $this->containerObject;
   }
 
   protected function hideComments(array $ids) {
     throw new PhutilMethodNotImplementedException();
   }
 
   protected function showComments(array $ids) {
     throw new PhutilMethodNotImplementedException();
   }
 
   private $changesetID;
   private $isNewFile;
   private $isOnRight;
   private $lineNumber;
   private $lineLength;
   private $operation;
   private $commentID;
   private $renderer;
   private $replyToCommentPHID;
 
   public function getCommentID() {
     return $this->commentID;
   }
 
   public function getOperation() {
     return $this->operation;
   }
 
   public function getLineLength() {
     return $this->lineLength;
   }
 
   public function getLineNumber() {
     return $this->lineNumber;
   }
 
   public function getIsOnRight() {
     return $this->isOnRight;
   }
 
   public function getChangesetID() {
     return $this->changesetID;
   }
 
   public function getIsNewFile() {
     return $this->isNewFile;
   }
 
   public function setRenderer($renderer) {
     $this->renderer = $renderer;
     return $this;
   }
 
   public function getRenderer() {
     return $this->renderer;
   }
 
   public function setReplyToCommentPHID($phid) {
     $this->replyToCommentPHID = $phid;
     return $this;
   }
 
   public function getReplyToCommentPHID() {
     return $this->replyToCommentPHID;
   }
 
   public function processRequest() {
     $request = $this->getRequest();
     $viewer = $this->getViewer();
 
     if (!$request->validateCSRF()) {
       return new Aphront404Response();
     }
 
     $this->readRequestParameters();
 
     $op = $this->getOperation();
     switch ($op) {
       case 'hide':
       case 'show':
         $ids = $request->getStrList('ids');
         if ($ids) {
           if ($op == 'hide') {
             $this->hideComments($ids);
           } else {
             $this->showComments($ids);
           }
         }
 
         return id(new AphrontAjaxResponse())->setContent(array());
       case 'done':
         $inline = $this->loadCommentForDone($this->getCommentID());
 
         $is_draft_state = false;
         $is_checked = false;
         switch ($inline->getFixedState()) {
           case PhabricatorInlineComment::STATE_DRAFT:
             $next_state = PhabricatorInlineComment::STATE_UNDONE;
             break;
           case PhabricatorInlineComment::STATE_UNDRAFT:
             $next_state = PhabricatorInlineComment::STATE_DONE;
             $is_checked = true;
             break;
           case PhabricatorInlineComment::STATE_DONE:
             $next_state = PhabricatorInlineComment::STATE_UNDRAFT;
             $is_draft_state = true;
             break;
           default:
           case PhabricatorInlineComment::STATE_UNDONE:
             $next_state = PhabricatorInlineComment::STATE_DRAFT;
             $is_draft_state = true;
             $is_checked = true;
             break;
         }
 
         $inline->setFixedState($next_state)->save();
 
         return id(new AphrontAjaxResponse())
           ->setContent(
             array(
               'isChecked' => $is_checked,
               'draftState' => $is_draft_state,
             ));
       case 'delete':
       case 'undelete':
       case 'refdelete':
         // NOTE: For normal deletes, we just process the delete immediately
         // and show an "Undo" action. For deletes by reference from the
         // preview ("refdelete"), we prompt first (because the "Undo" may
         // not draw, or may not be easy to locate).
 
         if ($op == 'refdelete') {
           if (!$request->isFormPost()) {
             return $this->newDialog()
               ->setTitle(pht('Really delete comment?'))
               ->addHiddenInput('id', $this->getCommentID())
               ->addHiddenInput('op', $op)
               ->appendParagraph(pht('Delete this inline comment?'))
               ->addCancelButton('#')
               ->addSubmitButton(pht('Delete'));
           }
         }
 
         $is_delete = ($op == 'delete' || $op == 'refdelete');
 
         $inline = $this->loadCommentByIDForEdit($this->getCommentID());
 
         if ($is_delete) {
           $inline->setIsDeleted(1);
         } else {
           $inline->setIsDeleted(0);
         }
 
         $this->saveComment($inline);
 
         return $this->buildEmptyResponse();
       case 'edit':
       case 'save':
         $inline = $this->loadCommentByIDForEdit($this->getCommentID());
         if ($op === 'save') {
           $this->updateCommentContentState($inline);
 
-          $inline->setIsEditing(false);
+          $inline
+            ->setIsEditing(false)
+            ->setIsDeleted(0);
 
-          if (!$inline->isVoidComment($viewer)) {
-            $inline->setIsDeleted(0);
+          $this->saveComment($inline);
 
-            $this->saveComment($inline);
-
-            return $this->buildRenderedCommentResponse(
-              $inline,
-              $this->getIsOnRight());
-          } else {
-            $inline->setIsDeleted(1);
-
-            $this->saveComment($inline);
-
-            return $this->buildEmptyResponse();
-          }
+          return $this->buildRenderedCommentResponse(
+            $inline,
+            $this->getIsOnRight());
         } else {
           // NOTE: At time of writing, the "editing" state of inlines is
           // preserved by simulating a click on "Edit" when the inline loads.
 
           // In this case, we don't want to "saveComment()", because it
           // recalculates object drafts and purges versioned drafts.
 
           // The recalculation is merely unnecessary (state doesn't change)
           // but purging drafts means that loading a page and then closing it
           // discards your drafts.
 
           // To avoid the purge, only invoke "saveComment()" if we actually
           // have changes to apply.
 
           $is_dirty = false;
           if (!$inline->getIsEditing()) {
             $inline
               ->setIsDeleted(0)
               ->setIsEditing(true);
 
             $is_dirty = true;
           }
 
           if ($this->hasContentState()) {
             $this->updateCommentContentState($inline);
             $is_dirty = true;
           } else {
             PhabricatorInlineComment::loadAndAttachVersionedDrafts(
               $viewer,
               array($inline));
           }
 
           if ($is_dirty) {
             $this->saveComment($inline);
           }
         }
 
         $edit_dialog = $this->buildEditDialog($inline)
           ->setTitle(pht('Edit Inline Comment'));
 
         $view = $this->buildScaffoldForView($edit_dialog);
 
         return $this->newInlineResponse($inline, $view, true);
       case 'cancel':
         $inline = $this->loadCommentByIDForEdit($this->getCommentID());
 
         $inline->setIsEditing(false);
 
         // If the user uses "Undo" to get into an edited state ("AB"), then
         // clicks cancel to return to the previous state ("A"), we also want
         // to set the stored state back to "A".
         $this->updateCommentContentState($inline);
 
         if ($inline->isVoidComment($viewer)) {
           $inline->setIsDeleted(1);
         }
 
         $this->saveComment($inline);
 
         return $this->buildEmptyResponse();
       case 'draft':
         $inline = $this->loadCommentByIDForEdit($this->getCommentID());
 
         $versioned_draft = PhabricatorVersionedDraft::loadOrCreateDraft(
           $inline->getPHID(),
           $viewer->getPHID(),
           $inline->getID());
 
         $map = $this->newRequestContentState($inline)->newStorageMap();
         $versioned_draft->setProperty('inline.state', $map);
         $versioned_draft->save();
 
         // We have to synchronize the draft engine after saving a versioned
         // draft, because taking an inline comment from "no text, no draft"
         // to "no text, text in a draft" marks the container object as having
         // a draft.
         $draft_engine = $this->newDraftEngine();
         if ($draft_engine) {
           $draft_engine->synchronize();
         }
 
         return $this->buildEmptyResponse();
       case 'new':
       case 'reply':
       default:
         // NOTE: We read the values from the client (the display values), not
         // the values from the database (the original values) when replying.
         // In particular, when replying to a ghost comment which was moved
         // across diffs and then moved backward to the most recent visible
         // line, we want to reply on the display line (which exists), not on
         // the comment's original line (which may not exist in this changeset).
         $is_new = $this->getIsNewFile();
         $number = $this->getLineNumber();
         $length = $this->getLineLength();
 
         $inline = $this->createComment()
           ->setChangesetID($this->getChangesetID())
           ->setAuthorPHID($viewer->getPHID())
           ->setIsNewFile($is_new)
           ->setLineNumber($number)
           ->setLineLength($length)
           ->setReplyToCommentPHID($this->getReplyToCommentPHID())
           ->setIsEditing(true)
           ->setStartOffset($request->getInt('startOffset'))
           ->setEndOffset($request->getInt('endOffset'))
           ->setContent('');
 
         $document_engine_key = $request->getStr('documentEngineKey');
         if ($document_engine_key !== null) {
           $inline->setDocumentEngineKey($document_engine_key);
         }
 
         // If you own this object, mark your own inlines as "Done" by default.
         $owner_phid = $this->loadObjectOwnerPHID($inline);
         if ($owner_phid) {
           if ($viewer->getPHID() == $owner_phid) {
             $fixed_state = PhabricatorInlineComment::STATE_DRAFT;
             $inline->setFixedState($fixed_state);
           }
         }
 
         if ($this->hasContentState()) {
           $this->updateCommentContentState($inline);
         }
 
         $this->saveComment($inline);
 
         // Reload the inline to attach context.
         $inline = $this->loadCommentByIDForEdit($inline->getID());
 
         $edit_dialog = $this->buildEditDialog($inline);
 
         if ($this->getOperation() == 'reply') {
           $edit_dialog->setTitle(pht('Reply to Inline Comment'));
         } else {
           $edit_dialog->setTitle(pht('New Inline Comment'));
         }
 
         $view = $this->buildScaffoldForView($edit_dialog);
 
         return $this->newInlineResponse($inline, $view, true);
     }
   }
 
   private function readRequestParameters() {
     $request = $this->getRequest();
 
     // NOTE: This isn't necessarily a DifferentialChangeset ID, just an
     // application identifier for the changeset. In Diffusion, it's a Path ID.
     $this->changesetID = $request->getInt('changesetID');
 
     $this->isNewFile = (int)$request->getBool('is_new');
     $this->isOnRight = $request->getBool('on_right');
     $this->lineNumber = $request->getInt('number');
     $this->lineLength = $request->getInt('length');
     $this->commentID = $request->getInt('id');
     $this->operation = $request->getStr('op');
     $this->renderer = $request->getStr('renderer');
     $this->replyToCommentPHID = $request->getStr('replyToCommentPHID');
 
     if ($this->getReplyToCommentPHID()) {
       $reply_phid = $this->getReplyToCommentPHID();
       $reply_comment = $this->loadCommentByPHID($reply_phid);
       if (!$reply_comment) {
         throw new Exception(
           pht('Failed to load comment "%s".', $reply_phid));
       }
 
       // When replying, force the new comment into the same location as the
       // old comment. If we don't do this, replying to a ghost comment from
       // diff A while viewing diff B can end up placing the two comments in
       // different places while viewing diff C, because the porting algorithm
       // makes a different decision. Forcing the comments to bind to the same
       // place makes sure they stick together no matter which diff is being
       // viewed. See T10562 for discussion.
 
       $this->changesetID = $reply_comment->getChangesetID();
       $this->isNewFile = $reply_comment->getIsNewFile();
       $this->lineNumber = $reply_comment->getLineNumber();
       $this->lineLength = $reply_comment->getLineLength();
     }
   }
 
   private function buildEditDialog(PhabricatorInlineComment $inline) {
     $request = $this->getRequest();
     $viewer = $this->getViewer();
 
     $edit_dialog = id(new PHUIDiffInlineCommentEditView())
       ->setViewer($viewer)
       ->setInlineComment($inline)
       ->setIsOnRight($this->getIsOnRight())
       ->setRenderer($this->getRenderer());
 
     return $edit_dialog;
   }
 
   private function buildEmptyResponse() {
     return id(new AphrontAjaxResponse())
       ->setContent(
         array(
           'inline' => array(),
           'view' => null,
         ));
   }
 
   private function buildRenderedCommentResponse(
     PhabricatorInlineComment $inline,
     $on_right) {
 
     $request = $this->getRequest();
     $viewer = $this->getViewer();
 
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($viewer);
     $engine->addObject(
       $inline,
       PhabricatorInlineComment::MARKUP_FIELD_BODY);
     $engine->process();
 
     $phids = array($viewer->getPHID());
 
     $handles = $this->loadViewerHandles($phids);
     $object_owner_phid = $this->loadObjectOwnerPHID($inline);
 
     $view = id(new PHUIDiffInlineCommentDetailView())
       ->setUser($viewer)
       ->setInlineComment($inline)
       ->setIsOnRight($on_right)
       ->setMarkupEngine($engine)
       ->setHandles($handles)
       ->setEditable(true)
       ->setCanMarkDone(false)
       ->setObjectOwnerPHID($object_owner_phid);
 
     $view = $this->buildScaffoldForView($view);
 
     return $this->newInlineResponse($inline, $view, false);
   }
 
   private function buildScaffoldForView(PHUIDiffInlineCommentView $view) {
     $renderer = DifferentialChangesetHTMLRenderer::getHTMLRendererByKey(
       $this->getRenderer());
 
     $view = $renderer->getRowScaffoldForInline($view);
 
     return id(new PHUIDiffInlineCommentTableScaffold())
       ->addRowScaffold($view);
   }
 
   private function newInlineResponse(
     PhabricatorInlineComment $inline,
     $view,
     $is_edit) {
 
     if ($inline->getReplyToCommentPHID()) {
       $can_suggest = false;
     } else {
       $can_suggest = (bool)$inline->getInlineContext();
     }
 
     if ($is_edit) {
       $viewer = $this->getViewer();
       $content_state = $inline->getContentStateForEdit($viewer);
     } else {
       $content_state = $inline->getContentState();
     }
 
     $state_map = $content_state->newStorageMap();
 
     $response = array(
       'inline' => array(
         'id' => $inline->getID(),
         'contentState' => $state_map,
         'canSuggestEdit' => $can_suggest,
       ),
       'view' => hsprintf('%s', $view),
     );
 
     return id(new AphrontAjaxResponse())
       ->setContent($response);
   }
 
   final protected function loadCommentByID($id) {
     $query = $this->newInlineCommentQuery()
       ->withIDs(array($id));
 
     return $this->loadCommentByQuery($query);
   }
 
   final protected function loadCommentByPHID($phid) {
     $query = $this->newInlineCommentQuery()
       ->withPHIDs(array($phid));
 
     return $this->loadCommentByQuery($query);
   }
 
   final protected function loadCommentByIDForEdit($id) {
     $viewer = $this->getViewer();
 
     $query = $this->newInlineCommentQuery()
       ->withIDs(array($id))
       ->needInlineContext(true);
 
     $inline = $this->loadCommentByQuery($query);
 
     if (!$inline) {
       throw new Exception(
         pht(
           'Unable to load inline "%s".',
           $id));
     }
 
     if (!$this->canEditInlineComment($viewer, $inline)) {
       throw new Exception(
         pht(
           'Inline comment "%s" is not editable.',
           $id));
     }
 
     return $inline;
   }
 
   private function loadCommentByQuery(
     PhabricatorDiffInlineCommentQuery $query) {
     $viewer = $this->getViewer();
 
     $inline = $query
       ->setViewer($viewer)
       ->executeOne();
 
     if ($inline) {
       $inline = $inline->newInlineCommentObject();
     }
 
     return $inline;
   }
 
   private function hasContentState() {
     $request = $this->getRequest();
     return (bool)$request->getBool('hasContentState');
   }
 
   private function newRequestContentState($inline) {
     $request = $this->getRequest();
     return $inline->newContentStateFromRequest($request);
   }
 
   private function updateCommentContentState(PhabricatorInlineComment $inline) {
     if (!$this->hasContentState()) {
       throw new Exception(
         pht(
           'Attempting to update comment content state, but request has no '.
           'content state.'));
     }
 
     $state = $this->newRequestContentState($inline);
     $inline->setContentState($state);
   }
 
   private function saveComment(PhabricatorInlineComment $inline) {
     $viewer = $this->getViewer();
     $draft_engine = $this->newDraftEngine();
 
     $inline->openTransaction();
       $inline->save();
 
       PhabricatorVersionedDraft::purgeDrafts(
         $inline->getPHID(),
         $viewer->getPHID());
 
       if ($draft_engine) {
         $draft_engine->synchronize();
       }
 
     $inline->saveTransaction();
   }
 
   private function newDraftEngine() {
     $viewer = $this->getViewer();
     $object = $this->getContainerObject();
 
     if (!($object instanceof PhabricatorDraftInterface)) {
       return null;
     }
 
     return $object->newDraftEngine()
       ->setObject($object)
       ->setViewer($viewer);
   }
 
 }
diff --git a/webroot/rsrc/js/application/diff/DiffInline.js b/webroot/rsrc/js/application/diff/DiffInline.js
index 32d47562e3..c17217adfe 100644
--- a/webroot/rsrc/js/application/diff/DiffInline.js
+++ b/webroot/rsrc/js/application/diff/DiffInline.js
@@ -1,1165 +1,1191 @@
 /**
  * @provides phabricator-diff-inline
  * @requires javelin-dom
  *           phabricator-diff-inline-content-state
  * @javelin
  */
 
 JX.install('DiffInline', {
 
   construct : function() {
     this._activeContentState = new JX.DiffInlineContentState();
   },
 
   members: {
     _id: null,
     _phid: null,
     _changesetID: null,
     _row: null,
     _number: null,
     _length: null,
     _displaySide: null,
     _isNewFile: null,
     _replyToCommentPHID: null,
     _originalState: null,
     _snippet: null,
     _menuItems: null,
     _documentEngineKey: null,
 
     _isDeleted: false,
     _isInvisible: false,
     _isLoading: false,
 
     _changeset: null,
 
     _isCollapsed: false,
     _isDraft: null,
     _isDraftDone: null,
     _isFixed: null,
     _isEditing: false,
     _isNew: false,
     _isSynthetic: false,
     _isHidden: false,
 
     _editRow: null,
     _undoRow: null,
     _undoType: null,
     _undoState: null,
+    _preventUndo: false,
 
     _draftRequest: null,
     _skipFocus: false,
     _menu: null,
 
     _startOffset: null,
     _endOffset: null,
     _isSelected: false,
     _canSuggestEdit: false,
 
     _activeContentState: null,
 
     bindToRow: function(row) {
       this._row = row;
 
       var row_data = JX.Stratcom.getData(row);
       row_data.inline = this;
       this._isCollapsed = row_data.hidden || false;
 
       // TODO: Get smarter about this once we do more editing, this is pretty
       // hacky.
       var comment = JX.DOM.find(row, 'div', 'differential-inline-comment');
       var data = JX.Stratcom.getData(comment);
 
       this._readInlineState(data);
       this._phid = data.phid;
 
       if (data.on_right) {
         this._displaySide = 'right';
       } else {
         this._displaySide = 'left';
       }
 
       this._number = parseInt(data.number, 10);
       this._length = parseInt(data.length, 10);
 
       this._isNewFile = data.isNewFile;
 
       this._replyToCommentPHID = data.replyToCommentPHID;
 
       this._isDraft = data.isDraft;
       this._isFixed = data.isFixed;
       this._isGhost = data.isGhost;
       this._isSynthetic = data.isSynthetic;
       this._isDraftDone = data.isDraftDone;
 
       this._changesetID = data.changesetID;
       this._isNew = false;
       this._snippet = data.snippet;
       this._menuItems = data.menuItems;
       this._documentEngineKey = data.documentEngineKey;
 
       this._startOffset = data.startOffset;
       this._endOffset = data.endOffset;
 
       this._isEditing = data.isEditing;
 
       if (this._isEditing) {
         // NOTE: The "original" shipped down in the DOM may reflect a draft
         // which we're currently editing. This flow is a little clumsy, but
         // reasonable until some future change moves away from "send down
         // the inline, then immediately click edit".
         this.edit(null, true);
       } else {
         this.setInvisible(false);
       }
 
       this._startDrafts();
 
       return this;
     },
 
     isDraft: function() {
       return this._isDraft;
     },
 
     isDone: function() {
       return this._isFixed;
     },
 
     isEditing: function() {
       return this._isEditing;
     },
 
     isUndo: function() {
       return !!this._undoRow;
     },
 
     isDeleted: function() {
       return this._isDeleted;
     },
 
     isSynthetic: function() {
       return this._isSynthetic;
     },
 
     isDraftDone: function() {
       return this._isDraftDone;
     },
 
     isHidden: function() {
       return this._isHidden;
     },
 
     isGhost: function() {
       return this._isGhost;
     },
 
     getStartOffset: function() {
       return this._startOffset;
     },
 
     getEndOffset: function() {
       return this._endOffset;
     },
 
+    _setPreventUndo: function(prevent_undo) {
+      this._preventUndo = prevent_undo;
+    },
+
+    _getPreventUndo: function() {
+      return this._preventUndo;
+    },
+
     setIsSelected: function(is_selected) {
       this._isSelected = is_selected;
 
       if (this._row) {
         JX.DOM.alterClass(
           this._row,
           'inline-comment-selected',
           this._isSelected);
       }
 
       return this;
     },
 
     bindToRange: function(data) {
       this._displaySide = data.displaySide;
       this._number = parseInt(data.number, 10);
       this._length = parseInt(data.length, 10);
       this._isNewFile = data.isNewFile;
       this._changesetID = data.changesetID;
       this._isNew = true;
 
       if (data.hasOwnProperty('startOffset')) {
         this._startOffset = data.startOffset;
       } else {
         this._startOffset = null;
       }
 
       if (data.hasOwnProperty('endOffset')) {
         this._endOffset = data.endOffset;
       } else {
         this._endOffset = null;
       }
 
       // Insert the comment after any other comments which already appear on
       // the same row.
       var parent_row = JX.DOM.findAbove(data.target, 'tr');
       var target_row = parent_row.nextSibling;
       while (target_row && JX.Stratcom.hasSigil(target_row, 'inline-row')) {
         target_row = target_row.nextSibling;
       }
 
       var row = this._newRow();
       parent_row.parentNode.insertBefore(row, target_row);
 
       this.setInvisible(true);
       this._startDrafts();
 
       return this;
     },
 
     bindToReply: function(inline) {
       this._displaySide = inline._displaySide;
       this._number = inline._number;
       this._length = inline._length;
       this._isNewFile = inline._isNewFile;
       this._changesetID = inline._changesetID;
       this._isNew = true;
       this._documentEngineKey = inline._documentEngineKey;
 
       this._replyToCommentPHID = inline._phid;
 
       var changeset = this.getChangeset();
 
       // We're going to figure out where in the document to position the new
       // inline. Normally, it goes after any existing inline rows (so if
       // several inlines reply to the same line, they appear in chronological
       // order).
 
       // However: if inlines are threaded, we want to put the new inline in
       // the right place in the thread. This might be somewhere in the middle,
       // so we need to do a bit more work to figure it out.
 
       // To find the right place in the thread, we're going to look for any
       // inline which is at or above the level of the comment we're replying
       // to. This means we've reached a new fork of the thread, and should
       // put our new inline before the comment we found.
       var ancestor_map = {};
       var ancestor = inline;
       var reply_phid;
       while (ancestor) {
         reply_phid = ancestor.getReplyToCommentPHID();
         if (!reply_phid) {
           break;
         }
         ancestor_map[reply_phid] = true;
         ancestor = changeset.getInlineByPHID(reply_phid);
       }
 
       var parent_row = inline._row;
       var target_row = parent_row.nextSibling;
       while (target_row && JX.Stratcom.hasSigil(target_row, 'inline-row')) {
         var target = changeset.getInlineForRow(target_row);
         reply_phid = target.getReplyToCommentPHID();
 
         // If we found an inline which is replying directly to some ancestor
         // of this new comment, this is where the new rows go.
         if (ancestor_map.hasOwnProperty(reply_phid)) {
           break;
         }
 
         target_row = target_row.nextSibling;
       }
 
       var row = this._newRow();
       parent_row.parentNode.insertBefore(row, target_row);
 
       this.setInvisible(true);
       this._startDrafts();
 
       return this;
     },
 
     setChangeset: function(changeset) {
       this._changeset = changeset;
       return this;
     },
 
     getChangeset: function() {
       return this._changeset;
     },
 
     setEditing: function(editing) {
       this._isEditing = editing;
       return this;
     },
 
     setHidden: function(hidden) {
       this._isHidden = hidden;
       this._redraw();
       return this;
     },
 
     canReply: function() {
       return this._hasMenuAction('reply');
     },
 
     canEdit: function() {
       return this._hasMenuAction('edit');
     },
 
     canDone: function() {
       if (!JX.DOM.scry(this._row, 'input', 'differential-inline-done').length) {
         return false;
       }
 
       return true;
     },
 
     canCollapse: function() {
       return this._hasMenuAction('collapse');
     },
 
     _newRow: function() {
       var attributes = {
         sigil: 'inline-row'
       };
 
       var row = JX.$N('tr', attributes);
 
       JX.Stratcom.getData(row).inline = this;
       this._row = row;
 
       this._id = null;
       this._phid = null;
       this._isCollapsed = false;
 
       this._originalState = null;
 
       return row;
     },
 
     setCollapsed: function(collapsed) {
       this._closeMenu();
 
       this._isCollapsed = collapsed;
 
       var op;
       if (collapsed) {
         op = 'hide';
       } else {
         op = 'show';
       }
 
       var inline_uri = this._getInlineURI();
       var comment_id = this._id;
 
       new JX.Workflow(inline_uri, {op: op, ids: comment_id})
         .setHandler(JX.bag)
         .start();
 
       this._redraw();
       this._didUpdate(true);
     },
 
     isCollapsed: function() {
       return this._isCollapsed;
     },
 
     toggleDone: function() {
       var uri = this._getInlineURI();
       var data = {
         op: 'done',
         id: this._id
       };
 
       var ondone = JX.bind(this, this._ondone);
 
       new JX.Workflow(uri, data)
         .setHandler(ondone)
         .start();
     },
 
     _ondone: function(response) {
       var checkbox = JX.DOM.find(
         this._row,
         'input',
         'differential-inline-done');
 
       checkbox.checked = (response.isChecked ? 'checked' : null);
 
       var comment = JX.DOM.findAbove(
         checkbox,
         'div',
         'differential-inline-comment');
 
       JX.DOM.alterClass(comment, 'inline-is-done', response.isChecked);
 
       // NOTE: This is marking the inline as having an unsubmitted checkmark,
       // as opposed to a submitted checkmark. This is different from the
       // top-level "draft" state of unsubmitted comments.
       JX.DOM.alterClass(comment, 'inline-state-is-draft', response.draftState);
 
       this._isFixed = response.isChecked;
       this._isDraftDone = !!response.draftState;
 
       this._didUpdate();
     },
 
     create: function(content_state) {
       var changeset = this.getChangeset();
       if (!this._documentEngineKey) {
         this._documentEngineKey = changeset.getResponseDocumentEngineKey();
       }
 
       var uri = this._getInlineURI();
       var handler = JX.bind(this, this._oncreateresponse);
       var data = this._newRequestData('new', content_state);
 
       this.setLoading(true);
 
       new JX.Request(uri, handler)
         .setData(data)
         .send();
     },
 
     reply: function(with_quote) {
       this._closeMenu();
 
       var content_state = this._newContentState();
       if (with_quote) {
         var text = this._getActiveContentState().getTextForQuote();
         content_state.text = text;
       }
 
       var changeset = this.getChangeset();
       return changeset.newInlineReply(this, content_state);
     },
 
     edit: function(content_state, skip_focus) {
       this._closeMenu();
 
       this._skipFocus = !!skip_focus;
 
       // If you edit an inline ("A"), modify the text ("AB"), cancel, and then
       // edit it again: discard the undo state ("AB"). Otherwise we end up
       // with an open editor and an active "Undo" link, which is weird.
 
       if (this._undoRow) {
         JX.DOM.remove(this._undoRow);
         this._undoRow = null;
 
         this._undoType = null;
         this._undoText = null;
       }
 
       var uri = this._getInlineURI();
       var handler = JX.bind(this, this._oneditresponse);
 
       var data = this._newRequestData('edit', content_state);
 
       this.setLoading(true);
 
       new JX.Request(uri, handler)
         .setData(data)
         .send();
     },
 
     delete: function(is_ref) {
       var uri = this._getInlineURI();
       var handler = JX.bind(this, this._ondeleteresponse);
 
       // NOTE: This may be a direct delete (the user clicked on the inline
       // itself) or a "refdelete" (the user clicked somewhere else, like the
       // preview, but the inline is present on the page).
 
       // For a "refdelete", we prompt the user to confirm that they want to
       // delete the comment, because they can not undo deletions from the
       // preview. We could jump the user to the inline instead, but this would
       // be somewhat disruptive and make deleting several comments more
       // difficult.
 
       var op;
       if (is_ref) {
         op = 'refdelete';
       } else {
         op = 'delete';
       }
 
       var data = this._newRequestData(op);
 
       this.setLoading(true);
 
       new JX.Workflow(uri, data)
         .setHandler(handler)
         .start();
     },
 
     getDisplaySide: function() {
       return this._displaySide;
     },
 
     getLineNumber: function() {
       return this._number;
     },
 
     getLineLength: function() {
       return this._length;
     },
 
     isNewFile: function() {
       return this._isNewFile;
     },
 
     getID: function() {
       return this._id;
     },
 
     getPHID: function() {
       return this._phid;
     },
 
     getChangesetID: function() {
       return this._changesetID;
     },
 
     getReplyToCommentPHID: function() {
       return this._replyToCommentPHID;
     },
 
     setDeleted: function(deleted) {
       this._isDeleted = deleted;
       this._redraw();
       return this;
     },
 
     setInvisible: function(invisible) {
       this._isInvisible = invisible;
       this._redraw();
       return this;
     },
 
     setLoading: function(loading) {
       this._isLoading = loading;
       this._redraw();
       return this;
     },
 
     _newRequestData: function(operation, content_state) {
       var data = {
         op: operation,
         is_new: this.isNewFile(),
         on_right: ((this.getDisplaySide() == 'right') ? 1 : 0),
         renderer: this.getChangeset().getRendererKey()
       };
 
       if (operation === 'new') {
         var create_data = {
           changesetID: this.getChangesetID(),
           documentEngineKey: this._documentEngineKey,
           replyToCommentPHID: this.getReplyToCommentPHID(),
           startOffset: this._startOffset,
           endOffset: this._endOffset,
           number: this.getLineNumber(),
           length: this.getLineLength()
         };
 
         JX.copy(data, create_data);
       } else {
         var edit_data = {
           id: this._id
         };
 
         JX.copy(data, edit_data);
       }
 
       if (content_state) {
         data.hasContentState = 1;
         JX.copy(data, content_state);
       }
 
       return data;
     },
 
     _oneditresponse: function(response) {
       var rows = JX.$H(response.view).getNode();
 
       this._readInlineState(response.inline);
       this._drawEditRows(rows);
 
       this.setLoading(false);
       this.setInvisible(true);
     },
 
     _oncreateresponse: function(response) {
       var rows = JX.$H(response.view).getNode();
 
       this._readInlineState(response.inline);
       this._drawEditRows(rows);
     },
 
     _readInlineState: function(state) {
       this._id = state.id;
       this._originalState = state.contentState;
 
       this._getActiveContentState().readWireFormat(state.contentState);
 
       this._canSuggestEdit = state.canSuggestEdit;
     },
 
     _ondeleteresponse: function() {
       // If there's an existing "unedit" undo element, remove it.
       if (this._undoRow) {
         JX.DOM.remove(this._undoRow);
         this._undoRow = null;
       }
 
       // If there's an existing editor, remove it. This happens when you
       // delete a comment from the comment preview area. In this case, we
       // read and preserve the text so "Undo" restores it.
       var state = null;
       if (this._editRow) {
         state = this._getActiveContentState().getWireFormat();
         JX.DOM.remove(this._editRow);
         this._editRow = null;
       }
 
-      this._drawUndeleteRows(state);
+      if (!this._getPreventUndo()) {
+        this._drawUndeleteRows(state);
+      }
 
       this.setLoading(false);
       this.setDeleted(true);
 
       this._didUpdate();
     },
 
     _drawUndeleteRows: function(content_state) {
       this._undoType = 'undelete';
       this._undoState = content_state || null;
 
       return this._drawUndoRows('undelete', this._row);
     },
 
     _drawUneditRows: function(content_state) {
       this._undoType = 'unedit';
       this._undoState = content_state;
 
       return this._drawUndoRows('unedit', null);
     },
 
     _drawUndoRows: function(mode, cursor) {
       var templates = this.getChangeset().getUndoTemplates();
 
       var template;
       if (this.getDisplaySide() == 'right') {
         template = templates.r;
       } else {
         template = templates.l;
       }
       template = JX.$H(template).getNode();
 
       this._undoRow = this._drawRows(template, cursor, mode);
     },
 
     _drawContentRows: function(rows) {
       return this._drawRows(rows, null, 'content');
     },
 
     _drawEditRows: function(rows) {
       this.setEditing(true);
       this._editRow = this._drawRows(rows, null, 'edit');
 
       this._drawSuggestionState(this._editRow);
       this.setHasSuggestion(this._originalState.hasSuggestion);
     },
 
     _drawRows: function(rows, cursor, type) {
       var first_row = JX.DOM.scry(rows, 'tr')[0];
       var row = first_row;
       var anchor = cursor || this._row;
       cursor = cursor || this._row.nextSibling;
 
 
       var result_row;
       var next_row;
       while (row) {
         // Grab this first, since it's going to change once we insert the row
         // into the document.
         next_row = row.nextSibling;
 
         // Bind edit and undo rows to this DiffInline object so that
         // interactions like hovering work properly.
         JX.Stratcom.getData(row).inline = this;
 
         anchor.parentNode.insertBefore(row, cursor);
         cursor = row;
 
         if (!result_row) {
           result_row = row;
         }
 
         if (!this._skipFocus) {
           // If the row has a textarea, focus it. This allows the user to start
           // typing a comment immediately after a "new", "edit", or "reply"
           // action.
 
           // (When simulating an "edit" on page load, we don't do this.)
 
           var textareas = JX.DOM.scry(
             row,
             'textarea',
             'inline-content-text');
           if (textareas.length) {
             var area = textareas[0];
             area.focus();
 
             var length = area.value.length;
             JX.TextAreaUtils.setSelectionRange(area, length, length);
           }
         }
 
         row = next_row;
       }
 
       JX.Stratcom.invoke('resize');
 
       return result_row;
     },
 
     _drawSuggestionState: function(row) {
       if (this._canSuggestEdit) {
         var button = this._getSuggestionButton();
         var node = button.getNode();
 
         // As a side effect of form submission, the button may become
         // visually disabled. Re-enable it. This is a bit hacky.
         JX.DOM.alterClass(node, 'disabled', false);
         node.disabled = false;
 
         var container = JX.DOM.find(row, 'div', 'inline-edit-buttons');
         container.appendChild(node);
       }
     },
 
     _getSuggestionButton: function() {
       if (!this._suggestionButton) {
         var button = new JX.PHUIXButtonView()
           .setIcon('fa-pencil-square-o')
           .setColor('grey');
 
         var node = button.getNode();
         JX.DOM.alterClass(node, 'inline-button-left', true);
 
         var onclick = JX.bind(this, this._onSuggestEdit);
         JX.DOM.listen(node, 'click', null, onclick);
 
         this._suggestionButton = button;
       }
 
       return this._suggestionButton;
     },
 
     _onSuggestEdit: function(e) {
       e.kill();
 
       this.setHasSuggestion(!this.getHasSuggestion());
 
       // The first time the user actually clicks the button and enables
       // suggestions for a given editor state, fill the input with the
       // underlying text if there isn't any text yet.
       if (this.getHasSuggestion()) {
         if (this._editRow) {
           var node = this._getSuggestionNode(this._editRow);
           if (node) {
             if (!node.value.length) {
               var data = JX.Stratcom.getData(node);
               if (!data.hasSetDefault) {
                 data.hasSetDefault = true;
                 node.value = data.defaultText;
                 node.rows = Math.max(3, node.value.split('\n').length);
               }
             }
           }
         }
       }
 
       // Save the "hasSuggestion" part of the content state.
       this.triggerDraft();
     },
 
     _getActiveContentState: function() {
       var state = this._activeContentState;
 
       if (this._editRow) {
         state.readForm(this._editRow);
       }
 
       return state;
     },
 
     setHasSuggestion: function(has_suggestion) {
       var state = this._getActiveContentState();
       state.setHasSuggestion(has_suggestion);
 
       var button = this._getSuggestionButton();
       var pht = this.getChangeset().getChangesetList().getTranslations();
       if (has_suggestion) {
         button
           .setIcon('fa-times')
           .setText(pht('Discard Edit'));
       } else {
         button
           .setIcon('fa-plus')
           .setText(pht('Suggest Edit'));
       }
 
       if (this._editRow) {
         JX.DOM.alterClass(this._editRow, 'has-suggestion', has_suggestion);
       }
     },
 
     getHasSuggestion: function() {
       return this._getActiveContentState().getHasSuggestion();
     },
 
     save: function() {
+      if (this._shouldDeleteOnSave()) {
+        this._setPreventUndo(true);
+        this._applyDelete();
+      } else {
+        this._applySave();
+      }
+    },
+
+    _shouldDeleteOnSave: function() {
       var state = this._getActiveContentState();
-      var handler = JX.bind(this, this._onsubmitresponse);
 
-      this.setLoading(true);
+      // TODO: This is greatly simplified because we don't track all the
+      // state we need yet.
 
-      var uri = this._getInlineURI();
+      return !state.getText().length;
+    },
+
+    _applySave: function() {
+      var handler = JX.bind(this, this._onsaveresponse);
+
+      var state = this._getActiveContentState();
       var data = this._newRequestData('save', state.getWireFormat());
 
-      new JX.Request(uri, handler)
-        .setData(data)
-        .send();
+      this._applyCall(handler, data);
+    },
+
+    _applyDelete: function() {
+      var handler = JX.bind(this, this._ondeleteresponse);
+
+      var data = this._newRequestData('delete');
+
+      this._applyCall(handler, data);
+    },
+
+    _applyCall: function(handler, data) {
+      var uri = this._getInlineURI();
+
+      var callback = JX.bind(this, function() {
+        this.setLoading(false);
+        handler.apply(null, arguments);
+      });
+
+      this.setLoading(true);
+
+      new JX.Workflow(uri, data)
+        .setHandler(callback)
+        .start();
     },
 
     undo: function() {
       JX.DOM.remove(this._undoRow);
       this._undoRow = null;
 
       if (this._undoType === 'undelete') {
         var uri = this._getInlineURI();
         var data = this._newRequestData('undelete');
         var handler = JX.bind(this, this._onundelete);
 
         this.setDeleted(false);
         this.setLoading(true);
 
         new JX.Request(uri, handler)
           .setData(data)
           .send();
       }
 
       if (this._undoState !== null) {
         this.edit(this._undoState);
       }
     },
 
     _onundelete: function() {
       this.setLoading(false);
       this._didUpdate();
     },
 
     cancel: function() {
       var state = this._getActiveContentState().getWireFormat();
 
       JX.DOM.remove(this._editRow);
       this._editRow = null;
 
       var is_empty = this._isVoidContentState(state);
       var is_same = this._isSameContentState(state, this._originalState);
       if (!is_empty && !is_same) {
         this._drawUneditRows(state);
       }
 
       // If this was an empty box and we typed some text and then hit cancel,
       // don't show the empty concrete inline.
       if (this._isVoidContentState(this._originalState)) {
         this.setInvisible(true);
       } else {
         this.setInvisible(false);
       }
 
       // If you "undo" to restore text ("AB") and then "Cancel", we put you
       // back in the original text state ("A"). We also send the original
       // text ("A") to the server as the current persistent state.
 
       var uri = this._getInlineURI();
       var data = this._newRequestData('cancel', this._originalState);
       var handler = JX.bind(this, this._onCancelResponse);
 
       this.setLoading(true);
 
       new JX.Request(uri, handler)
         .setData(data)
         .send();
 
       this._didUpdate(true);
     },
 
     _onCancelResponse: function(response) {
       this.setEditing(false);
       this.setLoading(false);
 
       // If the comment was empty when we started editing it (there's no
       // original text) and empty when we finished editing it (there's no
       // undo row), just delete the comment.
       if (this._isVoidContentState(this._originalState) && !this.isUndo()) {
         this.setDeleted(true);
 
         JX.DOM.remove(this._row);
         this._row = null;
 
         this._didUpdate();
       }
     },
 
     _getSuggestionNode: function(row) {
       try {
         return JX.DOM.find(row, 'textarea', 'inline-content-suggestion');
       } catch (ex) {
         return null;
       }
     },
 
-    _onsubmitresponse: function(response) {
+    _onsaveresponse: function(response) {
       if (this._editRow) {
         JX.DOM.remove(this._editRow);
         this._editRow = null;
       }
 
       this.setLoading(false);
       this.setInvisible(false);
       this.setEditing(false);
 
-      this._onupdate(response);
-    },
-
-    _onupdate: function(response) {
-      var new_row;
-      if (response.view) {
-        new_row = this._drawContentRows(JX.$H(response.view).getNode());
-      }
-
-      // TODO: Save the old row so the action it's undo-able if it was a
-      // delete.
-      var remove_old = true;
-      if (remove_old) {
-        JX.DOM.remove(this._row);
-      }
-
-      // If you delete the content on a comment and save it, it acts like a
-      // delete: the server does not return a new row.
-      if (new_row) {
-        this.bindToRow(new_row);
-      } else {
-        this.setDeleted(true);
-        this._row = null;
-      }
+      var new_row = this._drawContentRows(JX.$H(response.view).getNode());
+      JX.DOM.remove(this._row);
+      this.bindToRow(new_row);
 
       this._didUpdate();
     },
 
     _didUpdate: function(local_only) {
       // After making changes to inline comments, refresh the transaction
       // preview at the bottom of the page.
       if (!local_only) {
         this.getChangeset().getChangesetList().redrawPreview();
       }
 
       this.getChangeset().getChangesetList().redrawCursor();
       this.getChangeset().getChangesetList().resetHover();
 
       // Emit a resize event so that UI elements like the keyboard focus
       // reticle can redraw properly.
       JX.Stratcom.invoke('resize');
     },
 
     _redraw: function() {
       var is_invisible =
         (this._isInvisible || this._isDeleted || this._isHidden);
       var is_loading = this._isLoading;
       var is_collapsed = (this._isCollapsed && !this._isHidden);
 
       var row = this._row;
       JX.DOM.alterClass(row, 'differential-inline-hidden', is_invisible);
       JX.DOM.alterClass(row, 'differential-inline-loading', is_loading);
       JX.DOM.alterClass(row, 'inline-hidden', is_collapsed);
     },
 
     _getInlineURI: function() {
       var changeset = this.getChangeset();
       var list = changeset.getChangesetList();
       return list.getInlineURI();
     },
 
     _startDrafts: function() {
       if (this._draftRequest) {
         return;
       }
 
       var onresponse = JX.bind(this, this._onDraftResponse);
       var draft = JX.bind(this, this._getDraftState);
 
       var uri = this._getInlineURI();
       var request = new JX.PhabricatorShapedRequest(uri, onresponse, draft);
 
       // The main transaction code uses a 500ms delay on desktop and a
       // 10s delay on mobile. Perhaps this should be standardized.
       request.setRateLimit(2000);
 
       this._draftRequest = request;
 
       request.start();
     },
 
     _onDraftResponse: function() {
       // For now, do nothing.
     },
 
     _getDraftState: function() {
       if (this.isDeleted()) {
         return null;
       }
 
       if (!this.isEditing()) {
         return null;
       }
 
       var state = this._getActiveContentState().getWireFormat();
       if (this._isVoidContentState(state)) {
         return null;
       }
 
       var draft_data = {
         op: 'draft',
         id: this.getID(),
       };
 
       JX.copy(draft_data, state);
 
       return draft_data;
     },
 
     triggerDraft: function() {
       if (this._draftRequest) {
         this._draftRequest.trigger();
       }
     },
 
     activateMenu: function(button, e) {
       // If we already have a menu for this button, let the menu handle the
       // event.
       var data = JX.Stratcom.getData(button);
       if (data.menu) {
         return;
       }
 
       e.prevent();
 
       var menu = new JX.PHUIXDropdownMenu(button)
         .setWidth(240);
 
       var list = new JX.PHUIXActionListView();
       var items = this._newMenuItems(menu);
       for (var ii = 0; ii < items.length; ii++) {
         list.addItem(items[ii]);
       }
 
       menu.setContent(list.getNode());
 
       data.menu = menu;
       this._menu = menu;
 
       menu.listen('open', JX.bind(this, function() {
         var changeset_list = this.getChangeset().getChangesetList();
         changeset_list.selectInline(this, true);
       }));
 
       menu.open();
     },
 
     _newMenuItems: function(menu) {
       var items = [];
 
       for (var ii = 0; ii < this._menuItems.length; ii++) {
         var spec = this._menuItems[ii];
 
         var onmenu = JX.bind(this, this._onMenuItem, menu, spec.action, spec);
 
         var item = new JX.PHUIXActionView()
           .setIcon(spec.icon)
           .setName(spec.label)
           .setHandler(onmenu);
 
         if (spec.key) {
           item.setKeyCommand(spec.key);
         }
 
         items.push(item);
       }
 
       return items;
     },
 
     _onMenuItem: function(menu, action, spec, e) {
       e.prevent();
       menu.close();
 
       switch (action) {
         case 'reply':
           this.reply();
           break;
         case 'quote':
           this.reply(true);
           break;
         case 'collapse':
           this.setCollapsed(true);
           break;
         case 'delete':
           this.delete();
           break;
         case 'edit':
           this.edit();
           break;
         case 'raw':
           new JX.Workflow(spec.uri)
             .start();
           break;
       }
 
     },
 
     _hasMenuAction: function(action) {
       for (var ii = 0; ii < this._menuItems.length; ii++) {
         var spec = this._menuItems[ii];
         if (spec.action === action) {
           return true;
         }
       }
       return false;
     },
 
     _closeMenu: function() {
       if (this._menu) {
         this._menu.close();
       }
     },
 
     _newContentState: function() {
       return {
         text: '',
         suggestionText: '',
         hasSuggestion: false
       };
     },
 
     _isVoidContentState: function(state) {
       return (!state.text.length && !state.suggestionText.length);
     },
 
     _isSameContentState: function(u, v) {
       return (
         ((u === null) === (v === null)) &&
         (u.text === v.text) &&
         (u.suggestionText === v.suggestionText) &&
         (u.hasSuggestion === v.hasSuggestion));
     }
   }
 
 });