Merge changes I5c65740d,I919cf96d,I8dc8281e,I770c7281,I3d98e55f, ...

* changes:
  OutputStreamQuery: Clone PSA for currentPatchSet
  OutputStreamQuery: Use AccountLoader for current patch set
  OutputStreamQuery: Nest RevWalk using options under existing condition
  OutputStreamQuery: Lazy load labelTypes
  OutputStreamQuery: Add patchset comments when adding patchsets
  OutputStreamQuery: Remove duplicate addPatchSets()
  EventFactory: Re-use revwalk for loading ChangeKindCache
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
index 7b3d1bc..5f1a982 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
@@ -95,13 +95,15 @@
     PushOneCommit.Result change2 = createChange();
 
     Change.Id id1 = change1.getPatchSetId().changeId();
+    Change.Id id2 = change2.getPatchSetId().changeId();
     submitWithConflict(
         change2.getChangeId(),
-        "Failed to submit 2 changes due to the following problems:\n"
-            + "Change "
-            + id1
-            + ": Change 8 must be submitted with change 7 but 7 is not ready: "
-            + "submit requirement 'Code-Review' is unsatisfied.");
+        String.format(
+            "Failed to submit 2 changes due to the following problems:\n"
+                + "Change %d"
+                + ": Change %d must be submitted with change %d but %d is not ready: "
+                + "submit requirement 'Code-Review' is unsatisfied.",
+            id1.get(), id2.get(), id1.get(), id1.get()));
 
     RevCommit updatedHead = projectOperations.project(project).getHead("master");
     assertThat(updatedHead.getId()).isEqualTo(initialHead.getId());
diff --git a/plugins/hooks b/plugins/hooks
index 41c3ad1..4f43f5d 160000
--- a/plugins/hooks
+++ b/plugins/hooks
@@ -1 +1 @@
-Subproject commit 41c3ad1d584f3b81bacc59e89e022dc1e7ffc3f2
+Subproject commit 4f43f5db6b8aa7f36381f4f9a4c9ec1fc335d949
diff --git a/plugins/replication b/plugins/replication
index cc32fe2..6b4bc77 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit cc32fe20832ea07c3a3388e87df777258686e5d5
+Subproject commit 6b4bc775bfabf8cc1862443b67a247731a79bcf1
diff --git a/polygerrit-ui/app/api/plugin.ts b/polygerrit-ui/app/api/plugin.ts
index 8630f75..c595add 100644
--- a/polygerrit-ui/app/api/plugin.ts
+++ b/polygerrit-ui/app/api/plugin.ts
@@ -9,6 +9,7 @@
 import {ChangeReplyPluginApi} from './change-reply';
 import {ChecksPluginApi} from './checks';
 import {EventHelperPluginApi} from './event-helper';
+import {PluginElement} from './hook';
 import {PopupPluginApi} from './popup';
 import {ReportingPluginApi} from './reporting';
 import {ChangeActionsPluginApi} from './change-actions';
@@ -63,7 +64,7 @@
   suggestions(): SuggestionsPluginApi;
   eventHelper(element: Node): EventHelperPluginApi;
   getPluginName(): string;
-  hook<T extends HTMLElement>(
+  hook<T extends PluginElement>(
     endpointName: string,
     opt_options?: RegisterOptions
   ): HookApi<T>;
@@ -72,12 +73,12 @@
   popup(): Promise<PopupPluginApi>;
   popup(moduleName: string): Promise<PopupPluginApi>;
   popup(moduleName?: string): Promise<PopupPluginApi | null>;
-  registerCustomComponent<T extends HTMLElement>(
+  registerCustomComponent<T extends PluginElement>(
     endpointName: string,
     moduleName?: string,
     options?: RegisterOptions
   ): HookApi<T>;
-  registerDynamicCustomComponent<T extends HTMLElement>(
+  registerDynamicCustomComponent<T extends PluginElement>(
     endpointName: string,
     moduleName?: string,
     options?: RegisterOptions