Index: src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php
===================================================================
--- src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php
+++ src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php
@@ -31,6 +31,16 @@
     return pht('Commit Hook: Commit Content');
   }
 
+  public function getAdapterSortOrder() {
+    return 2500;
+  }
+
+  public function getAdapterContentDescription() {
+    return pht(
+      "React to commits being pushed to hosted repositories.\n".
+      "Hook rules can block changes.");
+  }
+
   public function getFieldNameMap() {
     return array(
     ) + parent::getFieldNameMap();
Index: src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php
===================================================================
--- src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php
+++ src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php
@@ -34,6 +34,16 @@
     return pht('Commit Hook: Branches/Tags/Bookmarks');
   }
 
+  public function getAdapterSortOrder() {
+    return 2000;
+  }
+
+  public function getAdapterContentDescription() {
+    return pht(
+      "React to branches and tags being pushed to hosted repositories.\n".
+      "Hook rules can block changes.");
+  }
+
   public function getFieldNameMap() {
     return array(
       self::FIELD_REF_TYPE => pht('Ref type'),
Index: src/applications/herald/adapter/HeraldAdapter.php
===================================================================
--- src/applications/herald/adapter/HeraldAdapter.php
+++ src/applications/herald/adapter/HeraldAdapter.php
@@ -134,9 +134,21 @@
   }
 
   abstract public function getAdapterContentName();
+  abstract public function getAdapterContentDescription();
   abstract public function getAdapterApplicationClass();
   abstract public function getObject();
 
+  public function getAdapterSortKey() {
+    return sprintf(
+      '%08d%s',
+      $this->getAdapterSortOrder(),
+      $this->getAdapterContentName());
+  }
+
+  public function getAdapterSortOrder() {
+    return 1000;
+  }
+
 
 /* -(  Fields  )------------------------------------------------------------- */
 
@@ -808,6 +820,7 @@
       $adapters = id(new PhutilSymbolLoader())
         ->setAncestorClass(__CLASS__)
         ->loadObjects();
+      $adapters = msort($adapters, 'getAdapterSortKey');
     }
     return $adapters;
   }
@@ -840,7 +853,6 @@
       $map[$type] = $name;
     }
 
-    asort($map);
     return $map;
   }
 
Index: src/applications/herald/adapter/HeraldCommitAdapter.php
===================================================================
--- src/applications/herald/adapter/HeraldCommitAdapter.php
+++ src/applications/herald/adapter/HeraldCommitAdapter.php
@@ -42,6 +42,13 @@
     return pht('Commits');
   }
 
+  public function getAdapterContentDescription() {
+    return pht(
+      "React to new commits appearing in tracked repositories.\n".
+      "Commit rules can send email, flag commits, trigger audits, ".
+      "and run build plans.");
+  }
+
   public function getFieldNameMap() {
     return array(
       self::FIELD_NEED_AUDIT_FOR_PACKAGE =>
Index: src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
===================================================================
--- src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
+++ src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
@@ -36,6 +36,13 @@
     return pht('Differential Revisions');
   }
 
+  public function getAdapterContentDescription() {
+    return pht(
+      "React to revisions being created or updated.\n".
+      "Revision rules can send email, flag revisions, add reviewers, ".
+      "and run build plans.");
+  }
+
   public function getFields() {
     return array_merge(
       array(
Index: src/applications/herald/adapter/HeraldManiphestTaskAdapter.php
===================================================================
--- src/applications/herald/adapter/HeraldManiphestTaskAdapter.php
+++ src/applications/herald/adapter/HeraldManiphestTaskAdapter.php
@@ -14,6 +14,11 @@
     return 'PhabricatorApplicationManiphest';
   }
 
+  public function getAdapterContentDescription() {
+    return pht(
+      'React to tasks being created or updated.');
+  }
+
   public function setTask(ManiphestTask $task) {
     $this->task = $task;
     return $this;
Index: src/applications/herald/adapter/HeraldPholioMockAdapter.php
===================================================================
--- src/applications/herald/adapter/HeraldPholioMockAdapter.php
+++ src/applications/herald/adapter/HeraldPholioMockAdapter.php
@@ -12,6 +12,11 @@
     return 'PhabricatorApplicationPholio';
   }
 
+  public function getAdapterContentDescription() {
+    return pht(
+      'React to mocks being created or updated.');
+  }
+
   public function getObject() {
     return $this->mock;
   }
Index: src/applications/herald/controller/HeraldNewController.php
===================================================================
--- src/applications/herald/controller/HeraldNewController.php
+++ src/applications/herald/controller/HeraldNewController.php
@@ -53,19 +53,21 @@
       ->setUser($user)
       ->setAction($this->getApplicationURI('new/'));
 
-    $rule_types = $this->renderRuleTypeControl($rule_type_map, $e_rule);
+    $content_types = $this->renderContentTypeControl(
+      $content_type_map,
+      $e_type);
+
+    $rule_types = $this->renderRuleTypeControl(
+      $rule_type_map,
+      $e_rule);
 
     switch ($step) {
       case 0:
       default:
         $form
           ->addHiddenInput('step', 1)
-          ->appendChild(
-            id(new AphrontFormSelectControl())
-              ->setLabel(pht('New Rule for'))
-              ->setName('content_type')
-              ->setValue($request->getStr('content_type'))
-              ->setOptions($content_type_map));
+          ->appendChild($content_types);
+
         $cancel_text = null;
         $cancel_uri = $this->getApplicationURI();
         break;
@@ -73,7 +75,16 @@
         $form
           ->addHiddenInput('content_type', $request->getStr('content_type'))
           ->addHiddenInput('step', 2)
+          ->appendChild(
+            id(new AphrontFormStaticControl())
+              ->setLabel(pht('Rule for'))
+              ->setValue(
+                phutil_tag(
+                  'strong',
+                  array(),
+                  idx($content_type_map, $content_type))))
           ->appendChild($rule_types);
+
         $cancel_text = pht('Back');
         $cancel_uri = id(new PhutilURI('new/'))
           ->setQueryParams(
@@ -112,6 +123,27 @@
       ));
   }
 
+  private function renderContentTypeControl(array $content_type_map, $e_type) {
+    $request = $this->getRequest();
+
+    $radio = id(new AphrontFormRadioButtonControl())
+      ->setLabel(pht('New Rule for'))
+      ->setName('content_type')
+      ->setValue($request->getStr('content_type'))
+      ->setError($e_type);
+
+    foreach ($content_type_map as $value => $name) {
+      $adapter = HeraldAdapter::getAdapterForContentType($value);
+      $radio->addButton(
+        $value,
+        $name,
+        phutil_escape_html_newlines($adapter->getAdapterContentDescription()));
+    }
+
+    return $radio;
+  }
+
+
   private function renderRuleTypeControl(array $rule_type_map, $e_rule) {
     $request = $this->getRequest();