diff --git a/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php b/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php
index 4d31f39f02..cf13e8e5b2 100644
--- a/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php
@@ -1,58 +1,69 @@
 <?php
 
 final class DifferentialRevisionHoldDraftTransaction
   extends DifferentialRevisionTransactionType {
 
   const TRANSACTIONTYPE = 'draft';
   const EDITKEY = 'draft';
 
   public function generateOldValue($object) {
     return (bool)$object->getHoldAsDraft();
   }
 
   public function generateNewValue($object, $value) {
     return (bool)$value;
   }
 
   public function applyInternalEffects($object, $value) {
     $object->setHoldAsDraft($value);
 
     // If draft isn't the default state but we're creating a new revision
     // and holding it as a draft, put it in draft mode. See PHI206.
     // TODO: This can probably be removed once Draft is the universal default.
     if ($this->isNewObject()) {
       if ($object->isNeedsReview()) {
         $object
           ->setModernRevisionStatus(DifferentialRevisionStatus::DRAFT)
           ->setShouldBroadcast(false);
       }
     }
   }
 
   public function getTitle() {
     if ($this->getNewValue()) {
       return pht(
         '%s held this revision as a draft.',
         $this->renderAuthor());
     } else {
       return pht(
         '%s set this revision to automatically submit once builds complete.',
         $this->renderAuthor());
     }
   }
 
   public function getTitleForFeed() {
     if ($this->getNewValue()) {
       return pht(
         '%s held %s as a draft.',
         $this->renderAuthor(),
         $this->renderObject());
     } else {
       return pht(
         '%s set %s to automatically submit once builds complete.',
         $this->renderAuthor(),
         $this->renderObject());
     }
   }
 
+  public function getTransactionTypeForConduit($xaction) {
+    return 'draft';
+  }
+
+  public function getFieldValuesForConduit($xaction, $data) {
+    return array(
+      'old' => $xaction->getOldValue(),
+      'new' => $xaction->getNewValue(),
+    );
+  }
+
 }
diff --git a/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php
index 238eb53903..66b412ee9c 100644
--- a/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php
@@ -1,64 +1,75 @@
 <?php
 
 final class DifferentialRevisionSummaryTransaction
   extends DifferentialRevisionTransactionType {
 
   const TRANSACTIONTYPE = 'differential.revision.summary';
   const EDITKEY = 'summary';
 
   public function generateOldValue($object) {
     return $object->getSummary();
   }
 
   public function applyInternalEffects($object, $value) {
     $object->setSummary($value);
   }
 
   public function getTitle() {
     return pht(
       '%s edited the summary of this revision.',
       $this->renderAuthor());
   }
 
   public function getTitleForFeed() {
     return pht(
       '%s updated the summary of %s.',
       $this->renderAuthor(),
       $this->renderObject());
   }
 
   public function hasChangeDetailView() {
     return true;
   }
 
   public function getMailDiffSectionHeader() {
     return pht('CHANGES TO REVISION SUMMARY');
   }
 
   public function newChangeDetailView() {
     $viewer = $this->getViewer();
 
     return id(new PhabricatorApplicationTransactionTextDiffDetailView())
       ->setViewer($viewer)
       ->setOldText($this->getOldValue())
       ->setNewText($this->getNewValue());
   }
 
   public function newRemarkupChanges() {
     $changes = array();
 
     $changes[] = $this->newRemarkupChange()
       ->setOldValue($this->getOldValue())
       ->setNewValue($this->getNewValue());
 
     return $changes;
   }
 
   public function validateTransactions($object, array $xactions) {
     return $this->validateCommitMessageCorpusTransactions(
       $object,
       $xactions,
       pht('Summary'));
   }
 
+  public function getTransactionTypeForConduit($xaction) {
+    return 'summary';
+  }
+
+  public function getFieldValuesForConduit($xaction, $data) {
+    return array(
+      'old' => $xaction->getOldValue(),
+      'new' => $xaction->getNewValue(),
+    );
+  }
+
 }
diff --git a/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php
index c7c77fbcff..99837a09fa 100644
--- a/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php
@@ -1,78 +1,89 @@
 <?php
 
 final class DifferentialRevisionTestPlanTransaction
   extends DifferentialRevisionTransactionType {
 
   const TRANSACTIONTYPE = 'differential.revision.testplan';
   const EDITKEY = 'testPlan';
 
   public function generateOldValue($object) {
     return $object->getTestPlan();
   }
 
   public function applyInternalEffects($object, $value) {
     $object->setTestPlan($value);
   }
 
   public function getTitle() {
     return pht(
       '%s edited the test plan for this revision.',
       $this->renderAuthor());
   }
 
   public function getTitleForFeed() {
     return pht(
       '%s updated the test plan for %s.',
       $this->renderAuthor(),
       $this->renderObject());
   }
 
   public function hasChangeDetailView() {
     return true;
   }
 
   public function getMailDiffSectionHeader() {
     return pht('CHANGES TO TEST PLAN');
   }
 
   public function newChangeDetailView() {
     $viewer = $this->getViewer();
 
     return id(new PhabricatorApplicationTransactionTextDiffDetailView())
       ->setViewer($viewer)
       ->setOldText($this->getOldValue())
       ->setNewText($this->getNewValue());
   }
 
   public function newRemarkupChanges() {
     $changes = array();
 
     $changes[] = $this->newRemarkupChange()
       ->setOldValue($this->getOldValue())
       ->setNewValue($this->getNewValue());
 
     return $changes;
   }
 
   public function validateTransactions($object, array $xactions) {
     $errors = $this->validateCommitMessageCorpusTransactions(
       $object,
       $xactions,
       pht('Test Plan'));
 
     $is_required = PhabricatorEnv::getEnvConfig(
       'differential.require-test-plan-field');
 
     if ($is_required) {
       if ($this->isEmptyTextTransaction($object->getTestPlan(), $xactions)) {
         $errors[] = $this->newRequiredError(
           pht(
             'You must provide a test plan. Describe the actions you '.
             'performed to verify the behavior of this change.'));
       }
     }
 
     return $errors;
   }
 
+  public function getTransactionTypeForConduit($xaction) {
+    return 'testPlan';
+  }
+
+  public function getFieldValuesForConduit($xaction, $data) {
+    return array(
+      'old' => $xaction->getOldValue(),
+      'new' => $xaction->getNewValue(),
+    );
+  }
+
 }
diff --git a/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php
index 812464b26d..50d00e1892 100644
--- a/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php
@@ -1,69 +1,69 @@
 <?php
 
 final class DifferentialRevisionTitleTransaction
   extends DifferentialRevisionTransactionType {
 
   const TRANSACTIONTYPE = 'differential.revision.title';
   const EDITKEY = 'title';
 
   public function generateOldValue($object) {
     return $object->getTitle();
   }
 
   public function applyInternalEffects($object, $value) {
     $object->setTitle($value);
   }
 
   public function getTitle() {
     return pht(
       '%s retitled this revision from %s to %s.',
       $this->renderAuthor(),
       $this->renderOldValue(),
       $this->renderNewValue());
   }
 
   public function getTitleForFeed() {
     return pht(
       '%s retitled %s from %s to %s.',
       $this->renderAuthor(),
       $this->renderObject(),
       $this->renderOldValue(),
       $this->renderNewValue());
   }
 
   public function validateTransactions($object, array $xactions) {
     $errors = array();
 
     if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) {
       $errors[] = $this->newRequiredError(
         pht('Revisions must have a title.'));
     }
 
     $max_length = $object->getColumnMaximumByteLength('title');
     foreach ($xactions as $xaction) {
       $new_value = $xaction->getNewValue();
       $new_length = strlen($new_value);
       if ($new_length > $max_length) {
         $errors[] = $this->newInvalidError(
           pht(
             'Revision title is too long: the maximum length of a '.
             'revision title is 255 bytes.'),
           $xaction);
       }
     }
 
     return $errors;
   }
 
   public function getTransactionTypeForConduit($xaction) {
     return 'title';
   }
 
-  public function getFieldValuesForConduit($object, $data) {
+  public function getFieldValuesForConduit($xaction, $data) {
     return array(
-      'old' => $object->getOldValue(),
-      'new' => $object->getNewValue(),
+      'old' => $xaction->getOldValue(),
+      'new' => $xaction->getNewValue(),
     );
   }
 
 }
diff --git a/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php b/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php
index 33bbaceb7e..ab544b1c68 100644
--- a/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php
@@ -1,238 +1,238 @@
 <?php
 
 final class DifferentialRevisionUpdateTransaction
   extends DifferentialRevisionTransactionType {
 
   const TRANSACTIONTYPE = 'differential:update';
   const EDITKEY = 'update';
 
   public function generateOldValue($object) {
     return $object->getActiveDiffPHID();
   }
 
   public function applyInternalEffects($object, $value) {
     $should_review = $this->shouldRequestReviewAfterUpdate($object);
     if ($should_review) {
       // If we're updating a non-broadcasting revision, put it back in draft
       // rather than moving it directly to "Needs Review".
       if ($object->getShouldBroadcast()) {
         $new_status = DifferentialRevisionStatus::NEEDS_REVIEW;
       } else {
         $new_status = DifferentialRevisionStatus::DRAFT;
       }
       $object->setModernRevisionStatus($new_status);
     }
 
     $editor = $this->getEditor();
     $diff = $editor->requireDiff($value);
 
     $this->updateRevisionLineCounts($object, $diff);
 
     $object->setRepositoryPHID($diff->getRepositoryPHID());
     $object->setActiveDiffPHID($diff->getPHID());
     $object->attachActiveDiff($diff);
   }
 
   private function shouldRequestReviewAfterUpdate($object) {
     if ($this->isCommitUpdate()) {
       return false;
     }
 
     $should_update =
       $object->isNeedsRevision() ||
       $object->isChangePlanned() ||
       $object->isAbandoned();
     if ($should_update) {
       return true;
     }
 
     return false;
   }
 
   public function applyExternalEffects($object, $value) {
     $editor = $this->getEditor();
     $diff = $editor->requireDiff($value);
 
     // TODO: This can race with diff updates, particularly those from
     // Harbormaster. See discussion in T8650.
     $diff->setRevisionID($object->getID());
     $diff->save();
   }
 
   public function didCommitTransaction($object, $value) {
     $editor = $this->getEditor();
     $diff = $editor->requireDiff($value);
     $omnipotent = PhabricatorUser::getOmnipotentUser();
 
     // If there are any outstanding buildables for this diff, tell
     // Harbormaster that their containers need to be updated. This is
     // common, because `arc` creates buildables so it can upload lint
     // and unit results.
 
     $buildables = id(new HarbormasterBuildableQuery())
       ->setViewer($omnipotent)
       ->withManualBuildables(false)
       ->withBuildablePHIDs(array($diff->getPHID()))
       ->execute();
     foreach ($buildables as $buildable) {
       $buildable->sendMessage(
         $this->getActor(),
         HarbormasterMessageType::BUILDABLE_CONTAINER,
         true);
     }
   }
 
   public function getColor() {
     return 'sky';
   }
 
   public function getIcon() {
     return 'fa-refresh';
   }
 
   public function getActionName() {
     if ($this->isCreateTransaction()) {
       return pht('Request');
     } else {
       return pht('Updated');
     }
   }
 
   public function getActionStrength() {
     return 2;
   }
 
   public function getTitle() {
     $old = $this->getOldValue();
     $new = $this->getNewValue();
 
     if ($this->isCommitUpdate()) {
       return pht(
         'This revision was automatically updated to reflect the '.
         'committed changes.');
     }
 
     // NOTE: Very, very old update transactions did not have a new value or
     // did not use a diff PHID as a new value. This was changed years ago,
     // but wasn't migrated. We might consider migrating if this causes issues.
 
     return pht(
       '%s updated this revision to %s.',
       $this->renderAuthor(),
       $this->renderNewHandle());
   }
 
   public function getTitleForFeed() {
     return pht(
       '%s updated the diff for %s.',
       $this->renderAuthor(),
       $this->renderObject());
   }
 
   public function validateTransactions($object, array $xactions) {
     $errors = array();
 
     $diff_phid = null;
     foreach ($xactions as $xaction) {
       $diff_phid = $xaction->getNewValue();
 
       $diff = id(new DifferentialDiffQuery())
         ->withPHIDs(array($diff_phid))
         ->setViewer($this->getActor())
         ->executeOne();
       if (!$diff) {
         $errors[] = $this->newInvalidError(
           pht(
             'Specified diff ("%s") does not exist.',
             $diff_phid),
           $xaction);
         continue;
       }
 
       $is_attached =
         ($diff->getRevisionID()) &&
         ($diff->getRevisionID() == $object->getID());
       if ($is_attached) {
         $is_active = ($diff_phid == $object->getActiveDiffPHID());
       } else {
         $is_active = false;
       }
 
       if ($is_attached) {
         if ($is_active) {
           // This is a no-op: we're reattaching the current active diff to the
           // revision it is already attached to. This is valid and will just
           // be dropped later on in the process.
         } else {
           // At least for now, there's no support for "undoing" a diff and
           // reverting to an older proposed change without just creating a
           // new diff from whole cloth.
           $errors[] = $this->newInvalidError(
             pht(
               'You can not update this revision with the specified diff '.
               '("%s") because this diff is already attached to the revision '.
               'as an older version of the change.',
               $diff_phid),
             $xaction);
           continue;
         }
       } else if ($diff->getRevisionID()) {
         $errors[] = $this->newInvalidError(
           pht(
             'You can not update this revision with the specified diff ("%s") '.
             'because the diff is already attached to another revision.',
             $diff_phid),
           $xaction);
         continue;
       }
     }
 
     if (!$diff_phid && !$object->getActiveDiffPHID()) {
       $errors[] = $this->newInvalidError(
         pht(
           'You must specify an initial diff when creating a revision.'));
     }
 
     return $errors;
   }
 
   public function isCommitUpdate() {
     return (bool)$this->getMetadataValue('isCommitUpdate');
   }
 
   private function updateRevisionLineCounts(
     DifferentialRevision $revision,
     DifferentialDiff $diff) {
 
     $revision->setLineCount($diff->getLineCount());
 
     $conn = $revision->establishConnection('r');
 
     $row = queryfx_one(
       $conn,
       'SELECT SUM(addLines) A, SUM(delLines) D FROM %T
         WHERE diffID = %d',
       id(new DifferentialChangeset())->getTableName(),
       $diff->getID());
 
     if ($row) {
       $revision->setAddedLineCount((int)$row['A']);
       $revision->setRemovedLineCount((int)$row['D']);
     }
   }
 
   public function getTransactionTypeForConduit($xaction) {
     return 'update';
   }
 
-  public function getFieldValuesForConduit($object, $data) {
-    $commit_phids = $object->getMetadataValue('commitPHIDs', array());
+  public function getFieldValuesForConduit($xaction, $data) {
+    $commit_phids = $xaction->getMetadataValue('commitPHIDs', array());
 
     return array(
-      'old' => $object->getOldValue(),
-      'new' => $object->getNewValue(),
+      'old' => $xaction->getOldValue(),
+      'new' => $xaction->getNewValue(),
       'commitPHIDs' => $commit_phids,
     );
   }
 
 }