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
@@ -4617,6 +4617,7 @@
     'PhrictionDocumentHeraldAdapter' => 'applications/phriction/herald/PhrictionDocumentHeraldAdapter.php',
     'PhrictionDocumentHeraldField' => 'applications/phriction/herald/PhrictionDocumentHeraldField.php',
     'PhrictionDocumentHeraldFieldGroup' => 'applications/phriction/herald/PhrictionDocumentHeraldFieldGroup.php',
+    'PhrictionDocumentMoveToTransaction' => 'applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php',
     'PhrictionDocumentPHIDType' => 'applications/phriction/phid/PhrictionDocumentPHIDType.php',
     'PhrictionDocumentPathHeraldField' => 'applications/phriction/herald/PhrictionDocumentPathHeraldField.php',
     'PhrictionDocumentQuery' => 'applications/phriction/query/PhrictionDocumentQuery.php',
@@ -10256,6 +10257,7 @@
     'PhrictionDocumentHeraldAdapter' => 'HeraldAdapter',
     'PhrictionDocumentHeraldField' => 'HeraldField',
     'PhrictionDocumentHeraldFieldGroup' => 'HeraldFieldGroup',
+    'PhrictionDocumentMoveToTransaction' => 'PhrictionDocumentTransactionType',
     'PhrictionDocumentPHIDType' => 'PhabricatorPHIDType',
     'PhrictionDocumentPathHeraldField' => 'PhrictionDocumentHeraldField',
     'PhrictionDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
diff --git a/src/applications/phriction/controller/PhrictionMoveController.php b/src/applications/phriction/controller/PhrictionMoveController.php
--- a/src/applications/phriction/controller/PhrictionMoveController.php
+++ b/src/applications/phriction/controller/PhrictionMoveController.php
@@ -64,7 +64,8 @@
 
       $xactions = array();
       $xactions[] = id(new PhrictionTransaction())
-        ->setTransactionType(PhrictionTransaction::TYPE_MOVE_TO)
+        ->setTransactionType(
+          PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE)
         ->setNewValue($document);
       $target_document = id(new PhrictionDocumentQuery())
         ->setViewer(PhabricatorUser::getOmnipotentUser())
@@ -88,7 +89,8 @@
         return id(new AphrontRedirectResponse())->setURI($redir_uri);
       } catch (PhabricatorApplicationTransactionValidationException $ex) {
         $validation_exception = $ex;
-        $e_slug = $ex->getShortMessage(PhrictionTransaction::TYPE_MOVE_TO);
+        $e_slug = $ex->getShortMessage(
+          PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE);
       }
     }
 
diff --git a/src/applications/phriction/editor/PhrictionTransactionEditor.php b/src/applications/phriction/editor/PhrictionTransactionEditor.php
--- a/src/applications/phriction/editor/PhrictionTransactionEditor.php
+++ b/src/applications/phriction/editor/PhrictionTransactionEditor.php
@@ -82,7 +82,6 @@
 
     $types[] = PhrictionTransaction::TYPE_CONTENT;
     $types[] = PhrictionTransaction::TYPE_DELETE;
-    $types[] = PhrictionTransaction::TYPE_MOVE_TO;
     $types[] = PhrictionTransaction::TYPE_MOVE_AWAY;
 
     $types[] = PhabricatorTransactions::TYPE_EDGE;
@@ -104,7 +103,6 @@
         }
         return $this->getOldContent()->getContent();
       case PhrictionTransaction::TYPE_DELETE:
-      case PhrictionTransaction::TYPE_MOVE_TO:
       case PhrictionTransaction::TYPE_MOVE_AWAY:
         return null;
     }
@@ -118,17 +116,11 @@
       case PhrictionTransaction::TYPE_CONTENT:
       case PhrictionTransaction::TYPE_DELETE:
         return $xaction->getNewValue();
-      case PhrictionTransaction::TYPE_MOVE_TO:
+      case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
         $document = $xaction->getNewValue();
         // grab the real object now for the sub-editor to come
         $this->moveAwayDocument = $document;
-        $dict = array(
-          'id' => $document->getID(),
-          'phid' => $document->getPHID(),
-          'content' => $document->getContent()->getContent(),
-          'title' => $document->getContent()->getTitle(),
-        );
-        return $dict;
+        return;
       case PhrictionTransaction::TYPE_MOVE_AWAY:
         $document = $xaction->getNewValue();
         $dict = array(
@@ -150,7 +142,7 @@
       case PhrictionDocumentTitleTransaction::TRANSACTIONTYPE:
       case PhrictionTransaction::TYPE_CONTENT:
       case PhrictionTransaction::TYPE_DELETE:
-      case PhrictionTransaction::TYPE_MOVE_TO:
+      case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
       case PhrictionTransaction::TYPE_MOVE_AWAY:
         return true;
       }
@@ -172,9 +164,6 @@
 
     switch ($xaction->getTransactionType()) {
       case PhrictionTransaction::TYPE_CONTENT:
-      case PhrictionTransaction::TYPE_MOVE_TO:
-        $object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
-        return;
       case PhrictionTransaction::TYPE_MOVE_AWAY:
         $object->setStatus(PhrictionDocumentStatus::STATUS_MOVED);
         return;
@@ -202,7 +191,7 @@
             ->setMetadataValue('contentDelete', true);
         }
         break;
-      case PhrictionTransaction::TYPE_MOVE_TO:
+      case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
         $document = $xaction->getNewValue();
         $xactions[] = id(new PhrictionTransaction())
           ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
@@ -232,14 +221,6 @@
         $this->getNewContent()->setChangeType(
           PhrictionChangeType::CHANGE_DELETE);
         break;
-      case PhrictionTransaction::TYPE_MOVE_TO:
-        $dict = $xaction->getNewValue();
-        $this->getNewContent()->setContent($dict['content']);
-        $this->getNewContent()->setTitle($dict['title']);
-        $this->getNewContent()->setChangeType(
-          PhrictionChangeType::CHANGE_MOVE_HERE);
-        $this->getNewContent()->setChangeRef($dict['id']);
-        break;
       case PhrictionTransaction::TYPE_MOVE_AWAY:
         $dict = $xaction->getNewValue();
         $this->getNewContent()->setContent('');
@@ -263,7 +244,7 @@
         case PhrictionTransaction::TYPE_CONTENT:
         case PhrictionTransaction::TYPE_DELETE:
         case PhrictionTransaction::TYPE_MOVE_AWAY:
-        case PhrictionTransaction::TYPE_MOVE_TO:
+        case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
           $save_content = true;
           break;
         default:
@@ -448,7 +429,7 @@
 
     foreach ($xactions as $xaction) {
       switch ($xaction->getTransactionType()) {
-        case PhrictionTransaction::TYPE_MOVE_TO:
+        case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
           $dict = $xaction->getNewValue();
           $phids[] = $dict['phid'];
           break;
@@ -510,31 +491,8 @@
 
           break;
 
-        case PhrictionTransaction::TYPE_MOVE_TO:
+        case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
           $source_document = $xaction->getNewValue();
-          switch ($source_document->getStatus()) {
-            case PhrictionDocumentStatus::STATUS_DELETED:
-              $e_text = pht('A deleted document can not be moved.');
-              break;
-            case PhrictionDocumentStatus::STATUS_MOVED:
-              $e_text = pht('A moved document can not be moved again.');
-              break;
-            case PhrictionDocumentStatus::STATUS_STUB:
-              $e_text = pht('A stub document can not be moved.');
-              break;
-            default:
-              $e_text = null;
-              break;
-          }
-
-          if ($e_text) {
-            $error = new PhabricatorApplicationTransactionValidationError(
-              $type,
-              pht('Can not move document.'),
-              $e_text,
-              $xaction);
-            $errors[] = $error;
-          }
 
           $ancestry_errors = $this->validateAncestry(
             $object,
@@ -611,7 +569,7 @@
     return $errors;
   }
 
-  private function validateAncestry(
+  public function validateAncestry(
     PhabricatorLiskDAO $object,
     $type,
     PhabricatorApplicationTransaction $xaction,
diff --git a/src/applications/phriction/storage/PhrictionTransaction.php b/src/applications/phriction/storage/PhrictionTransaction.php
--- a/src/applications/phriction/storage/PhrictionTransaction.php
+++ b/src/applications/phriction/storage/PhrictionTransaction.php
@@ -5,7 +5,6 @@
 
   const TYPE_CONTENT = 'content';
   const TYPE_DELETE  = 'delete';
-  const TYPE_MOVE_TO = 'move-to';
   const TYPE_MOVE_AWAY = 'move-away';
 
   const MAILTAG_TITLE       = 'phriction-title';
@@ -34,7 +33,7 @@
     $phids = parent::getRequiredHandlePHIDs();
     $new = $this->getNewValue();
     switch ($this->getTransactionType()) {
-      case self::TYPE_MOVE_TO:
+      case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
       case self::TYPE_MOVE_AWAY:
         $phids[] = $new['phid'];
         break;
@@ -76,7 +75,7 @@
 
   public function shouldHideForMail(array $xactions) {
     switch ($this->getTransactionType()) {
-      case self::TYPE_MOVE_TO:
+      case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
       case self::TYPE_MOVE_AWAY:
         return true;
       case PhrictionDocumentTitleTransaction::TRANSACTIONTYPE:
@@ -87,7 +86,7 @@
 
   public function shouldHideForFeed() {
     switch ($this->getTransactionType()) {
-      case self::TYPE_MOVE_TO:
+      case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
       case self::TYPE_MOVE_AWAY:
         return true;
       case PhrictionDocumentTitleTransaction::TRANSACTIONTYPE:
@@ -102,7 +101,6 @@
         return 1.3;
       case self::TYPE_DELETE:
         return 1.5;
-      case self::TYPE_MOVE_TO:
       case self::TYPE_MOVE_AWAY:
         return 1.0;
     }
@@ -119,8 +117,6 @@
         return pht('Edited');
       case self::TYPE_DELETE:
         return pht('Deleted');
-      case self::TYPE_MOVE_TO:
-        return pht('Moved');
       case self::TYPE_MOVE_AWAY:
         return pht('Moved Away');
     }
@@ -137,7 +133,6 @@
         return 'fa-pencil';
       case self::TYPE_DELETE:
         return 'fa-times';
-      case self::TYPE_MOVE_TO:
       case self::TYPE_MOVE_AWAY:
         return 'fa-arrows';
     }
@@ -163,12 +158,6 @@
           '%s deleted this document.',
           $this->renderHandleLink($author_phid));
 
-      case self::TYPE_MOVE_TO:
-        return pht(
-          '%s moved this document from %s',
-          $this->renderHandleLink($author_phid),
-          $this->renderHandleLink($new['phid']));
-
       case self::TYPE_MOVE_AWAY:
         return pht(
           '%s moved this document to %s',
diff --git a/src/applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php b/src/applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php
@@ -0,0 +1,102 @@
+<?php
+
+final class PhrictionDocumentMoveToTransaction
+  extends PhrictionDocumentTransactionType {
+
+  const TRANSACTIONTYPE = 'move-to';
+
+  public function generateOldValue($object) {
+    return null;
+  }
+
+  public function generateNewValue($object, $value) {
+    $document = $value;
+    $dict = array(
+      'id' => $document->getID(),
+      'phid' => $document->getPHID(),
+      'content' => $document->getContent()->getContent(),
+      'title' => $document->getContent()->getTitle(),
+    );
+    return $dict;
+  }
+
+  public function applyInternalEffects($object, $value) {
+    $object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
+    $this->getEditor()->getNewContent()->setTitle($value);
+  }
+
+  public function applyExternalEffects($object, $value) {
+    $dict = $value;
+    $this->getEditor()->getNewContent()->setContent($dict['content']);
+    $this->getEditor()->getNewContent()->setTitle($dict['title']);
+    $this->getEditor()->getNewContent()->setChangeType(
+      PhrictionChangeType::CHANGE_MOVE_HERE);
+    $this->getEditor()->getNewContent()->setChangeRef($dict['id']);
+  }
+
+  public function getActionStrength() {
+    return 1.0;
+  }
+
+  public function getActionName() {
+    return pht('Moved');
+  }
+
+  public function getTitle() {
+    $old = $this->getOldValue();
+    $new = $this->getNewValue();
+
+    return pht(
+      '%s moved this document from %s',
+      $this->renderAuthor(),
+      $this->renderHandle($new['phid']));
+  }
+
+  public function getTitleForFeed() {
+    $old = $this->getOldValue();
+    $new = $this->getNewValue();
+
+    return pht(
+      '%s moved %s from %s',
+      $this->renderAuthor(),
+      $this->renderObject(),
+      $this->renderHandle($new['phid']));
+  }
+
+  public function validateTransactions($object, array $xactions) {
+    $errors = array();
+
+    $e_text = null;
+    foreach ($xactions as $xaction) {
+      $source_document = $xaction->getNewValue();
+      switch ($source_document->getStatus()) {
+        case PhrictionDocumentStatus::STATUS_DELETED:
+          $e_text = pht('A deleted document can not be moved.');
+          break;
+        case PhrictionDocumentStatus::STATUS_MOVED:
+          $e_text = pht('A moved document can not be moved again.');
+          break;
+        case PhrictionDocumentStatus::STATUS_STUB:
+          $e_text = pht('A stub document can not be moved.');
+          break;
+        default:
+          $e_text = null;
+          break;
+      }
+
+      if ($e_text !== null) {
+        $errors[] = $this->newInvalidError($e_text);
+      }
+
+    }
+
+    // TODO: Move Ancestry validation here once all types are converted.
+
+    return $errors;
+  }
+
+  public function getIcon() {
+    return 'fa-arrows';
+  }
+
+}