diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml
index 9f2f1d9036fd0c5e2a5e73e4ede8e9f6e1fbf5b4..38de671385ec67c3dd96ccb7fd1294b9663032e2 100644
--- a/automatic_updates.services.yml
+++ b/automatic_updates.services.yml
@@ -12,21 +12,9 @@ services:
     arguments:
       - '@state'
       - '@string_translation'
-      - '@package_manager.beginner'
-      - '@package_manager.stager'
-      - '@package_manager.cleaner'
-      - '@package_manager.committer'
       - '@event_dispatcher'
-      - '@automatic_updates.path_locator'
-  automatic_updates.cleaner:
-    class: Drupal\automatic_updates\ComposerStager\Cleaner
-    decorates: package_manager.cleaner
-    public: false
-    arguments:
-      - '@automatic_updates.cleaner.inner'
-      - '%site.path%'
-      - '@automatic_updates.path_locator'
-    properties: { _serviceId: package_manager.cleaner }
+      - '@package_manager.path_locator'
+      - '@package_manager.stage'
   automatic_updates.update_refresh_subscriber:
     class: Drupal\automatic_updates\Event\UpdateRefreshSubscriber
     arguments:
diff --git a/package_manager/package_manager.services.yml b/package_manager/package_manager.services.yml
index 40bb06838dc43814e71619d87efb9ce195b4125d..41deacfbde761f9c6cb50b730007058019e8b93a 100644
--- a/package_manager/package_manager.services.yml
+++ b/package_manager/package_manager.services.yml
@@ -74,6 +74,23 @@ services:
       - '@package_manager.file_syncer'
       - '@package_manager.file_system'
   package_manager.cleaner:
-    class: PhpTuf\ComposerStager\Domain\Cleaner
+    class: Drupal\package_manager\Cleaner
     arguments:
       - '@package_manager.file_system'
+      - '%site.path%'
+      - '@package_manager.path_locator'
+  package_manager.path_locator:
+    class: Drupal\package_manager\PathLocator
+    arguments:
+      - '@config.factory'
+      - '%app.root%'
+
+  # Public API.
+  package_manager.stage:
+    class: Drupal\package_manager\Stage
+    arguments:
+      - '@package_manager.path_locator'
+      - '@package_manager.beginner'
+      - '@package_manager.stager'
+      - '@package_manager.committer'
+      - '@package_manager.cleaner'
diff --git a/src/ComposerStager/Cleaner.php b/package_manager/src/Cleaner.php
similarity index 71%
rename from src/ComposerStager/Cleaner.php
rename to package_manager/src/Cleaner.php
index 22ddac8e0dd214b400161907466cc111b56100f3..e920c259ae2b9df8080b99e1f2149dd8562fe813 100644
--- a/src/ComposerStager/Cleaner.php
+++ b/package_manager/src/Cleaner.php
@@ -1,10 +1,11 @@
 <?php
 
-namespace Drupal\automatic_updates\ComposerStager;
+namespace Drupal\package_manager;
 
-use Drupal\automatic_updates\PathLocator;
+use PhpTuf\ComposerStager\Domain\Cleaner as StagerCleaner;
 use PhpTuf\ComposerStager\Domain\CleanerInterface;
 use PhpTuf\ComposerStager\Domain\Output\ProcessOutputCallbackInterface;
+use PhpTuf\ComposerStager\Infrastructure\Filesystem\FilesystemInterface;
 use Symfony\Component\Filesystem\Filesystem;
 
 /**
@@ -29,25 +30,25 @@ class Cleaner implements CleanerInterface {
   /**
    * The path locator service.
    *
-   * @var \Drupal\automatic_updates\PathLocator
+   * @var \Drupal\package_manager\PathLocator
    */
   protected $pathLocator;
 
   /**
    * Constructs a Cleaner object.
    *
-   * @param \PhpTuf\ComposerStager\Domain\CleanerInterface $decorated
-   *   The decorated cleaner service.
+   * @param \PhpTuf\ComposerStager\Infrastructure\Filesystem\FilesystemInterface $file_system
+   *   The file system service from Composer Stager.
    * @param string $site_path
    *   The current site path (e.g., 'sites/default'), without leading or
    *   trailing slashes.
-   * @param \Drupal\automatic_updates\PathLocator $locator
+   * @param \Drupal\package_manager\PathLocator $path_locator
    *   The path locator service.
    */
-  public function __construct(CleanerInterface $decorated, string $site_path, PathLocator $locator) {
-    $this->decorated = $decorated;
+  public function __construct(FilesystemInterface $file_system, string $site_path, PathLocator $path_locator) {
+    $this->decorated = new StagerCleaner($file_system);
     $this->sitePath = $site_path;
-    $this->pathLocator = $locator;
+    $this->pathLocator = $path_locator;
   }
 
   /**
diff --git a/package_manager/src/PathLocator.php b/package_manager/src/PathLocator.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae28ee005cd88a545b164a633e34633a843ec845
--- /dev/null
+++ b/package_manager/src/PathLocator.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace Drupal\package_manager;
+
+use Composer\Autoload\ClassLoader;
+use Drupal\Component\FileSystem\FileSystem;
+use Drupal\Core\Config\ConfigFactoryInterface;
+
+/**
+ * Computes file system paths that are needed to stage code changes.
+ */
+class PathLocator {
+
+  /**
+   * The config factory service.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * The absolute path of the running Drupal code base.
+   *
+   * @var string
+   */
+  protected $appRoot;
+
+  /**
+   * Constructs a PathLocator object.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory service.
+   * @param string $app_root
+   *   The absolute path of the running Drupal code base.
+   */
+  public function __construct(ConfigFactoryInterface $config_factory, string $app_root) {
+    $this->configFactory = $config_factory;
+    $this->appRoot = $app_root;
+  }
+
+  /**
+   * Returns the path of the active code base.
+   *
+   * @return string
+   *   The absolute path of the active, running code base.
+   */
+  public function getActiveDirectory(): string {
+    return $this->getProjectRoot();
+  }
+
+  /**
+   * Returns the path of the directory where changes should be staged.
+   *
+   * This directory may be made world-writeable for clean-up, so it should be
+   * somewhere that doesn't put the Drupal installation at risk.
+   *
+   * @return string
+   *   The absolute path of the directory where changes should be staged.
+   */
+  public function getStageDirectory(): string {
+    // Append the site ID to the directory in order to support parallel test
+    // runs, or multiple sites hosted on the same server.
+    $site_id = $this->configFactory->get('system.site')->get('uuid');
+    return FileSystem::getOsTemporaryDirectory() . DIRECTORY_SEPARATOR . '.package_manager_' . $site_id;
+  }
+
+  /**
+   * Returns the absolute path of the project root.
+   *
+   * This is where the project-level composer.json should normally be found, and
+   * may or may not be the same path as the Drupal code base.
+   *
+   * @return string
+   *   The absolute path of the project root.
+   */
+  public function getProjectRoot(): string {
+    // Assume that the vendor directory is immediately below the project root.
+    return realpath($this->getVendorDirectory() . DIRECTORY_SEPARATOR . '..');
+  }
+
+  /**
+   * Returns the absolute path of the vendor directory.
+   *
+   * @return string
+   *   The absolute path of the vendor directory.
+   */
+  public function getVendorDirectory(): string {
+    $reflector = new \ReflectionClass(ClassLoader::class);
+    return dirname($reflector->getFileName(), 2);
+  }
+
+  /**
+   * Returns the path of the Drupal installation, relative to the project root.
+   *
+   * @return string
+   *   The path of the Drupal installation, relative to the project root and
+   *   without leading or trailing slashes. Will return an empty string if the
+   *   project root and Drupal root are the same.
+   */
+  public function getWebRoot(): string {
+    $web_root = str_replace($this->getProjectRoot(), NULL, $this->appRoot);
+    return trim($web_root, DIRECTORY_SEPARATOR);
+  }
+
+}
diff --git a/package_manager/src/Stage.php b/package_manager/src/Stage.php
new file mode 100644
index 0000000000000000000000000000000000000000..d3a84009b5b16e023d88ccee9eee63ede43c9313
--- /dev/null
+++ b/package_manager/src/Stage.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Drupal\package_manager;
+
+use PhpTuf\ComposerStager\Domain\BeginnerInterface;
+use PhpTuf\ComposerStager\Domain\CleanerInterface;
+use PhpTuf\ComposerStager\Domain\CommitterInterface;
+use PhpTuf\ComposerStager\Domain\StagerInterface;
+
+/**
+ * Creates and manages a staging area in which to install or update code.
+ *
+ * Allows calling code to copy the current Drupal site into a temporary staging
+ * directory, use Composer to require packages into it, sync changes from the
+ * staging directory back into the active code base, and then delete the
+ * staging directory.
+ */
+class Stage {
+
+  /**
+   * The path locator service.
+   *
+   * @var \Drupal\package_manager\PathLocator
+   */
+  protected $pathLocator;
+
+  /**
+   * The beginner service from Composer Stager.
+   *
+   * @var \PhpTuf\ComposerStager\Domain\BeginnerInterface
+   */
+  protected $beginner;
+
+  /**
+   * The stager service from Composer Stager.
+   *
+   * @var \PhpTuf\ComposerStager\Domain\StagerInterface
+   */
+  protected $stager;
+
+  /**
+   * The committer service from Composer Stager.
+   *
+   * @var \PhpTuf\ComposerStager\Domain\CommitterInterface
+   */
+  protected $committer;
+
+  /**
+   * The cleaner service from Composer Stager.
+   *
+   * @var \PhpTuf\ComposerStager\Domain\CleanerInterface
+   */
+  protected $cleaner;
+
+  /**
+   * Constructs a new Stage object.
+   *
+   * @param \Drupal\package_manager\PathLocator $path_locator
+   *   The path locator service.
+   * @param \PhpTuf\ComposerStager\Domain\BeginnerInterface $beginner
+   *   The beginner service from Composer Stager.
+   * @param \PhpTuf\ComposerStager\Domain\StagerInterface $stager
+   *   The stager service from Composer Stager.
+   * @param \PhpTuf\ComposerStager\Domain\CommitterInterface $committer
+   *   The committer service from Composer Stager.
+   * @param \PhpTuf\ComposerStager\Domain\CleanerInterface $cleaner
+   *   The cleaner service from Composer Stager.
+   */
+  public function __construct(PathLocator $path_locator, BeginnerInterface $beginner, StagerInterface $stager, CommitterInterface $committer, CleanerInterface $cleaner) {
+    $this->pathLocator = $path_locator;
+    $this->beginner = $beginner;
+    $this->stager = $stager;
+    $this->committer = $committer;
+    $this->cleaner = $cleaner;
+  }
+
+  /**
+   * Copies the active code base into the staging area.
+   *
+   * @param array|null $exclusions
+   *   Paths to exclude from being copied into the staging area.
+   *
+   * @todo Remove the $exclusions parameter when this method fires events.
+   */
+  public function create(?array $exclusions = []): void {
+    $active_dir = $this->pathLocator->getActiveDirectory();
+    $stage_dir = $this->pathLocator->getStageDirectory();
+    $this->beginner->begin($active_dir, $stage_dir, $exclusions);
+  }
+
+  /**
+   * Requires packages in the staging area.
+   *
+   * @param string[] $constraints
+   *   The packages to require, in the form 'vendor/name:version'.
+   */
+  public function require(array $constraints): void {
+    $command = array_merge(['require'], $constraints);
+    $command[] = '--update-with-all-dependencies';
+    $this->stager->stage($command, $this->pathLocator->getStageDirectory());
+  }
+
+  /**
+   * Applies staged changes to the active directory.
+   *
+   * @param array|null $exclusions
+   *   Paths to exclude from being copied into the active directory.
+   *
+   * @todo Remove the $exclusions parameter when this method fires events.
+   */
+  public function apply(?array $exclusions = []): void {
+    $active_dir = $this->pathLocator->getActiveDirectory();
+    $stage_dir = $this->pathLocator->getStageDirectory();
+    $this->committer->commit($stage_dir, $active_dir, $exclusions);
+  }
+
+  /**
+   * Deletes the staging area.
+   */
+  public function destroy(): void {
+    $stage_dir = $this->pathLocator->getStageDirectory();
+    if (is_dir($stage_dir)) {
+      $this->cleaner->clean($stage_dir);
+    }
+  }
+
+}
diff --git a/src/ComposerStager/README.txt b/src/ComposerStager/README.txt
deleted file mode 100644
index f17637771ad20b171109c56ba1ed6c69d48e1d91..0000000000000000000000000000000000000000
--- a/src/ComposerStager/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-In a perfect world we would not need these classes and we would options in composer_stager not need the overrides.
-@todo Make issues in composer_stager.
diff --git a/src/PathLocator.php b/src/PathLocator.php
index dfc56c412ef86d4e9f475f3b24313da0f7a4a02b..3ba735edadf0106dcf26d01a8d9e2227d35820e5 100644
--- a/src/PathLocator.php
+++ b/src/PathLocator.php
@@ -2,106 +2,10 @@
 
 namespace Drupal\automatic_updates;
 
-use Composer\Autoload\ClassLoader;
-use Drupal\Component\FileSystem\FileSystem;
-use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\package_manager\PathLocator as PackageManagerPathLocator;
 
 /**
  * Computes file system paths that are needed for automatic updates.
  */
-class PathLocator {
-
-  /**
-   * The config factory service.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
-   */
-  protected $configFactory;
-
-  /**
-   * The absolute path of the running Drupal code base.
-   *
-   * @var string
-   */
-  protected $appRoot;
-
-  /**
-   * Constructs a PathLocator object.
-   *
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The config factory service.
-   * @param string $app_root
-   *   The absolute path of the running Drupal code base.
-   */
-  public function __construct(ConfigFactoryInterface $config_factory, string $app_root) {
-    $this->configFactory = $config_factory;
-    $this->appRoot = $app_root;
-  }
-
-  /**
-   * Returns the path of the active directory, which should be updated.
-   *
-   * @return string
-   *   The absolute path which should be updated.
-   */
-  public function getActiveDirectory(): string {
-    return $this->getProjectRoot();
-  }
-
-  /**
-   * Returns the path of the directory where updates should be staged.
-   *
-   * This directory may be made world-writeable for clean-up, so it should be
-   * somewhere that doesn't put the Drupal installation at risk.
-   *
-   * @return string
-   *   The absolute path of the directory where updates should be staged.
-   *
-   * @see \Drupal\automatic_updates\ComposerStager\Cleaner::clean()
-   */
-  public function getStageDirectory(): string {
-    // Append the site ID to the directory in order to support parallel test
-    // runs, or multiple sites hosted on the same server.
-    $site_id = $this->configFactory->get('system.site')->get('uuid');
-    return FileSystem::getOsTemporaryDirectory() . DIRECTORY_SEPARATOR . '.automatic_updates_stage_' . $site_id;
-  }
-
-  /**
-   * Returns the absolute path of the project root.
-   *
-   * This is where the project-level composer.json should normally be found, and
-   * may or may not be the same path as the Drupal code base.
-   *
-   * @return string
-   *   The absolute path of the project root.
-   */
-  public function getProjectRoot(): string {
-    // Assume that the vendor directory is immediately below the project root.
-    return realpath($this->getVendorDirectory() . DIRECTORY_SEPARATOR . '..');
-  }
-
-  /**
-   * Returns the absolute path of the vendor directory.
-   *
-   * @return string
-   *   The absolute path of the vendor directory.
-   */
-  public function getVendorDirectory(): string {
-    $reflector = new \ReflectionClass(ClassLoader::class);
-    return dirname($reflector->getFileName(), 2);
-  }
-
-  /**
-   * Returns the path of the Drupal installation, relative to the project root.
-   *
-   * @return string
-   *   The path of the Drupal installation, relative to the project root and
-   *   without leading or trailing slashes. Will return an empty string if the
-   *   project root and Drupal root are the same.
-   */
-  public function getWebRoot(): string {
-    $web_root = str_replace($this->getProjectRoot(), NULL, $this->appRoot);
-    return trim($web_root, DIRECTORY_SEPARATOR);
-  }
-
+class PathLocator extends PackageManagerPathLocator {
 }
diff --git a/src/Updater.php b/src/Updater.php
index 4cb0b90a644156660ff6df0249978c207446d5c5..66158618d1f90aea100134011affea7676661c1b 100644
--- a/src/Updater.php
+++ b/src/Updater.php
@@ -10,11 +10,9 @@ use Drupal\Core\State\StateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\package_manager\ComposerUtility;
+use Drupal\package_manager\PathLocator as PackageManagerPathLocator;
+use Drupal\package_manager\Stage;
 use Drupal\system\SystemManager;
-use PhpTuf\ComposerStager\Domain\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\CleanerInterface;
-use PhpTuf\ComposerStager\Domain\CommitterInterface;
-use PhpTuf\ComposerStager\Domain\StagerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 /**
@@ -31,34 +29,6 @@ class Updater {
    */
   public const STATE_KEY = 'AUTOMATIC_UPDATES_CURRENT';
 
-  /**
-   * The composer_stager beginner service.
-   *
-   * @var \Drupal\automatic_updates\ComposerStager\Beginner
-   */
-  protected $beginner;
-
-  /**
-   * The composer_stager stager service.
-   *
-   * @var \PhpTuf\ComposerStager\Domain\StagerInterface
-   */
-  protected $stager;
-
-  /**
-   * The composer_stager cleaner service.
-   *
-   * @var \PhpTuf\ComposerStager\Domain\CleanerInterface
-   */
-  protected $cleaner;
-
-  /**
-   * The composer_stager committer service.
-   *
-   * @var \PhpTuf\ComposerStager\Domain\CommitterInterface
-   */
-  protected $committer;
-
   /**
    * The state service.
    *
@@ -76,10 +46,17 @@ class Updater {
   /**
    * The path locator service.
    *
-   * @var \Drupal\automatic_updates\PathLocator
+   * @var \Drupal\package_manager\PathLocator
    */
   protected $pathLocator;
 
+  /**
+   * The stage service.
+   *
+   * @var \Drupal\package_manager\Stage
+   */
+  protected $stage;
+
   /**
    * Constructs an Updater object.
    *
@@ -87,28 +64,19 @@ class Updater {
    *   The state service.
    * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
    *   The string translation service.
-   * @param \PhpTuf\ComposerStager\Domain\BeginnerInterface $beginner
-   *   The Composer Stager's beginner service.
-   * @param \PhpTuf\ComposerStager\Domain\StagerInterface $stager
-   *   The Composer Stager's stager service.
-   * @param \PhpTuf\ComposerStager\Domain\CleanerInterface $cleaner
-   *   The Composer Stager's cleaner service.
-   * @param \PhpTuf\ComposerStager\Domain\CommitterInterface $committer
-   *   The Composer Stager's committer service.
    * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
    *   The event dispatcher service.
-   * @param \Drupal\automatic_updates\PathLocator $path_locator
+   * @param \Drupal\package_manager\PathLocator $path_locator
    *   The path locator service.
+   * @param \Drupal\package_manager\Stage $stage
+   *   The stage service.
    */
-  public function __construct(StateInterface $state, TranslationInterface $translation, BeginnerInterface $beginner, StagerInterface $stager, CleanerInterface $cleaner, CommitterInterface $committer, EventDispatcherInterface $event_dispatcher, PathLocator $path_locator) {
+  public function __construct(StateInterface $state, TranslationInterface $translation, EventDispatcherInterface $event_dispatcher, PackageManagerPathLocator $path_locator, Stage $stage) {
     $this->state = $state;
-    $this->beginner = $beginner;
-    $this->stager = $stager;
-    $this->cleaner = $cleaner;
-    $this->committer = $committer;
     $this->setStringTranslation($translation);
     $this->eventDispatcher = $event_dispatcher;
     $this->pathLocator = $path_locator;
+    $this->stage = $stage;
   }
 
   /**
@@ -150,7 +118,7 @@ class Updater {
     $stage_key = $this->createActiveStage($packages);
     /** @var \Drupal\automatic_updates\Event\PreStartEvent $event */
     $event = $this->dispatchUpdateEvent(new PreStartEvent($composer, $packages), AutomaticUpdatesEvents::PRE_START);
-    $this->beginner->begin($this->pathLocator->getActiveDirectory(), $this->pathLocator->getStageDirectory(), $this->getExclusions($event));
+    $this->stage->create($this->getExclusions($event));
     return $stage_key;
   }
 
@@ -175,19 +143,7 @@ class Updater {
    */
   public function stage(): void {
     $current = $this->state->get(static::STATE_KEY);
-    $this->stagePackages($current['package_versions']);
-  }
-
-  /**
-   * Installs Composer packages in the staging area.
-   *
-   * @param string[] $packages
-   *   The versions of the packages to stage, keyed by package name.
-   */
-  protected function stagePackages(array $packages): void {
-    $command = array_merge(['require'], $packages);
-    $command[] = '--update-with-all-dependencies';
-    $this->stageCommand($command);
+    $this->stage->require($current['package_versions']);
   }
 
   /**
@@ -202,7 +158,7 @@ class Updater {
 
     /** @var \Drupal\automatic_updates\Event\PreCommitEvent $event */
     $event = $this->dispatchUpdateEvent(new PreCommitEvent($active_composer, $stage_composer), AutomaticUpdatesEvents::PRE_COMMIT);
-    $this->committer->commit($stage_dir, $active_dir, $this->getExclusions($event));
+    $this->stage->apply($this->getExclusions($event));
     $this->dispatchUpdateEvent(new UpdateEvent($active_composer), AutomaticUpdatesEvents::POST_COMMIT);
   }
 
@@ -210,26 +166,10 @@ class Updater {
    * Cleans the current update.
    */
   public function clean(): void {
-    $stage_dir = $this->pathLocator->getStageDirectory();
-    if (is_dir($stage_dir)) {
-      $this->cleaner->clean($stage_dir);
-    }
+    $this->stage->destroy();
     $this->state->delete(static::STATE_KEY);
   }
 
-  /**
-   * Stages a Composer command.
-   *
-   * @param string[] $command
-   *   The command array as expected by
-   *   \PhpTuf\ComposerStager\Domain\StagerInterface::stage().
-   *
-   * @see \PhpTuf\ComposerStager\Domain\StagerInterface::stage()
-   */
-  protected function stageCommand(array $command): void {
-    $this->stager->stage($command, $this->pathLocator->getStageDirectory());
-  }
-
   /**
    * Initializes an active update and returns its ID.
    *
diff --git a/tests/src/Functional/FileSystemOperationsTest.php b/tests/src/Functional/FileSystemOperationsTest.php
index 5fce64a3862f21abb0e99a9cef50306d05a7a6d6..1e821229b44d4edf52e32c327b609c9670710ebb 100644
--- a/tests/src/Functional/FileSystemOperationsTest.php
+++ b/tests/src/Functional/FileSystemOperationsTest.php
@@ -2,10 +2,11 @@
 
 namespace Drupal\Tests\automatic_updates\Functional;
 
-use Drupal\automatic_updates\ComposerStager\Cleaner;
-use Drupal\automatic_updates\PathLocator;
+use Drupal\package_manager\Cleaner;
 use Drupal\automatic_updates\Updater;
 use Drupal\Core\Site\Settings;
+use Drupal\package_manager\PathLocator;
+use Drupal\package_manager\Stage;
 
 /**
  * Tests handling of files and directories during an update.
@@ -64,20 +65,25 @@ class FileSystemOperationsTest extends AutomaticUpdatesFunctionalTestBase {
     // will otherwise default to the site path being used for the test site,
     // which doesn't exist in the fake site fixture.
     $cleaner = new Cleaner(
-      $this->container->get('package_manager.cleaner'),
+      $this->container->get('package_manager.file_system'),
       'sites/default',
       $locator->reveal()
     );
 
-    $this->updater = new Updater(
-      $this->container->get('state'),
-      $this->container->get('string_translation'),
+    $stage = new Stage(
+      $locator->reveal(),
       $this->container->get('package_manager.beginner'),
       $this->container->get('package_manager.stager'),
-      $cleaner,
       $this->container->get('package_manager.committer'),
+      $cleaner
+    );
+
+    $this->updater = new Updater(
+      $this->container->get('state'),
+      $this->container->get('string_translation'),
       $this->container->get('event_dispatcher'),
-      $locator->reveal()
+      $locator->reveal(),
+      $stage
     );
 
     // Use the public and private files directories in the fake site fixture.
diff --git a/tests/src/Kernel/UpdaterTest.php b/tests/src/Kernel/UpdaterTest.php
index d6bd48448f9443d875f26c360cd25a7e3ae26a26..ed9eeb51df89f98756f3b9df7e7ea36708f05b52 100644
--- a/tests/src/Kernel/UpdaterTest.php
+++ b/tests/src/Kernel/UpdaterTest.php
@@ -3,7 +3,6 @@
 namespace Drupal\Tests\automatic_updates\Kernel;
 
 use Drupal\automatic_updates\PathLocator;
-use Prophecy\Argument;
 
 /**
  * @coversDefaultClass \Drupal\automatic_updates\Updater
@@ -34,7 +33,7 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase {
     $locator = $this->prophesize(PathLocator::class);
     $locator->getActiveDirectory()->willReturn(__DIR__ . '/../../fixtures/fake-site');
     $locator->getStageDirectory()->willReturn('/tmp');
-    $this->container->set('automatic_updates.path_locator', $locator->reveal());
+    $this->container->set('package_manager.path_locator', $locator->reveal());
 
     $this->container->get('automatic_updates.updater')->begin([
       'drupal' => '9.8.1',
@@ -44,14 +43,9 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase {
     $kernel = $this->container->get('kernel');
     $kernel->rebuildContainer();
     $this->container = $kernel->getContainer();
-    $stager = $this->prophesize('\PhpTuf\ComposerStager\Domain\StagerInterface');
-    $command = [
-      'require',
-      'drupal/core-recommended:9.8.1',
-      '--update-with-all-dependencies',
-    ];
-    $stager->stage($command, Argument::cetera())->shouldBeCalled();
-    $this->container->set('package_manager.stager', $stager->reveal());
+    $stage = $this->prophesize('\Drupal\package_manager\Stage');
+    $stage->require(['drupal/core-recommended:9.8.1'])->shouldBeCalled();
+    $this->container->set('package_manager.stage', $stage->reveal());
     $this->container->get('automatic_updates.updater')->stage();
   }