From 99a864a0d1983430d1a98db23aeacea430cd8ff9 Mon Sep 17 00:00:00 2001
From: Adam G-H <32250-phenaproxima@users.noreply.drupalcode.org>
Date: Fri, 7 Jul 2023 17:13:58 +0000
Subject: [PATCH] Issue #3372673 by phenaproxima, tedbow: Update Composer
 Stager to 2.0.0-alpha4 to pave the way for translatability

---
 automatic_updates.services.yml                | 18 +-------
 .../src/ExtensionUpdateStage.php              | 16 +++----
 composer.json                                 |  2 +-
 package_manager/package_manager.install       |  7 ++--
 package_manager/package_manager.services.yml  | 18 ++++----
 package_manager/src/ComposerInspector.php     | 18 ++++----
 .../src/Event/CollectPathsToExcludeEvent.php  | 20 ++++-----
 package_manager/src/ExecutableFinder.php      | 22 +++-------
 package_manager/src/FileSyncerFactory.php     | 14 +++----
 .../src/NoSymlinksPointToADirectory.php       | 22 ++++++----
 .../src/PackageManagerServiceProvider.php     | 11 ++---
 .../src/PackageManagerUninstallValidator.php  |  2 +-
 package_manager/src/ProcessFactory.php        | 22 ++++------
 package_manager/src/ProcessOutputCallback.php |  6 ++-
 package_manager/src/StageBase.php             | 30 ++++++-------
 package_manager/src/StatusCheckTrait.php      |  4 +-
 .../Validator/ComposerPluginsValidator.php    |  2 +-
 .../src/Validator/RsyncValidator.php          |  6 +--
 .../src/Validator/SymlinkValidator.php        | 14 +++----
 .../src/FixtureManipulator.php                | 16 ++++---
 .../src/StageFixtureManipulator.php           | 16 +++----
 .../src/LoggingBeginner.php                   | 14 +++----
 .../src/LoggingCommitter.php                  | 14 +++----
 .../package_manager_bypass/src/NoOpStager.php | 10 ++---
 .../src/ApiController.php                     |  3 +-
 .../Functional/ComposerRequirementTest.php    | 18 ++++----
 .../src/Kernel/ComposerInspectorTest.php      | 22 +++++-----
 .../tests/src/Kernel/ExecutableFinderTest.php | 10 ++++-
 .../src/Kernel/FileSyncerFactoryTest.php      |  6 +--
 .../Kernel/PackageManagerKernelTestBase.php   |  2 +-
 .../SqliteDatabaseExcluderTest.php            |  2 +-
 .../tests/src/Kernel/RsyncValidatorTest.php   | 10 +++--
 .../tests/src/Kernel/ServicesTest.php         |  4 +-
 .../tests/src/Kernel/StageBaseTest.php        | 42 +++++++++++--------
 .../tests/src/Kernel/StatusCheckTraitTest.php |  2 +-
 .../tests/src/Kernel/SymlinkValidatorTest.php | 27 +++++++-----
 .../tests/src/Unit/ProcessFactoryTest.php     | 12 +++++-
 .../src/Unit/ProcessOutputCallbackTest.php    |  2 +-
 src/CronUpdateStage.php                       | 16 +++----
 src/UpdateStage.php                           | 16 +++----
 .../ComposerStagerOperationFailureTest.php    |  8 ++--
 tests/src/Kernel/CronUpdateStageTest.php      |  2 +-
 tests/src/Kernel/UpdateStageTest.php          | 11 ++++-
 43 files changed, 286 insertions(+), 253 deletions(-)

diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml
index 9b29fe9166..8ec0841cb2 100644
--- a/automatic_updates.services.yml
+++ b/automatic_updates.services.yml
@@ -28,23 +28,7 @@ services:
     calls:
       - ['setLogger', ['@logger.channel.automatic_updates']]
     arguments:
-      - '@automatic_updates.release_chooser'
-      - '@plugin.manager.mail'
-      - '@automatic_updates.status_check_mailer'
-      - '@state'
-      - '@config.factory'
-      - '@package_manager.composer_inspector'
-      - '@package_manager.path_locator'
-      - '@PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface'
-      - '@PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface'
-      - '@PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface'
-      - '@file_system'
-      - '@event_dispatcher'
-      - '@tempstore.shared'
-      - '@datetime.time'
-      - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface'
-      - '@package_manager.failure_marker'
-      - '@automatic_updates.cron_update_stage.inner'
+      $inner: '@automatic_updates.cron_update_stage.inner'
     decorates: 'cron'
   Drupal\automatic_updates\CronUpdateStage: '@automatic_updates.cron_update_stage'
   automatic_updates.requested_update_validator:
diff --git a/automatic_updates_extensions/src/ExtensionUpdateStage.php b/automatic_updates_extensions/src/ExtensionUpdateStage.php
index cc4b854740..9fb8df315f 100644
--- a/automatic_updates_extensions/src/ExtensionUpdateStage.php
+++ b/automatic_updates_extensions/src/ExtensionUpdateStage.php
@@ -13,10 +13,10 @@ use Drupal\package_manager\FailureMarker;
 use Drupal\package_manager\LegacyVersionUtility;
 use Drupal\package_manager\PathLocator;
 use Drupal\package_manager\StageBase;
-use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface;
-use PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Core\CommitterInterface;
+use PhpTuf\ComposerStager\API\Core\StagerInterface;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
 
 /**
@@ -35,11 +35,11 @@ class ExtensionUpdateStage extends StageBase {
    *   The Composer inspector service.
    * @param \Drupal\package_manager\PathLocator $pathLocator
    *   The path locator service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface $beginner
+   * @param \PhpTuf\ComposerStager\API\Core\BeginnerInterface $beginner
    *   The beginner service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface $stager
+   * @param \PhpTuf\ComposerStager\API\Core\StagerInterface $stager
    *   The stager service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface $committer
+   * @param \PhpTuf\ComposerStager\API\Core\CommitterInterface $committer
    *   The committer service.
    * @param \Drupal\Core\File\FileSystemInterface $fileSystem
    *   The file system service.
@@ -49,7 +49,7 @@ class ExtensionUpdateStage extends StageBase {
    *   The shared tempstore factory.
    * @param \Drupal\Component\Datetime\TimeInterface $time
    *   The time service.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $pathFactory
    *   The path factory service.
    * @param \Drupal\package_manager\FailureMarker $failureMarker
    *   The failure marker service.
diff --git a/composer.json b/composer.json
index 3e19d7afce..24f1d56a65 100644
--- a/composer.json
+++ b/composer.json
@@ -14,7 +14,7 @@
     },
     "require": {
         "ext-json": "*",
-        "php-tuf/composer-stager": "2.0-alpha2",
+        "php-tuf/composer-stager": "2.0-alpha4",
         "composer-runtime-api": "^2.1"
     },
     "require-dev": {
diff --git a/package_manager/package_manager.install b/package_manager/package_manager.install
index 5d59d0a8a3..303e3de373 100644
--- a/package_manager/package_manager.install
+++ b/package_manager/package_manager.install
@@ -9,7 +9,8 @@ declare(strict_types = 1);
 
 use Drupal\package_manager\ComposerInspector;
 use Drupal\package_manager\Exception\StageFailureMarkerException;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
 
 /**
  * Implements hook_requirements().
@@ -17,7 +18,7 @@ use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterfac
 function package_manager_requirements(string $phase) {
   $requirements = [];
   // BEGIN: DELETE FROM CORE MERGE REQUEST
-  if (!class_exists('\PhpTuf\ComposerStager\Domain\Core\Beginner\Beginner')) {
+  if (!interface_exists(BeginnerInterface::class)) {
     $requirements['package_manager_composer_dependencies'] = [
       'title' => t('Missing dependency'),
       'description' => t('External dependencies for Package Manager are not available. Composer must be used to download the module with dependencies.'),
@@ -45,7 +46,7 @@ function package_manager_requirements(string $phase) {
   if ($phase !== 'runtime') {
     return $requirements;
   }
-  /** @var \PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface $executable_finder */
+  /** @var \PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface $executable_finder */
   $executable_finder = \Drupal::service(ExecutableFinderInterface::class);
 
   // Report the Composer version in use, as well as its path.
diff --git a/package_manager/package_manager.services.yml b/package_manager/package_manager.services.yml
index 3e6a7f50c5..43e0aa906b 100644
--- a/package_manager/package_manager.services.yml
+++ b/package_manager/package_manager.services.yml
@@ -16,11 +16,11 @@ services:
     public: false
   Drupal\package_manager\FileSyncerFactory:
     public: false
-  PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface:
+  PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface:
     alias: 'Drupal\package_manager\ExecutableFinder'
-  PhpTuf\ComposerStager\Infrastructure\Factory\Process\ProcessFactoryInterface:
+  PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface:
     alias: 'Drupal\package_manager\ProcessFactory'
-  PhpTuf\ComposerStager\Domain\Service\FileSyncer\FileSyncerInterface:
+  PhpTuf\ComposerStager\API\FileSyncer\Service\FileSyncerInterface:
     factory: ['@Drupal\package_manager\FileSyncerFactory', 'create']
   logger.channel.package_manager:
     parent: logger.channel_base
@@ -33,14 +33,14 @@ services:
 
   # Services provided to Drupal by Package Manager.
   package_manager.beginner:
-    class: PhpTuf\ComposerStager\Domain\Core\Beginner\Beginner
-  PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface: '@package_manager.beginner'
+    class: PhpTuf\ComposerStager\Internal\Core\Beginner
+  PhpTuf\ComposerStager\API\Core\BeginnerInterface: '@package_manager.beginner'
   package_manager.stager:
-    class: PhpTuf\ComposerStager\Domain\Core\Stager\Stager
-  PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface: '@package_manager.stager'
+    class: PhpTuf\ComposerStager\Internal\Core\Stager
+  PhpTuf\ComposerStager\API\Core\StagerInterface: '@package_manager.stager'
   package_manager.committer:
-    class: PhpTuf\ComposerStager\Domain\Core\Committer\Committer
-  PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface: '@package_manager.committer'
+    class: PhpTuf\ComposerStager\Internal\Core\Committer
+  PhpTuf\ComposerStager\API\Core\CommitterInterface: '@package_manager.committer'
   package_manager.path_locator:
     class: Drupal\package_manager\PathLocator
     arguments:
diff --git a/package_manager/src/ComposerInspector.php b/package_manager/src/ComposerInspector.php
index 013d0ca7da..4c3044bd60 100644
--- a/package_manager/src/ComposerInspector.php
+++ b/package_manager/src/ComposerInspector.php
@@ -7,11 +7,11 @@ namespace Drupal\package_manager;
 use Composer\Semver\Semver;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\package_manager\Exception\ComposerNotReadyException;
-use PhpTuf\ComposerStager\Domain\Exception\PreconditionException;
-use PhpTuf\ComposerStager\Domain\Exception\RuntimeException;
-use PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Exception\PreconditionException;
+use PhpTuf\ComposerStager\API\Exception\RuntimeException;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Precondition\Service\ComposerIsAvailableInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
 use Psr\Log\LoggerInterface;
@@ -63,15 +63,15 @@ class ComposerInspector implements LoggerAwareInterface {
   /**
    * Constructs a ComposerInspector object.
    *
-   * @param \PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface $runner
+   * @param \PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface $runner
    *   The Composer runner service from Composer Stager.
-   * @param \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface $composerIsAvailable
+   * @param \PhpTuf\ComposerStager\API\Precondition\Service\ComposerIsAvailableInterface $composerIsAvailable
    *   The Composer Stager precondition to ensure that Composer is available.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $pathFactory
    *   The path factory service from Composer Stager.
    */
   public function __construct(
-    private readonly ComposerRunnerInterface $runner,
+    private readonly ComposerProcessRunnerInterface $runner,
     private readonly ComposerIsAvailableInterface $composerIsAvailable,
     private readonly PathFactoryInterface $pathFactory
   ) {
diff --git a/package_manager/src/Event/CollectPathsToExcludeEvent.php b/package_manager/src/Event/CollectPathsToExcludeEvent.php
index facece949a..ea63d612a1 100644
--- a/package_manager/src/Event/CollectPathsToExcludeEvent.php
+++ b/package_manager/src/Event/CollectPathsToExcludeEvent.php
@@ -6,9 +6,9 @@ namespace Drupal\package_manager\Event;
 
 use Drupal\package_manager\StageBase;
 use Drupal\package_manager\PathLocator;
-use PhpTuf\ComposerStager\Domain\Value\PathList\PathListInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
-use PhpTuf\ComposerStager\Infrastructure\Value\PathList\PathList;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathList;
+use PhpTuf\ComposerStager\API\Path\Value\PathListInterface;
 
 /**
  * Defines an event that collects paths to exclude.
@@ -21,7 +21,7 @@ final class CollectPathsToExcludeEvent extends StageEvent implements PathListInt
   /**
    * The list of paths to exclude.
    *
-   * @var \PhpTuf\ComposerStager\Domain\Value\PathList\PathListInterface
+   * @var \PhpTuf\ComposerStager\API\Path\Value\PathListInterface
    */
   protected PathListInterface $pathList;
 
@@ -32,7 +32,7 @@ final class CollectPathsToExcludeEvent extends StageEvent implements PathListInt
    *   The stage which fired this event.
    * @param \Drupal\package_manager\PathLocator $pathLocator
    *   The path locator service.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $pathFactory
    *   The path factory service.
    */
   public function __construct(
@@ -41,14 +41,14 @@ final class CollectPathsToExcludeEvent extends StageEvent implements PathListInt
     protected PathFactoryInterface $pathFactory
   ) {
     parent::__construct($stage);
-    $this->pathList = new PathList([]);
+    $this->pathList = new PathList();
   }
 
   /**
    * {@inheritdoc}
    */
-  public function add(array $paths): void {
-    $this->pathList->add($paths);
+  public function add(string ...$paths): void {
+    $this->pathList->add(...$paths);
   }
 
   /**
@@ -76,7 +76,7 @@ final class CollectPathsToExcludeEvent extends StageEvent implements PathListInt
 
     foreach ($paths as $path) {
       // Make the path relative to the project root by prefixing the web root.
-      $this->add([$web_root . $path]);
+      $this->add($web_root . $path);
     }
   }
 
@@ -101,7 +101,7 @@ final class CollectPathsToExcludeEvent extends StageEvent implements PathListInt
       // Make absolute paths relative to the project root.
       $path = str_replace($project_root, '', $path);
       $path = ltrim($path, '/');
-      $this->add([$path]);
+      $this->add($path);
     }
   }
 
diff --git a/package_manager/src/ExecutableFinder.php b/package_manager/src/ExecutableFinder.php
index 93e8ddd05a..731a751c6d 100644
--- a/package_manager/src/ExecutableFinder.php
+++ b/package_manager/src/ExecutableFinder.php
@@ -5,9 +5,8 @@ declare(strict_types = 1);
 namespace Drupal\package_manager;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinder as StagerExecutableFinder;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
-use Symfony\Component\Process\ExecutableFinder as SymfonyExecutableFinder;
+use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\Internal\Finder\Service\ExecutableFinder as StagerExecutableFinder;
 
 /**
  * An executable finder which looks for executable paths in configuration.
@@ -19,27 +18,18 @@ use Symfony\Component\Process\ExecutableFinder as SymfonyExecutableFinder;
  */
 final class ExecutableFinder implements ExecutableFinderInterface {
 
-  /**
-   * The decorated executable finder.
-   *
-   * @var \PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinder
-   */
-  private $decorated;
-
   /**
    * Constructs an ExecutableFinder object.
    *
-   * @param \Symfony\Component\Process\ExecutableFinder $symfony_executable_finder
-   *   The Symfony executable finder.
+   * @param \PhpTuf\ComposerStager\Internal\Finder\Service\ExecutableFinder $decorated
+   *   The decorated executable finder.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
    *   The config factory service.
    */
   public function __construct(
-    SymfonyExecutableFinder $symfony_executable_finder,
+    private readonly StagerExecutableFinder $decorated,
     private readonly ConfigFactoryInterface $configFactory
-  ) {
-    $this->decorated = new StagerExecutableFinder($symfony_executable_finder);
-  }
+  ) {}
 
   /**
    * {@inheritdoc}
diff --git a/package_manager/src/FileSyncerFactory.php b/package_manager/src/FileSyncerFactory.php
index 1210ae817f..cd7beee881 100644
--- a/package_manager/src/FileSyncerFactory.php
+++ b/package_manager/src/FileSyncerFactory.php
@@ -5,10 +5,10 @@ declare(strict_types = 1);
 namespace Drupal\package_manager;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
-use PhpTuf\ComposerStager\Domain\Service\FileSyncer\FileSyncerInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\FileSyncer\FileSyncerFactory as StagerFileSyncerFactory;
-use PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\PhpFileSyncer;
-use PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\RsyncFileSyncer;
+use PhpTuf\ComposerStager\API\FileSyncer\Service\FileSyncerInterface;
+use PhpTuf\ComposerStager\Internal\FileSyncer\Factory\FileSyncerFactory as StagerFileSyncerFactory;
+use PhpTuf\ComposerStager\Internal\FileSyncer\Service\PhpFileSyncer;
+use PhpTuf\ComposerStager\Internal\FileSyncer\Service\RsyncFileSyncer;
 use Symfony\Component\Process\ExecutableFinder;
 
 /**
@@ -24,7 +24,7 @@ final class FileSyncerFactory {
   /**
    * The decorated file syncer factory.
    *
-   * @var \PhpTuf\ComposerStager\Infrastructure\Factory\FileSyncer\FileSyncerFactory
+   * @var \PhpTuf\ComposerStager\Internal\FileSyncer\Factory\FileSyncerFactory
    */
   private $decorated;
 
@@ -33,9 +33,9 @@ final class FileSyncerFactory {
    *
    * @param \Symfony\Component\Process\ExecutableFinder $executable_finder
    *   The Symfony executable finder.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\PhpFileSyncer $phpFileSyncer
+   * @param \PhpTuf\ComposerStager\Internal\FileSyncer\Service\PhpFileSyncer $phpFileSyncer
    *   The PHP file syncer service.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\RsyncFileSyncer $rsyncFileSyncer
+   * @param \PhpTuf\ComposerStager\Internal\FileSyncer\Service\RsyncFileSyncer $rsyncFileSyncer
    *   The rsync file syncer service.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
    *   The config factory service.
diff --git a/package_manager/src/NoSymlinksPointToADirectory.php b/package_manager/src/NoSymlinksPointToADirectory.php
index fb97daf558..98b44711cd 100644
--- a/package_manager/src/NoSymlinksPointToADirectory.php
+++ b/package_manager/src/NoSymlinksPointToADirectory.php
@@ -6,9 +6,10 @@ namespace Drupal\package_manager;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
-use PhpTuf\ComposerStager\Domain\Service\Precondition\NoSymlinksPointToADirectoryInterface;
-use PhpTuf\ComposerStager\Domain\Value\Path\PathInterface;
-use PhpTuf\ComposerStager\Domain\Value\PathList\PathListInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathListInterface;
+use PhpTuf\ComposerStager\API\Precondition\Service\NoSymlinksPointToADirectoryInterface;
+use PhpTuf\ComposerStager\API\Translation\Value\TranslatableInterface;
 
 /**
  * Checks if the code base contains any symlinks that point to a directory.
@@ -29,7 +30,7 @@ final class NoSymlinksPointToADirectory implements NoSymlinksPointToADirectoryIn
   /**
    * Constructs a NoSymlinksPointToADirectory object.
    *
-   * @param \PhpTuf\ComposerStager\Domain\Service\Precondition\NoSymlinksPointToADirectoryInterface $decorated
+   * @param \PhpTuf\ComposerStager\API\Precondition\Service\NoSymlinksPointToADirectoryInterface $decorated
    *   The decorated precondition.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
    *   The config factory.
@@ -42,21 +43,21 @@ final class NoSymlinksPointToADirectory implements NoSymlinksPointToADirectoryIn
   /**
    * {@inheritdoc}
    */
-  public function getName(): string {
+  public function getName(): TranslatableInterface {
     return $this->decorated->getName();
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getDescription(): string {
+  public function getDescription(): TranslatableInterface {
     return $this->decorated->getDescription();
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getStatusMessage(PathInterface $activeDir, PathInterface $stagingDir, ?PathListInterface $exclusions = NULL,): string {
+  public function getStatusMessage(PathInterface $activeDir, PathInterface $stagingDir, ?PathListInterface $exclusions = NULL,): TranslatableInterface {
     if ($this->isUsingRsync()) {
       return $this->t('Symlinks to directories are supported by the rsync file syncer.');
     }
@@ -94,4 +95,11 @@ final class NoSymlinksPointToADirectory implements NoSymlinksPointToADirectoryIn
     return $syncer === 'rsync';
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getLeaves(): array {
+    return [$this];
+  }
+
 }
diff --git a/package_manager/src/PackageManagerServiceProvider.php b/package_manager/src/PackageManagerServiceProvider.php
index b6f5ccb513..ba31f9985b 100644
--- a/package_manager/src/PackageManagerServiceProvider.php
+++ b/package_manager/src/PackageManagerServiceProvider.php
@@ -6,8 +6,8 @@ namespace Drupal\package_manager;
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderBase;
-use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\Service\Precondition\NoSymlinksPointToADirectoryInterface;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Precondition\Service\NoSymlinksPointToADirectoryInterface;
 
 /**
  * Defines dynamic container services for Package Manager.
@@ -33,13 +33,14 @@ final class PackageManagerServiceProvider extends ServiceProviderBase {
     // Use an interface that we know exists to determine the absolute path where
     // Composer Stager is installed.
     $mirror = new \ReflectionClass(BeginnerInterface::class);
-    $path = dirname($mirror->getFileName(), 4);
+    $path = dirname($mirror->getFileName(), 3);
 
     // Certain subdirectories of Composer Stager shouldn't be scanned for
     // services.
     $ignore_directories = [
-      $path . '/Domain/Exception',
-      $path . '/Infrastructure/Value',
+      $path . '/API/Exception',
+      $path . '/Internal/Path/Value',
+      $path . '/Internal/Translation/Value',
     ];
     // As we scan for services, compile a list of which classes implement which
     // interfaces so that we can set up aliases for interfaces that are only
diff --git a/package_manager/src/PackageManagerUninstallValidator.php b/package_manager/src/PackageManagerUninstallValidator.php
index fa81fe4275..27f8203abe 100644
--- a/package_manager/src/PackageManagerUninstallValidator.php
+++ b/package_manager/src/PackageManagerUninstallValidator.php
@@ -6,7 +6,7 @@ namespace Drupal\package_manager;
 
 use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 
diff --git a/package_manager/src/ProcessFactory.php b/package_manager/src/ProcessFactory.php
index be9b445ec2..a231e61e0c 100644
--- a/package_manager/src/ProcessFactory.php
+++ b/package_manager/src/ProcessFactory.php
@@ -6,8 +6,8 @@ namespace Drupal\package_manager;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\File\FileSystemInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Process\ProcessFactoryInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Process\ProcessFactory as StagerProcessFactory;
+use PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface;
+use PhpTuf\ComposerStager\Internal\Process\Factory\ProcessFactory as StagerProcessFactory;
 use Symfony\Component\Process\Process;
 
 // cspell:ignore BINDIR
@@ -22,13 +22,6 @@ use Symfony\Component\Process\Process;
  */
 final class ProcessFactory implements ProcessFactoryInterface {
 
-  /**
-   * The decorated process factory.
-   *
-   * @var \PhpTuf\ComposerStager\Infrastructure\Factory\Process\ProcessFactoryInterface
-   */
-  private $decorated;
-
   /**
    * Constructs a ProcessFactory object.
    *
@@ -36,13 +29,14 @@ final class ProcessFactory implements ProcessFactoryInterface {
    *   The file system service.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
    *   The config factory service.
+   * @param \PhpTuf\ComposerStager\Internal\Process\Factory\ProcessFactory $decorated
+   *   The decorated process factory service.
    */
   public function __construct(
     private readonly FileSystemInterface $fileSystem,
-    private readonly ConfigFactoryInterface $configFactory
-  ) {
-    $this->decorated = new StagerProcessFactory();
-  }
+    private readonly ConfigFactoryInterface $configFactory,
+    private readonly StagerProcessFactory $decorated,
+  ) {}
 
   /**
    * Returns the value of an environment variable.
@@ -67,7 +61,7 @@ final class ProcessFactory implements ProcessFactoryInterface {
     $process = $this->decorated->create($command);
 
     $env = $process->getEnv();
-    if ($this->isComposerCommand($command)) {
+    if ($command && $this->isComposerCommand($command)) {
       $env['COMPOSER_HOME'] = $this->getComposerHomePath();
     }
     // Ensure that the current PHP installation is the first place that will be
diff --git a/package_manager/src/ProcessOutputCallback.php b/package_manager/src/ProcessOutputCallback.php
index 8ce6625087..fd0ac56d8a 100644
--- a/package_manager/src/ProcessOutputCallback.php
+++ b/package_manager/src/ProcessOutputCallback.php
@@ -4,7 +4,7 @@ declare(strict_types = 1);
 
 namespace Drupal\package_manager;
 
-use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessOutputCallbackInterface;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
 use Psr\Log\NullLogger;
@@ -48,6 +48,10 @@ final class ProcessOutputCallback implements ProcessOutputCallbackInterface, Log
    * {@inheritdoc}
    */
   public function __invoke(string $type, string $buffer): void {
+    // \Symfony\Component\Process\Process defines the output types in lowercase,
+    // but Composer Stager uses uppercase.
+    $type = strtoupper($type);
+
     if ($type === self::OUT) {
       $this->outBuffer .= $buffer;
     }
diff --git a/package_manager/src/StageBase.php b/package_manager/src/StageBase.php
index d4f7a8c866..293ee12b11 100644
--- a/package_manager/src/StageBase.php
+++ b/package_manager/src/StageBase.php
@@ -28,13 +28,13 @@ use Drupal\package_manager\Exception\ApplyFailedException;
 use Drupal\package_manager\Exception\StageEventException;
 use Drupal\package_manager\Exception\StageException;
 use Drupal\package_manager\Exception\StageOwnershipException;
-use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface;
-use PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface;
-use PhpTuf\ComposerStager\Domain\Exception\InvalidArgumentException;
-use PhpTuf\ComposerStager\Domain\Exception\PreconditionException;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
-use PhpTuf\ComposerStager\Infrastructure\Value\PathList\PathList;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Core\CommitterInterface;
+use PhpTuf\ComposerStager\API\Core\StagerInterface;
+use PhpTuf\ComposerStager\API\Exception\InvalidArgumentException;
+use PhpTuf\ComposerStager\API\Exception\PreconditionException;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathList;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
 use Psr\Log\NullLogger;
@@ -166,11 +166,11 @@ abstract class StageBase implements LoggerAwareInterface {
    *
    * @param \Drupal\package_manager\PathLocator $pathLocator
    *   The path locator service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface $beginner
+   * @param \PhpTuf\ComposerStager\API\Core\BeginnerInterface $beginner
    *   The beginner service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface $stager
+   * @param \PhpTuf\ComposerStager\API\Core\StagerInterface $stager
    *   The stager service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface $committer
+   * @param \PhpTuf\ComposerStager\API\Core\CommitterInterface $committer
    *   The committer service.
    * @param \Drupal\Core\File\FileSystemInterface $fileSystem
    *   The file system service.
@@ -180,7 +180,7 @@ abstract class StageBase implements LoggerAwareInterface {
    *   The shared tempstore factory.
    * @param \Drupal\Component\Datetime\TimeInterface $time
    *   The time service.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $pathFactory
    *   The path factory service.
    * @param \Drupal\package_manager\FailureMarker $failureMarker
    *   The failure marker service.
@@ -330,7 +330,7 @@ abstract class StageBase implements LoggerAwareInterface {
     $this->dispatch($event, [$this, 'markAsAvailable']);
 
     try {
-      $this->beginner->begin($active_dir, $stage_dir, new PathList($event->getExcludedPaths()), NULL, $timeout);
+      $this->beginner->begin($active_dir, $stage_dir, new PathList(...$event->getExcludedPaths()), NULL, $timeout);
     }
     catch (\Throwable $error) {
       $this->destroy();
@@ -452,10 +452,10 @@ abstract class StageBase implements LoggerAwareInterface {
     // Create a marker file so that we can tell later on if the commit failed.
     $this->failureMarker->write($this, $this->getFailureMarkerMessage());
     // Exclude the failure file from the commit operation.
-    $paths_to_exclude = new PathList($event->getExcludedPaths());
-    $paths_to_exclude->add([
+    $paths_to_exclude = new PathList(...$event->getExcludedPaths());
+    $paths_to_exclude->add(
       str_replace($this->pathLocator->getProjectRoot() . DIRECTORY_SEPARATOR, '', $this->failureMarker->getPath()),
-    ]);
+    );
 
     try {
       $this->committer->commit($stage_dir, $active_dir, $paths_to_exclude, NULL, $timeout);
diff --git a/package_manager/src/StatusCheckTrait.php b/package_manager/src/StatusCheckTrait.php
index 4bad25258d..23386235b8 100644
--- a/package_manager/src/StatusCheckTrait.php
+++ b/package_manager/src/StatusCheckTrait.php
@@ -6,7 +6,7 @@ namespace Drupal\package_manager;
 
 use Drupal\package_manager\Event\CollectPathsToExcludeEvent;
 use Drupal\package_manager\Event\StatusCheckEvent;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
 
 /**
@@ -28,7 +28,7 @@ trait StatusCheckTrait {
    *   (optional) The event dispatcher service.
    * @param \Drupal\package_manager\PathLocator $path_locator
    *   (optional) The path locator service.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $path_factory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $path_factory
    *   (optional) The path factory service.
    *
    * @return \Drupal\package_manager\ValidationResult[]
diff --git a/package_manager/src/Validator/ComposerPluginsValidator.php b/package_manager/src/Validator/ComposerPluginsValidator.php
index 369f0fb5a6..4cd11ce467 100644
--- a/package_manager/src/Validator/ComposerPluginsValidator.php
+++ b/package_manager/src/Validator/ComposerPluginsValidator.php
@@ -13,7 +13,7 @@ use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
 use Drupal\package_manager\Event\StatusCheckEvent;
 use Drupal\package_manager\PathLocator;
-use PhpTuf\ComposerStager\Domain\Exception\RuntimeException;
+use PhpTuf\ComposerStager\API\Exception\RuntimeException;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
diff --git a/package_manager/src/Validator/RsyncValidator.php b/package_manager/src/Validator/RsyncValidator.php
index b6551fe75b..315ea17731 100644
--- a/package_manager/src/Validator/RsyncValidator.php
+++ b/package_manager/src/Validator/RsyncValidator.php
@@ -11,8 +11,8 @@ use Drupal\Core\Url;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
 use Drupal\package_manager\Event\StatusCheckEvent;
-use PhpTuf\ComposerStager\Domain\Exception\LogicException;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\API\Exception\LogicException;
+use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -32,7 +32,7 @@ final class RsyncValidator implements EventSubscriberInterface {
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
    *   The config factory.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface $executableFinder
+   * @param \PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface $executableFinder
    *   The executable finder service.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
    *   The module handler service.
diff --git a/package_manager/src/Validator/SymlinkValidator.php b/package_manager/src/Validator/SymlinkValidator.php
index 80b7d50794..7c4da395aa 100644
--- a/package_manager/src/Validator/SymlinkValidator.php
+++ b/package_manager/src/Validator/SymlinkValidator.php
@@ -7,10 +7,10 @@ namespace Drupal\package_manager\Validator;
 use Drupal\package_manager\Event\PreOperationStageEvent;
 use Drupal\package_manager\Event\PreRequireEvent;
 use Drupal\package_manager\PathLocator;
-use PhpTuf\ComposerStager\Domain\Aggregate\PreconditionsTree\NoUnsupportedLinksExistInterface;
-use PhpTuf\ComposerStager\Domain\Exception\PreconditionException;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
-use PhpTuf\ComposerStager\Infrastructure\Value\PathList\PathList;
+use PhpTuf\ComposerStager\API\Exception\PreconditionException;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathList;
+use PhpTuf\ComposerStager\API\Precondition\Service\NoUnsupportedLinksExistInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -32,9 +32,9 @@ final class SymlinkValidator implements EventSubscriberInterface {
    *
    * @param \Drupal\package_manager\PathLocator $pathLocator
    *   The path locator service.
-   * @param \PhpTuf\ComposerStager\Domain\Aggregate\PreconditionsTree\NoUnsupportedLinksExistInterface $precondition
+   * @param \PhpTuf\ComposerStager\API\Precondition\Service\NoUnsupportedLinksExistInterface $precondition
    *   The Composer Stager precondition that this validator wraps.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $pathFactory
    *   The path factory service.
    */
   public function __construct(
@@ -75,7 +75,7 @@ final class SymlinkValidator implements EventSubscriberInterface {
     }
 
     try {
-      $this->precondition->assertIsFulfilled($active_dir, $stage_dir, new PathList($excluded_paths));
+      $this->precondition->assertIsFulfilled($active_dir, $stage_dir, new PathList(...$excluded_paths));
     }
     catch (PreconditionException $e) {
       $event->addErrorFromThrowable($e);
diff --git a/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php b/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php
index 71ecc8c9fb..92aff515da 100644
--- a/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php
+++ b/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php
@@ -4,8 +4,8 @@ namespace Drupal\fixture_manipulator;
 
 use Drupal\Component\FileSystem\FileSystem;
 use Drupal\Component\Utility\NestedArray;
-use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessOutputCallbackInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface;
 use Symfony\Component\Filesystem\Filesystem as SymfonyFileSystem;
 use Drupal\Component\Serialization\Yaml;
 
@@ -55,8 +55,8 @@ class FixtureManipulator {
    * Validate the fixtures still passes `composer validate`.
    */
   private function validateComposer(): void {
-    /** @var \PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface $runner */
-    $runner = \Drupal::service(ComposerRunnerInterface::class);
+    /** @var \PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface $runner */
+    $runner = \Drupal::service(ComposerProcessRunnerInterface::class);
     $runner->run([
       'validate',
       '--check-lock',
@@ -446,6 +446,10 @@ class FixtureManipulator {
        * {@inheritdoc}
        */
       public function __invoke(string $type, string $buffer): void {
+        // \Symfony\Component\Process\Process defines the output types in
+        // lowercase, but Composer Stager uses uppercase.
+        $type = strtoupper($type);
+
         if ($type === self::OUT) {
           $this->stdout .= $buffer;
           return;
@@ -458,8 +462,8 @@ class FixtureManipulator {
       }
 
     };
-    /** @var \PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface $runner */
-    $runner = \Drupal::service(ComposerRunnerInterface::class);
+    /** @var \PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface $runner */
+    $runner = \Drupal::service(ComposerProcessRunnerInterface::class);
     $command_options[] = "--working-dir={$this->dir}";
     $runner->run($command_options, $plain_output);
     return $plain_output;
diff --git a/package_manager/tests/modules/fixture_manipulator/src/StageFixtureManipulator.php b/package_manager/tests/modules/fixture_manipulator/src/StageFixtureManipulator.php
index 03667d4dac..29e0db0da3 100644
--- a/package_manager/tests/modules/fixture_manipulator/src/StageFixtureManipulator.php
+++ b/package_manager/tests/modules/fixture_manipulator/src/StageFixtureManipulator.php
@@ -5,11 +5,11 @@ declare(strict_types = 1);
 namespace Drupal\fixture_manipulator;
 
 use Drupal\Core\State\StateInterface;
-use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ProcessRunnerInterface;
-use PhpTuf\ComposerStager\Domain\Value\Path\PathInterface;
-use PhpTuf\ComposerStager\Domain\Value\PathList\PathListInterface;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathListInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessOutputCallbackInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessRunnerInterface;
 
 /**
  * A fixture manipulator service that commits changes after begin.
@@ -31,7 +31,7 @@ final class StageFixtureManipulator extends FixtureManipulator implements Beginn
   /**
    * The decorated service.
    *
-   * @var \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface
+   * @var \PhpTuf\ComposerStager\API\Core\BeginnerInterface
    */
   private BeginnerInterface $inner;
 
@@ -40,7 +40,7 @@ final class StageFixtureManipulator extends FixtureManipulator implements Beginn
    *
    * @param \Drupal\Core\State\StateInterface $state
    *   The state service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface $inner
+   * @param \PhpTuf\ComposerStager\API\Core\BeginnerInterface $inner
    *   The decorated beginner service.
    */
   public function __construct(StateInterface $state, BeginnerInterface $inner) {
@@ -54,7 +54,7 @@ final class StageFixtureManipulator extends FixtureManipulator implements Beginn
   public function begin(PathInterface $activeDir, PathInterface $stagingDir, ?PathListInterface $exclusions = NULL, ?ProcessOutputCallbackInterface $callback = NULL, ?int $timeout = ProcessRunnerInterface::DEFAULT_TIMEOUT): void {
     $this->inner->begin($activeDir, $stagingDir, $exclusions, $callback, $timeout);
     if ($this->getQueuedManipulationItems()) {
-      $this->doCommitChanges($stagingDir->resolve());
+      $this->doCommitChanges($stagingDir->resolved());
     }
   }
 
diff --git a/package_manager/tests/modules/package_manager_bypass/src/LoggingBeginner.php b/package_manager/tests/modules/package_manager_bypass/src/LoggingBeginner.php
index ffe51348c7..e5c154c828 100644
--- a/package_manager/tests/modules/package_manager_bypass/src/LoggingBeginner.php
+++ b/package_manager/tests/modules/package_manager_bypass/src/LoggingBeginner.php
@@ -5,11 +5,11 @@ declare(strict_types = 1);
 namespace Drupal\package_manager_bypass;
 
 use Drupal\Core\State\StateInterface;
-use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ProcessRunnerInterface;
-use PhpTuf\ComposerStager\Domain\Value\Path\PathInterface;
-use PhpTuf\ComposerStager\Domain\Value\PathList\PathListInterface;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathListInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessOutputCallbackInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessRunnerInterface;
 
 /**
  * A composer-stager Beginner decorator that adds logging.
@@ -24,7 +24,7 @@ final class LoggingBeginner implements BeginnerInterface {
   /**
    * The decorated service.
    *
-   * @var \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface
+   * @var \PhpTuf\ComposerStager\API\Core\BeginnerInterface
    */
   private $inner;
 
@@ -33,7 +33,7 @@ final class LoggingBeginner implements BeginnerInterface {
    *
    * @param \Drupal\Core\State\StateInterface $state
    *   The state service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface $inner
+   * @param \PhpTuf\ComposerStager\API\Core\BeginnerInterface $inner
    *   The decorated beginner service.
    */
   public function __construct(StateInterface $state, BeginnerInterface $inner) {
diff --git a/package_manager/tests/modules/package_manager_bypass/src/LoggingCommitter.php b/package_manager/tests/modules/package_manager_bypass/src/LoggingCommitter.php
index e6aea32a9d..cf813a12db 100644
--- a/package_manager/tests/modules/package_manager_bypass/src/LoggingCommitter.php
+++ b/package_manager/tests/modules/package_manager_bypass/src/LoggingCommitter.php
@@ -5,11 +5,11 @@ declare(strict_types = 1);
 namespace Drupal\package_manager_bypass;
 
 use Drupal\Core\State\StateInterface;
-use PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ProcessRunnerInterface;
-use PhpTuf\ComposerStager\Domain\Value\Path\PathInterface;
-use PhpTuf\ComposerStager\Domain\Value\PathList\PathListInterface;
+use PhpTuf\ComposerStager\API\Core\CommitterInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathListInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessOutputCallbackInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessRunnerInterface;
 
 /**
  * A composer-stager Committer decorator that adds logging.
@@ -24,7 +24,7 @@ final class LoggingCommitter implements CommitterInterface {
   /**
    * The decorated service.
    *
-   * @var \PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface
+   * @var \PhpTuf\ComposerStager\API\Core\CommitterInterface
    */
   private $inner;
 
@@ -33,7 +33,7 @@ final class LoggingCommitter implements CommitterInterface {
    *
    * @param \Drupal\Core\State\StateInterface $state
    *   The state service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface $inner
+   * @param \PhpTuf\ComposerStager\API\Core\CommitterInterface $inner
    *   The decorated committer service.
    */
   public function __construct(StateInterface $state, CommitterInterface $inner) {
diff --git a/package_manager/tests/modules/package_manager_bypass/src/NoOpStager.php b/package_manager/tests/modules/package_manager_bypass/src/NoOpStager.php
index a7819d302e..5adc41d3cb 100644
--- a/package_manager/tests/modules/package_manager_bypass/src/NoOpStager.php
+++ b/package_manager/tests/modules/package_manager_bypass/src/NoOpStager.php
@@ -6,10 +6,10 @@ namespace Drupal\package_manager_bypass;
 
 use Composer\Json\JsonFile;
 use Drupal\Core\State\StateInterface;
-use PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ProcessRunnerInterface;
-use PhpTuf\ComposerStager\Domain\Value\Path\PathInterface;
+use PhpTuf\ComposerStager\API\Core\StagerInterface;
+use PhpTuf\ComposerStager\API\Path\Value\PathInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessOutputCallbackInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ProcessRunnerInterface;
 
 /**
  * A composer-stager Stager implementation that does nothing, except logging.
@@ -49,7 +49,7 @@ final class NoOpStager implements StagerInterface {
 
     // If desired, simulate a change to the lock file (e.g., as a result of
     // running `composer update`).
-    $lockFile = new JsonFile($stagingDir->resolve() . '/composer.lock');
+    $lockFile = new JsonFile($stagingDir->resolved() . '/composer.lock');
     $changeLockFile = $this->state->get(static::class . ' lock', TRUE);
 
     if ($changeLockFile && $lockFile->exists()) {
diff --git a/package_manager/tests/modules/package_manager_test_api/src/ApiController.php b/package_manager/tests/modules/package_manager_test_api/src/ApiController.php
index 9178d26780..bbc229018a 100644
--- a/package_manager/tests/modules/package_manager_test_api/src/ApiController.php
+++ b/package_manager/tests/modules/package_manager_test_api/src/ApiController.php
@@ -8,6 +8,7 @@ use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Url;
 use Drupal\package_manager\PathLocator;
 use Drupal\package_manager\StageBase;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -65,7 +66,7 @@ class ApiController extends ControllerBase {
       $container->get('event_dispatcher'),
       $container->get('tempstore.shared'),
       $container->get('datetime.time'),
-      $container->get('PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface'),
+      $container->get(PathFactoryInterface::class),
       $container->get('package_manager.failure_marker'));
     return new static(
       $stage,
diff --git a/package_manager/tests/src/Functional/ComposerRequirementTest.php b/package_manager/tests/src/Functional/ComposerRequirementTest.php
index 8eb7729b7e..161a0f18e6 100644
--- a/package_manager/tests/src/Functional/ComposerRequirementTest.php
+++ b/package_manager/tests/src/Functional/ComposerRequirementTest.php
@@ -6,7 +6,7 @@ namespace Drupal\Tests\package_manager\Functional;
 
 use Drupal\package_manager\ComposerInspector;
 use Drupal\Tests\BrowserTestBase;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
 
 /**
  * Tests that Package Manager shows the Composer version on the status report.
@@ -27,14 +27,20 @@ class ComposerRequirementTest extends BrowserTestBase {
   protected $defaultTheme = 'stark';
 
   /**
-   * Tests that Composer and file syncer info is listed on the status report.
+   * Tests that Composer version and path are listed on the status report.
    */
   public function testComposerInfoShown(): void {
-    /** @var \PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface $executable_finder */
+    $config = $this->config('package_manager.settings');
+
+    // Ensure we can locate the Composer executable.
+    /** @var \PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface $executable_finder */
     $executable_finder = $this->container->get(ExecutableFinderInterface::class);
     $composer_path = $executable_finder->find('composer');
     $composer_version = $this->container->get(ComposerInspector::class)->getVersion();
 
+    // With a valid path to Composer, ensure the status report shows its version
+    // number and path.
+    $config->set('executables.composer', $composer_path)->save();
     $account = $this->drupalCreateUser(['administer site configuration']);
     $this->drupalLogin($account);
     $this->drupalGet('/admin/reports/status');
@@ -44,12 +50,10 @@ class ComposerRequirementTest extends BrowserTestBase {
 
     // If the path to Composer is invalid, we should see the error message
     // that gets raised when we try to get its version.
-    $this->config('package_manager.settings')
-      ->set('executables.composer', '/path/to/composer')
-      ->save();
+    $config->set('executables.composer', '/path/to/composer')->save();
     $this->getSession()->reload();
     $assert_session->statusCodeEquals(200);
-    $assert_session->pageTextContains('Composer was not found. The error message was: The command "\'/path/to/composer\' \'--format=json\'" failed.');
+    $assert_session->pageTextContains('Composer was not found. The error message was: Failed to run process: The command "\'/path/to/composer\' \'--format=json\'" failed.');
   }
 
 }
diff --git a/package_manager/tests/src/Kernel/ComposerInspectorTest.php b/package_manager/tests/src/Kernel/ComposerInspectorTest.php
index 02cc502af1..5d4c0de288 100644
--- a/package_manager/tests/src/Kernel/ComposerInspectorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerInspectorTest.php
@@ -14,11 +14,12 @@ use Drupal\package_manager\ProcessOutputCallback;
 use Drupal\package_manager\InstalledPackagesList;
 use Drupal\Tests\package_manager\Traits\InstalledPackagesListTrait;
 use Drupal\package_manager\PathLocator;
-use PhpTuf\ComposerStager\Domain\Exception\PreconditionException;
-use PhpTuf\ComposerStager\Domain\Exception\RuntimeException;
-use PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface;
-use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactory;
+use PhpTuf\ComposerStager\API\Exception\PreconditionException;
+use PhpTuf\ComposerStager\API\Exception\RuntimeException;
+use PhpTuf\ComposerStager\API\Precondition\Service\ComposerIsAvailableInterface;
+use PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface;
+use PhpTuf\ComposerStager\Internal\Path\Factory\PathFactory;
+use PhpTuf\ComposerStager\Internal\Translation\Value\TranslatableMessage;
 use Prophecy\Argument;
 use Prophecy\Prophecy\ObjectProphecy;
 
@@ -154,8 +155,9 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
     $mocked_precondition = $precondition->reveal();
     $this->container->set(ComposerIsAvailableInterface::class, $mocked_precondition);
 
+    $message = new TranslatableMessage("Well, that didn't work.");
     $precondition->assertIsFulfilled(Argument::cetera())
-      ->willThrow(new PreconditionException($mocked_precondition, "Well, that didn't work."))
+      ->willThrow(new PreconditionException($mocked_precondition, $message))
       // The result of the precondition is statically cached, so it should only
       // be called once even though we call validate() twice.
       ->shouldBeCalledOnce();
@@ -250,7 +252,7 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
     // The runner should be called with `validate` as the first argument, but
     // it won't affect the outcome of this test.
     $runner->run(Argument::withEntry(0, 'validate'));
-    $this->container->set(ComposerRunnerInterface::class, $runner->reveal());
+    $this->container->set(ComposerProcessRunnerInterface::class, $runner->reveal());
 
     if ($expected_message === '<default>') {
       $expected_message = "The detected Composer version, $reported_version, does not satisfy <code>" . ComposerInspector::SUPPORTED_VERSION . '</code>.';
@@ -285,7 +287,7 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
    *   [null]
    */
   public function testGetVersion(?string $reported_version): void {
-    $this->container->set(ComposerRunnerInterface::class, $this->mockComposerRunner($reported_version)->reveal());
+    $this->container->set(ComposerProcessRunnerInterface::class, $this->mockComposerRunner($reported_version)->reveal());
 
     if (empty($reported_version)) {
       $this->expectException(\UnexpectedValueException::class);
@@ -355,7 +357,7 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
    */
   public function testMetapackagePath(bool $is_metapackage, ?string $install_path, ?string $exception_message): void {
     $inspector = new class (
-      $this->container->get(ComposerRunnerInterface::class),
+      $this->container->get(ComposerProcessRunnerInterface::class),
       $this->container->get(ComposerIsAvailableInterface::class),
       new PathFactory(),
     ) extends ComposerInspector {
@@ -484,7 +486,7 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
    *   The configurator for the mocked Composer runner.
    */
   private function mockComposerRunner(?string $reported_version): ObjectProphecy {
-    $runner = $this->prophesize(ComposerRunnerInterface::class);
+    $runner = $this->prophesize(ComposerProcessRunnerInterface::class);
 
     $pass_version_to_output_callback = function (array $arguments_passed_to_runner) use ($reported_version): void {
       $command_output = Json::encode([
diff --git a/package_manager/tests/src/Kernel/ExecutableFinderTest.php b/package_manager/tests/src/Kernel/ExecutableFinderTest.php
index 5a4c4818a5..82402899b4 100644
--- a/package_manager/tests/src/Kernel/ExecutableFinderTest.php
+++ b/package_manager/tests/src/Kernel/ExecutableFinderTest.php
@@ -6,7 +6,9 @@ namespace Drupal\Tests\package_manager\Kernel;
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\package_manager\ExecutableFinder;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\Internal\Finder\Service\ExecutableFinder as StagerExecutableFinder;
+use PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface;
 use Symfony\Component\Process\ExecutableFinder as SymfonyExecutableFinder;
 
 /**
@@ -32,7 +34,10 @@ class ExecutableFinderTest extends PackageManagerKernelTestBase {
 
     };
     $container->getDefinition(ExecutableFinder::class)
-      ->setArgument('$symfony_executable_finder', $symfony_executable_finder);
+      ->setArgument('$decorated', new StagerExecutableFinder(
+        $symfony_executable_finder,
+        $this->createMock(TranslatableFactoryInterface::class),
+      ));
   }
 
   /**
@@ -44,6 +49,7 @@ class ExecutableFinderTest extends PackageManagerKernelTestBase {
       ->save();
 
     $executable_finder = $this->container->get(ExecutableFinderInterface::class);
+    $this->assertInstanceOf(ExecutableFinder::class, $executable_finder);
     $this->assertSame('/path/to/composer', $executable_finder->find('composer'));
     $this->assertSame('/dev/null', $executable_finder->find('rsync'));
   }
diff --git a/package_manager/tests/src/Kernel/FileSyncerFactoryTest.php b/package_manager/tests/src/Kernel/FileSyncerFactoryTest.php
index c0b2f335d6..2ff5bb65ae 100644
--- a/package_manager/tests/src/Kernel/FileSyncerFactoryTest.php
+++ b/package_manager/tests/src/Kernel/FileSyncerFactoryTest.php
@@ -6,9 +6,9 @@ namespace Drupal\Tests\package_manager\Kernel;
 
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\Tests\package_manager\Traits\AssertPreconditionsTrait;
-use PhpTuf\ComposerStager\Domain\Service\FileSyncer\FileSyncerInterface;
-use PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\PhpFileSyncer;
-use PhpTuf\ComposerStager\Infrastructure\Service\FileSyncer\RsyncFileSyncer;
+use PhpTuf\ComposerStager\API\FileSyncer\Service\FileSyncerInterface;
+use PhpTuf\ComposerStager\Internal\FileSyncer\Service\PhpFileSyncer;
+use PhpTuf\ComposerStager\Internal\FileSyncer\Service\RsyncFileSyncer;
 
 /**
  * @covers \Drupal\package_manager\FileSyncerFactory
diff --git a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
index 0dae050e06..b094bf13b1 100644
--- a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
+++ b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
@@ -29,7 +29,7 @@ use GuzzleHttp\Handler\MockHandler;
 use GuzzleHttp\HandlerStack;
 use GuzzleHttp\Psr7\Response;
 use GuzzleHttp\Psr7\Utils;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactory;
+use PhpTuf\ComposerStager\Internal\Path\Factory\PathFactory;
 use Psr\Http\Message\RequestInterface;
 use Symfony\Component\Filesystem\Filesystem;
 
diff --git a/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php
index 05fa39946e..b556127962 100644
--- a/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php
+++ b/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php
@@ -10,7 +10,7 @@ use Drupal\package_manager\Event\CollectPathsToExcludeEvent;
 use Drupal\package_manager\PathExcluder\SqliteDatabaseExcluder;
 use Drupal\package_manager\PathLocator;
 use Drupal\Tests\package_manager\Kernel\PackageManagerKernelTestBase;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 
 /**
  * @covers \Drupal\package_manager\PathExcluder\SqliteDatabaseExcluder
diff --git a/package_manager/tests/src/Kernel/RsyncValidatorTest.php b/package_manager/tests/src/Kernel/RsyncValidatorTest.php
index 807636be9a..54b4aae401 100644
--- a/package_manager/tests/src/Kernel/RsyncValidatorTest.php
+++ b/package_manager/tests/src/Kernel/RsyncValidatorTest.php
@@ -8,8 +8,9 @@ use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\ValidationResult;
 use Drupal\package_manager\Validator\RsyncValidator;
-use PhpTuf\ComposerStager\Domain\Exception\LogicException;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\API\Exception\LogicException;
+use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\Internal\Translation\Value\TranslatableMessage;
 
 /**
  * @covers \Drupal\package_manager\Validator\RsyncValidator
@@ -21,7 +22,7 @@ class RsyncValidatorTest extends PackageManagerKernelTestBase {
   /**
    * The mocked executable finder.
    *
-   * @var \PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface
+   * @var \PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface
    */
   private $executableFinder;
 
@@ -120,7 +121,8 @@ class RsyncValidatorTest extends PackageManagerKernelTestBase {
    * Tests that the stage cannot be created if rsync is selected, but not found.
    */
   public function testPreCreateFailsIfRsyncNotFound(): void {
-    $this->executableFinder->find('rsync')->willThrow(new LogicException('Nope!'));
+    $message = new TranslatableMessage('Nope!');
+    $this->executableFinder->find('rsync')->willThrow(new LogicException($message));
 
     $result = ValidationResult::createError([
       t('<code>rsync</code> is not available.'),
diff --git a/package_manager/tests/src/Kernel/ServicesTest.php b/package_manager/tests/src/Kernel/ServicesTest.php
index e9d81754f0..26862671b2 100644
--- a/package_manager/tests/src/Kernel/ServicesTest.php
+++ b/package_manager/tests/src/Kernel/ServicesTest.php
@@ -8,8 +8,8 @@ use Drupal\KernelTests\KernelTestBase;
 use Drupal\package_manager\ExecutableFinder;
 use Drupal\package_manager\ProcessFactory;
 use Drupal\Tests\package_manager\Traits\AssertPreconditionsTrait;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Process\ProcessFactoryInterface;
-use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface;
+use PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface;
 
 /**
  * Tests that Package Manager services are wired correctly.
diff --git a/package_manager/tests/src/Kernel/StageBaseTest.php b/package_manager/tests/src/Kernel/StageBaseTest.php
index a1547f03d9..61e4939a58 100644
--- a/package_manager/tests/src/Kernel/StageBaseTest.php
+++ b/package_manager/tests/src/Kernel/StageBaseTest.php
@@ -22,9 +22,11 @@ use Drupal\package_manager\Validator\WritableFileSystemValidator;
 use Drupal\package_manager_bypass\LoggingBeginner;
 use Drupal\package_manager_bypass\LoggingCommitter;
 use Drupal\package_manager_bypass\NoOpStager;
-use PhpTuf\ComposerStager\Domain\Exception\InvalidArgumentException;
-use PhpTuf\ComposerStager\Domain\Exception\PreconditionException;
-use PhpTuf\ComposerStager\Domain\Service\Precondition\PreconditionInterface;
+use PhpTuf\ComposerStager\API\Exception\ExceptionInterface;
+use PhpTuf\ComposerStager\API\Exception\InvalidArgumentException;
+use PhpTuf\ComposerStager\API\Exception\PreconditionException;
+use PhpTuf\ComposerStager\API\Precondition\Service\PreconditionInterface;
+use PhpTuf\ComposerStager\Internal\Translation\Value\TranslatableMessage;
 use Psr\Log\LogLevel;
 use ColinODell\PsrTestLogger\TestLogger;
 
@@ -227,11 +229,11 @@ class StageBaseTest extends PackageManagerKernelTestBase {
       // simulate an attempt to destroy the stage while it's being applied, for
       // testing purposes.
       $event->stage->destroy($force);
-      // @see \PhpTuf\ComposerStager\Infrastructure\Service\Precondition\StagingDirDoesNotExist
+      // @see \PhpTuf\ComposerStager\Internal\Precondition\Service\StagingDirDoesNotExist
       LoggingCommitter::setException(
         new PreconditionException(
           $this->prophesize(PreconditionInterface::class)->reveal(),
-          'Stage directory does not exist',
+          new TranslatableMessage('Stage directory does not exist'),
         )
       );
     };
@@ -359,14 +361,20 @@ class StageBaseTest extends PackageManagerKernelTestBase {
     $stage->create();
     $stage->require(['drupal/core:9.8.1']);
 
-    $thrown_message = 'A very bad thing happened';
+    $throwable_arguments = [
+      'A very bad thing happened',
+      123,
+    ];
+    // Composer Stager's exception messages are usually translatable, so they
+    // need to be wrapped by a TranslatableMessage object.
+    if (is_subclass_of($thrown_class, ExceptionInterface::class)) {
+      $throwable_arguments[0] = new TranslatableMessage($throwable_arguments[0]);
+    }
     // PreconditionException requires a preconditions object.
     if ($thrown_class === PreconditionException::class) {
-      $throwable = new PreconditionException($this->prophesize(PreconditionInterface::class)->reveal(), $thrown_message, 123);
-    }
-    else {
-      $throwable = new $thrown_class($thrown_message, 123);
+      array_unshift($throwable_arguments, $this->createMock(PreconditionInterface::class));
     }
+    $throwable = new $thrown_class(...$throwable_arguments);
     LoggingCommitter::setException($throwable);
 
     try {
@@ -374,19 +382,19 @@ class StageBaseTest extends PackageManagerKernelTestBase {
       $this->fail('Expected an exception.');
     }
     catch (\Throwable $exception) {
+      $this->assertInstanceOf($expected_class, $exception);
+      $this->assertSame(123, $exception->getCode());
+
       // This needs to be done because we always use the message from
       // \Drupal\package_manager\Stage::getFailureMarkerMessage() when throwing
       // ApplyFailedException.
       if ($expected_class == ApplyFailedException::class) {
         $class_in_message = get_class($throwable);
-        $thrown_message = "/^Staged changes failed to apply, and the site is in an indeterminate state. It is strongly recommended to restore the code and database from a backup. Caused by $class_in_message, with this message: A very bad thing happened\nBacktrace:\n#0 .*/";
+        $this->assertMatchesRegularExpression("/^Staged changes failed to apply, and the site is in an indeterminate state. It is strongly recommended to restore the code and database from a backup. Caused by $class_in_message, with this message: A very bad thing happened\nBacktrace:\n#0 .*/", $exception->getMessage());
       }
       else {
-        $thrown_message = "/^$thrown_message$/";
+        $this->assertSame('A very bad thing happened', $exception->getMessage());
       }
-      $this->assertInstanceOf($expected_class, $exception);
-      $this->assertMatchesRegularExpression($thrown_message, $exception->getMessage());
-      $this->assertSame(123, $exception->getCode());
 
       $failure_marker = $this->container->get(FailureMarker::class);
       if ($exception instanceof ApplyFailedException) {
@@ -644,7 +652,7 @@ class StageBaseTest extends PackageManagerKernelTestBase {
    */
   public function testCollectPathsToExclude(): void {
     $this->addEventTestListener(function (CollectPathsToExcludeEvent $event): void {
-      $event->add(['exclude/me']);
+      $event->add('exclude/me');
     }, CollectPathsToExcludeEvent::class);
 
     // On pre-create and pre-apply, ensure that the excluded path is known to
@@ -676,7 +684,7 @@ class StageBaseTest extends PackageManagerKernelTestBase {
     $committer = $this->container->get('package_manager.committer');
     $committer_args = $committer->getInvocationArguments();
     $this->assertCount(1, $committer_args);
-    /** @var \PhpTuf\ComposerStager\Domain\Value\PathList\PathListInterface $path_list */
+    /** @var \PhpTuf\ComposerStager\API\Path\Value\PathListInterface $path_list */
     $path_list = $committer_args[0][2];
     $this->assertContains('PACKAGE_MANAGER_FAILURE.yml', $path_list->getAll());
   }
diff --git a/package_manager/tests/src/Kernel/StatusCheckTraitTest.php b/package_manager/tests/src/Kernel/StatusCheckTraitTest.php
index fb9ceaa5ab..ba6e71e4a9 100644
--- a/package_manager/tests/src/Kernel/StatusCheckTraitTest.php
+++ b/package_manager/tests/src/Kernel/StatusCheckTraitTest.php
@@ -23,7 +23,7 @@ class StatusCheckTraitTest extends PackageManagerKernelTestBase {
    */
   public function testPathsToExcludeCollected(): void {
     $this->addEventTestListener(function (CollectPathsToExcludeEvent $event): void {
-      $event->add(['/junk/drawer']);
+      $event->add('/junk/drawer');
     }, CollectPathsToExcludeEvent::class);
 
     $status_check_called = FALSE;
diff --git a/package_manager/tests/src/Kernel/SymlinkValidatorTest.php b/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
index fa284bb462..1f59dc4c8a 100644
--- a/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
+++ b/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
@@ -8,7 +8,7 @@ use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Exception\StageEventException;
 use Drupal\package_manager\PathLocator;
 use Drupal\package_manager\ValidationResult;
-use PhpTuf\ComposerStager\Domain\Service\Host\HostInterface;
+use PhpTuf\ComposerStager\Internal\Host\Service\HostInterface;
 
 /**
  * @covers \Drupal\package_manager\Validator\SymlinkValidator
@@ -47,7 +47,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
 
     link($project_root . '/composer.json', $project_root . '/composer.link');
     $result = ValidationResult::createError([
-      t('The active directory at "@dir" contains hard links, which is not supported. The first one is "@dir/composer.json".', [
+      t('The active directory at @dir contains hard links, which is not supported. The first one is @dir/composer.json.', [
         '@dir' => $project_root,
       ]),
     ]);
@@ -63,7 +63,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
 
     symlink($project_root . '/composer.json', $project_root . '/composer.link');
     $result = ValidationResult::createError([
-      t('The active directory at "@dir" contains absolute links, which is not supported. The first one is "@dir/composer.link".', [
+      t('The active directory at @dir contains absolute links, which is not supported. The first one is @dir/composer.link.', [
         '@dir' => $project_root,
       ]),
     ]);
@@ -84,7 +84,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
     chdir($project_root);
     symlink('../hello.txt', 'fail.txt');
     $result = ValidationResult::createError([
-      t('The active directory at "@dir" contains links that point outside the codebase, which is not supported. The first one is "@dir/fail.txt".', [
+      t('The active directory at @dir contains links that point outside the codebase, which is not supported. The first one is @dir/fail.txt.', [
         '@dir' => $project_root,
       ]),
     ]);
@@ -111,7 +111,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
     symlink('../hello.txt', 'fail.txt');
 
     $result = ValidationResult::createError([
-      t('The staging directory at "@dir" contains links that point outside the codebase, which is not supported. The first one is "@dir/fail.txt".', [
+      t('The staging directory at @dir contains links that point outside the codebase, which is not supported. The first one is @dir/fail.txt.', [
         '@dir' => $stage_dir,
       ]),
     ]);
@@ -136,7 +136,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
         'php',
         [
           ValidationResult::createError([
-            t('The active directory at "<PROJECT_ROOT>" contains symlinks that point to a directory, which is not supported. The first one is "<PROJECT_ROOT>/modules/custom/example_module".'),
+            t('The active directory at <PROJECT_ROOT> contains symlinks that point to a directory, which is not supported. The first one is <PROJECT_ROOT>/modules/custom/example_module.'),
           ]),
         ],
       ],
@@ -178,9 +178,16 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
    * Tests that symlinks are not supported on Windows, even if they're safe.
    */
   public function testSymlinksNotAllowedOnWindows(): void {
-    $host = $this->prophesize(HostInterface::class);
-    $host->isWindows()->willReturn(TRUE);
-    $this->container->set(HostInterface::class, $host->reveal());
+    $this->container->set(HostInterface::class, new class () implements HostInterface {
+
+      /**
+       * {@inheritdoc}
+       */
+      public static function isWindows(): bool {
+        return TRUE;
+      }
+
+    });
 
     $project_root = $this->container->get(PathLocator::class)
       ->getProjectRoot();
@@ -190,7 +197,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
     symlink('composer.json', 'composer.link');
 
     $result = ValidationResult::createError([
-      t('The active directory at "@dir" contains links, which is not supported on Windows. The first one is "@dir/composer.link".', [
+      t('The active directory at @dir contains links, which is not supported on Windows. The first one is @dir/composer.link.', [
         '@dir' => $project_root,
       ]),
     ]);
diff --git a/package_manager/tests/src/Unit/ProcessFactoryTest.php b/package_manager/tests/src/Unit/ProcessFactoryTest.php
index a6d1c4fd07..c83e6d1e79 100644
--- a/package_manager/tests/src/Unit/ProcessFactoryTest.php
+++ b/package_manager/tests/src/Unit/ProcessFactoryTest.php
@@ -4,8 +4,11 @@ declare(strict_types = 1);
 
 namespace Drupal\Tests\package_manager\Unit;
 
+use Drupal\Core\File\FileSystemInterface;
 use Drupal\package_manager\ProcessFactory;
 use Drupal\Tests\UnitTestCase;
+use PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface;
+use PhpTuf\ComposerStager\Internal\Process\Factory\ProcessFactory as StagerProcessFactory;
 
 /**
  * @coversDefaultClass \Drupal\package_manager\ProcessFactory
@@ -18,9 +21,14 @@ class ProcessFactoryTest extends UnitTestCase {
    * Tests that the process factory prepends the PHP directory to PATH.
    */
   public function testPhpDirectoryPrependedToPath(): void {
+    $decorated = new StagerProcessFactory(
+      $this->createMock(TranslatableFactoryInterface::class),
+    );
+
     $factory = new ProcessFactory(
-      $this->prophesize('\Drupal\Core\File\FileSystemInterface')->reveal(),
-      $this->getConfigFactoryStub()
+      $this->createMock(FileSystemInterface::class),
+      $this->getConfigFactoryStub(),
+      $decorated,
     );
 
     // Ensure that the directory of the PHP interpreter can be found.
diff --git a/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php b/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php
index a1443385f8..6d99082334 100644
--- a/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php
+++ b/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php
@@ -33,7 +33,7 @@ class ProcessOutputCallbackTest extends UnitTestCase {
     $callback = new ProcessOutputCallback();
 
     $this->expectException(\InvalidArgumentException::class);
-    $this->expectExceptionMessage("Unsupported output type: 'telegram'");
+    $this->expectExceptionMessage("Unsupported output type: 'TELEGRAM'");
     $callback('telegram', 'Into the void...');
   }
 
diff --git a/src/CronUpdateStage.php b/src/CronUpdateStage.php
index 15f39ee97d..646ab893fd 100644
--- a/src/CronUpdateStage.php
+++ b/src/CronUpdateStage.php
@@ -22,10 +22,10 @@ use Drupal\package_manager\PathLocator;
 use Drupal\package_manager\ProjectInfo;
 use Drupal\update\ProjectRelease;
 use GuzzleHttp\Psr7\Uri as GuzzleUri;
-use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface;
-use PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Core\CommitterInterface;
+use PhpTuf\ComposerStager\API\Core\StagerInterface;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
 
@@ -85,11 +85,11 @@ class CronUpdateStage extends UpdateStage implements CronInterface {
    *   The Composer inspector service.
    * @param \Drupal\package_manager\PathLocator $pathLocator
    *   The path locator service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface $beginner
+   * @param \PhpTuf\ComposerStager\API\Core\BeginnerInterface $beginner
    *   The beginner service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface $stager
+   * @param \PhpTuf\ComposerStager\API\Core\StagerInterface $stager
    *   The stager service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface $committer
+   * @param \PhpTuf\ComposerStager\API\Core\CommitterInterface $committer
    *   The committer service.
    * @param \Drupal\Core\File\FileSystemInterface $fileSystem
    *   The file system service.
@@ -99,7 +99,7 @@ class CronUpdateStage extends UpdateStage implements CronInterface {
    *   The shared tempstore factory.
    * @param \Drupal\Component\Datetime\TimeInterface $time
    *   The time service.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $pathFactory
    *   The path factory service.
    * @param \Drupal\package_manager\FailureMarker $failureMarker
    *   The failure marker service.
diff --git a/src/UpdateStage.php b/src/UpdateStage.php
index f5bf4e0f66..e26f706086 100644
--- a/src/UpdateStage.php
+++ b/src/UpdateStage.php
@@ -12,10 +12,10 @@ use Drupal\package_manager\ComposerInspector;
 use Drupal\package_manager\FailureMarker;
 use Drupal\package_manager\PathLocator;
 use Drupal\package_manager\StageBase;
-use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
-use PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface;
-use PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface;
-use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
+use PhpTuf\ComposerStager\API\Core\BeginnerInterface;
+use PhpTuf\ComposerStager\API\Core\CommitterInterface;
+use PhpTuf\ComposerStager\API\Core\StagerInterface;
+use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
 
 /**
@@ -40,11 +40,11 @@ class UpdateStage extends StageBase {
    *   The Composer inspector service.
    * @param \Drupal\package_manager\PathLocator $pathLocator
    *   The path locator service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface $beginner
+   * @param \PhpTuf\ComposerStager\API\Core\BeginnerInterface $beginner
    *   The beginner service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface $stager
+   * @param \PhpTuf\ComposerStager\API\Core\StagerInterface $stager
    *   The stager service.
-   * @param \PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface $committer
+   * @param \PhpTuf\ComposerStager\API\Core\CommitterInterface $committer
    *   The committer service.
    * @param \Drupal\Core\File\FileSystemInterface $fileSystem
    *   The file system service.
@@ -54,7 +54,7 @@ class UpdateStage extends StageBase {
    *   The shared tempstore factory.
    * @param \Drupal\Component\Datetime\TimeInterface $time
    *   The time service.
-   * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
+   * @param \PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface $pathFactory
    *   The path factory service.
    * @param \Drupal\package_manager\FailureMarker $failureMarker
    *   The failure marker service.
diff --git a/tests/src/Functional/ComposerStagerOperationFailureTest.php b/tests/src/Functional/ComposerStagerOperationFailureTest.php
index f75342b51b..4263a4d6a1 100644
--- a/tests/src/Functional/ComposerStagerOperationFailureTest.php
+++ b/tests/src/Functional/ComposerStagerOperationFailureTest.php
@@ -7,8 +7,9 @@ namespace Drupal\Tests\automatic_updates\Functional;
 use Drupal\package_manager_bypass\LoggingBeginner;
 use Drupal\package_manager_bypass\LoggingCommitter;
 use Drupal\package_manager_bypass\NoOpStager;
-use PhpTuf\ComposerStager\Domain\Exception\InvalidArgumentException;
-use PhpTuf\ComposerStager\Domain\Exception\LogicException;
+use PhpTuf\ComposerStager\API\Exception\InvalidArgumentException;
+use PhpTuf\ComposerStager\API\Exception\LogicException;
+use PhpTuf\ComposerStager\Internal\Translation\Value\TranslatableMessage;
 
 /**
  * @covers \Drupal\automatic_updates\Form\UpdaterForm
@@ -38,7 +39,8 @@ class ComposerStagerOperationFailureTest extends UpdaterFormTestBase {
     $page->hasButton('Update to 9.8.1');
 
     // Make the specified Composer Stager operation class throw an exception.
-    $exception = new $exception_class('Failure from inside ' . $service_class);
+    $message = new TranslatableMessage("Failure from inside $service_class");
+    $exception = new $exception_class($message);
     call_user_func([$service_class, 'setException'], $exception);
 
     // Start the update.
diff --git a/tests/src/Kernel/CronUpdateStageTest.php b/tests/src/Kernel/CronUpdateStageTest.php
index b94b20086f..77a52f7f8f 100644
--- a/tests/src/Kernel/CronUpdateStageTest.php
+++ b/tests/src/Kernel/CronUpdateStageTest.php
@@ -349,7 +349,7 @@ class CronUpdateStageTest extends AutomaticUpdatesKernelTestBase {
 
     $listener = function (PostRequireEvent $event) use (&$cron_stage_dir, $original_stage_directory): void {
       $this->assertDirectoryDoesNotExist($original_stage_directory);
-      $cron_stage_dir = $this->container->get('package_manager.stager')->getInvocationArguments()[0][1]->resolve();
+      $cron_stage_dir = $this->container->get('package_manager.stager')->getInvocationArguments()[0][1]->resolved();
       $this->assertSame($event->stage->getStageDirectory(), $cron_stage_dir);
       $this->assertDirectoryExists($cron_stage_dir);
     };
diff --git a/tests/src/Kernel/UpdateStageTest.php b/tests/src/Kernel/UpdateStageTest.php
index e5a4476453..ab47c3ce61 100644
--- a/tests/src/Kernel/UpdateStageTest.php
+++ b/tests/src/Kernel/UpdateStageTest.php
@@ -9,7 +9,9 @@ use Drupal\package_manager\Exception\ApplyFailedException;
 use Drupal\package_manager\Exception\StageException;
 use Drupal\package_manager_bypass\LoggingCommitter;
 use Drupal\Tests\user\Traits\UserCreationTrait;
-use PhpTuf\ComposerStager\Domain\Exception\InvalidArgumentException;
+use PhpTuf\ComposerStager\API\Exception\ExceptionInterface;
+use PhpTuf\ComposerStager\API\Exception\InvalidArgumentException;
+use PhpTuf\ComposerStager\Internal\Translation\Value\TranslatableMessage;
 
 /**
  * @coversDefaultClass \Drupal\automatic_updates\UpdateStage
@@ -182,12 +184,17 @@ class UpdateStageTest extends AutomaticUpdatesKernelTestBase {
     ]);
     $stage->stage();
     $thrown_message = 'A very bad thing happened';
+    // Composer Stager's exception messages are usually translatable, so they
+    // need to be wrapped by a TranslatableMessage object.
+    if (is_subclass_of($thrown_class, ExceptionInterface::class)) {
+      $thrown_message = new TranslatableMessage($thrown_message);
+    }
     LoggingCommitter::setException(new $thrown_class($thrown_message, 123));
     $this->expectException($expected_class);
     $expected_message = $expected_class === ApplyFailedException::class ?
       "Automatic updates failed to apply, and the site is in an indeterminate state. Consider restoring the code and database from a backup."
       : $thrown_message;
-    $this->expectExceptionMessage($expected_message);
+    $this->expectExceptionMessage((string) $expected_message);
     $this->expectExceptionCode(123);
     $stage->apply();
   }
-- 
GitLab