diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -4195,6 +4195,7 @@
     'PhabricatorPolicyManagementWorkflow' => 'applications/policy/management/PhabricatorPolicyManagementWorkflow.php',
     'PhabricatorPolicyPHIDTypePolicy' => 'applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php',
     'PhabricatorPolicyQuery' => 'applications/policy/query/PhabricatorPolicyQuery.php',
+    'PhabricatorPolicyRef' => 'applications/policy/view/PhabricatorPolicyRef.php',
     'PhabricatorPolicyRequestExceptionHandler' => 'aphront/handler/PhabricatorPolicyRequestExceptionHandler.php',
     'PhabricatorPolicyRule' => 'applications/policy/rule/PhabricatorPolicyRule.php',
     'PhabricatorPolicySearchEngineExtension' => 'applications/policy/engineextension/PhabricatorPolicySearchEngineExtension.php',
@@ -10675,6 +10676,7 @@
     'PhabricatorPolicyManagementWorkflow' => 'PhabricatorManagementWorkflow',
     'PhabricatorPolicyPHIDTypePolicy' => 'PhabricatorPHIDType',
     'PhabricatorPolicyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+    'PhabricatorPolicyRef' => 'Phobject',
     'PhabricatorPolicyRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
     'PhabricatorPolicyRule' => 'Phobject',
     'PhabricatorPolicySearchEngineExtension' => 'PhabricatorSearchEngineExtension',
diff --git a/src/applications/policy/management/PhabricatorPolicyManagementShowWorkflow.php b/src/applications/policy/management/PhabricatorPolicyManagementShowWorkflow.php
--- a/src/applications/policy/management/PhabricatorPolicyManagementShowWorkflow.php
+++ b/src/applications/policy/management/PhabricatorPolicyManagementShowWorkflow.php
@@ -60,8 +60,10 @@
 
     $console->writeOut("__%s__\n\n", pht('CAPABILITIES'));
     foreach ($policies as $capability => $policy) {
+      $ref = $policy->newRef($viewer);
+
       $console->writeOut("  **%s**\n", $capability);
-      $console->writeOut("    %s\n", $policy->renderDescription());
+      $console->writeOut("    %s\n", $ref->getPolicyDisplayName());
       $console->writeOut("    %s\n",
         PhabricatorPolicy::getPolicyExplanation($viewer, $policy->getPHID()));
       $console->writeOut("\n");
diff --git a/src/applications/policy/query/PhabricatorPolicyQuery.php b/src/applications/policy/query/PhabricatorPolicyQuery.php
--- a/src/applications/policy/query/PhabricatorPolicyQuery.php
+++ b/src/applications/policy/query/PhabricatorPolicyQuery.php
@@ -48,7 +48,8 @@
     $policies = self::loadPolicies($viewer, $object);
 
     foreach ($policies as $capability => $policy) {
-      $policies[$capability] = $policy->renderDescription();
+      $policies[$capability] = $policy->newRef($viewer)
+        ->newCapabilityLink($object, $capability);
     }
 
     return $policies;
diff --git a/src/applications/policy/storage/PhabricatorPolicy.php b/src/applications/policy/storage/PhabricatorPolicy.php
--- a/src/applications/policy/storage/PhabricatorPolicy.php
+++ b/src/applications/policy/storage/PhabricatorPolicy.php
@@ -276,32 +276,22 @@
     }
   }
 
-  public function renderDescription() {
-    if ($this->getHref()) {
-      $desc = javelin_tag(
-        'a',
-        array(
-          'href' => $this->getHref(),
-          'class' => 'policy-link',
-          'sigil' => $this->getWorkflow() ? 'workflow' : null,
-        ),
-        $this->getName());
-    } else {
-      $desc = $this->getName();
-    }
+  public function newRef(PhabricatorUser $viewer) {
+    return id(new PhabricatorPolicyRef())
+      ->setViewer($viewer)
+      ->setPolicy($this);
+  }
 
-    switch ($this->getType()) {
-      case PhabricatorPolicyType::TYPE_PROJECT:
-        return pht('%s (Project)', $desc);
-      case PhabricatorPolicyType::TYPE_CUSTOM:
-        return $desc;
-      case PhabricatorPolicyType::TYPE_MASKED:
-        return pht(
-          '%s (You do not have permission to view policy details.)',
-          $desc);
-      default:
-        return $desc;
-    }
+  public function isProjectPolicy() {
+    return ($this->getType() === PhabricatorPolicyType::TYPE_PROJECT);
+  }
+
+  public function isCustomPolicy() {
+    return ($this->getType() === PhabricatorPolicyType::TYPE_CUSTOM);
+  }
+
+  public function isMaskedPolicy() {
+    return ($this->getType() === PhabricatorPolicyType::TYPE_MASKED);
   }
 
   /**
diff --git a/src/applications/policy/view/PhabricatorPolicyRef.php b/src/applications/policy/view/PhabricatorPolicyRef.php
new file mode 100644
--- /dev/null
+++ b/src/applications/policy/view/PhabricatorPolicyRef.php
@@ -0,0 +1,99 @@
+<?php
+
+final class PhabricatorPolicyRef
+  extends Phobject {
+
+  private $viewer;
+  private $policy;
+
+  public function setViewer(PhabricatorUser $viewer) {
+    $this->viewer = $viewer;
+    return $this;
+  }
+
+  public function getViewer() {
+    return $this->viewer;
+  }
+
+  public function setPolicy(PhabricatorPolicy $policy) {
+    $this->policy = $policy;
+    return $this;
+  }
+
+  public function getPolicy() {
+    return $this->policy;
+  }
+
+  public function getPolicyDisplayName() {
+    $policy = $this->getPolicy();
+    return $policy->getFullName();
+  }
+
+  public function newTransactionLink(
+    $mode,
+    PhabricatorApplicationTransaction $xaction) {
+
+    $policy = $this->getPolicy();
+
+    if ($policy->isCustomPolicy()) {
+      $uri = urisprintf(
+        '/transactions/%s/%s/',
+        $mode,
+        $xaction->getPHID());
+      $workflow = true;
+    } else {
+      $uri = $policy->getHref();
+      $workflow = false;
+    }
+
+    return $this->newLink($uri, $workflow);
+  }
+
+  public function newCapabilityLink($object, $capability) {
+    $policy = $this->getPolicy();
+
+    $uri = urisprintf(
+      '/policy/explain/%s/%s/',
+      $object->getPHID(),
+      $capability);
+
+    return $this->newLink($uri, true);
+  }
+
+  private function newLink($uri, $workflow) {
+    $policy = $this->getPolicy();
+    $name = $policy->getName();
+
+    if ($uri !== null) {
+      $name = javelin_tag(
+        'a',
+        array(
+          'href' => $uri,
+          'sigil' => ($workflow ? 'workflow' : null),
+        ),
+        $name);
+    }
+
+    $hint = $this->getPolicyTypeHint();
+    if ($hint !== null) {
+      $name = pht('%s (%s)', $name, $hint);
+    }
+
+    return $name;
+  }
+
+  private function getPolicyTypeHint() {
+    $policy = $this->getPolicy();
+
+    if ($policy->isProjectPolicy()) {
+      return pht('Project');
+    }
+
+    if ($policy->isMaskedPolicy()) {
+      return pht('You do not have permission to view policy details.');
+    }
+
+    return null;
+  }
+
+}
diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
--- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
+++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
@@ -445,19 +445,15 @@
     $policy = PhabricatorPolicy::newFromPolicyAndHandle(
       $phid,
       $this->getHandleIfExists($phid));
+
+    $ref = $policy->newRef($this->getViewer());
+
     if ($this->renderingTarget == self::TARGET_HTML) {
-      switch ($policy->getType()) {
-        case PhabricatorPolicyType::TYPE_CUSTOM:
-          $policy->setHref('/transactions/'.$state.'/'.$this->getPHID().'/');
-          $policy->setWorkflow(true);
-          break;
-        default:
-          break;
-      }
-      $output = $policy->renderDescription();
+      $output = $ref->newTransactionLink($state, $this);
     } else {
-      $output = hsprintf('%s', $policy->getFullName());
+      $output = $ref->getPolicyDisplayName();
     }
+
     return $output;
   }
 
diff --git a/src/applications/transactions/storage/PhabricatorModularTransactionType.php b/src/applications/transactions/storage/PhabricatorModularTransactionType.php
--- a/src/applications/transactions/storage/PhabricatorModularTransactionType.php
+++ b/src/applications/transactions/storage/PhabricatorModularTransactionType.php
@@ -215,17 +215,16 @@
       $phid,
       $handles[$phid]);
 
-    if ($this->isTextMode()) {
-      return $this->renderValue($policy->getFullName());
-    }
+    $ref = $policy->newRef($viewer);
 
-    $storage = $this->getStorage();
-    if ($policy->getType() == PhabricatorPolicyType::TYPE_CUSTOM) {
-      $policy->setHref('/transactions/'.$mode.'/'.$storage->getPHID().'/');
-      $policy->setWorkflow(true);
+    if ($this->isTextMode()) {
+      $name = $ref->getPolicyDisplayName();
+    } else {
+      $storage = $this->getStorage();
+      $name = $ref->newTransactionLink($mode, $storage);
     }
 
-    return $this->renderValue($policy->renderDescription());
+    return $this->renderValue($name);
   }
 
   final protected function renderHandleList(array $phids) {
diff --git a/src/docs/user/userguide/unlocking.diviner b/src/docs/user/userguide/unlocking.diviner
--- a/src/docs/user/userguide/unlocking.diviner
+++ b/src/docs/user/userguide/unlocking.diviner
@@ -63,15 +63,22 @@
 Unlocking Objects
 =================
 
-If you aren't sure who owns an object, or no user account has access to an
-object, you can directly change object policies from the CLI:
+If you aren't sure who owns an object, you can inspect the policies from the
+CLI:
 
 ```
-$ ./bin/policy unlock <object> [--view ...] [--edit ...] [--owner ...]
+$ ./bin/policy show <object>
 ```
 
-To identify the object you want to unlock, you can specify an object name (like
-`T123`) or a PHID as the `<object>` parameter.
+To identify the object you want to examine, you can specify an object
+name (like `T123`) or a PHID as the `<object>` parameter.
+
+If examining the policy isn't helpful, or no user account has access to an
+object, you can then directly change object policies from the CLI:
+
+```
+$ ./bin/policy unlock <object> [--view ...] [--edit ...] [--owner ...]
+```
 
 Use the `--view` and `--edit` flags (and, for some objects, the `--owner`
 flag) to specify new policies for the object.