Handle workspace interdependencies in `downgrade --tighten` (#4346)

diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 9cea5bc..e2b2c52 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -1378,7 +1378,12 @@
 
     final toTighten = <(Package, PackageRange)>[];
 
+    // Keep track of the versions of workspace packages - these are not included
+    // in the lockfile.
+    final workspaceVersions = <String, Version>{};
+
     for (final package in workspaceRoot.transitiveWorkspace) {
+      workspaceVersions[package.name] = package.version;
       if (packagesToUpgrade.isEmpty) {
         for (final range in [
           ...package.dependencies.values,
@@ -1400,10 +1405,12 @@
     for (final (package, range) in toTighten) {
       final changesForPackage = result[package] ??= {};
       final constraint = (changesForPackage[range] ?? range).constraint;
+
       final resolvedVersion =
           (packageVersions?.firstWhere((p) => p.name == range.name) ??
-                  lockFile.packages[range.name])!
-              .version;
+                      lockFile.packages[range.name])
+                  ?.version ??
+              workspaceVersions[range.name]!;
       if (range.source is HostedSource && constraint.isAny) {
         changesForPackage[range] = range
             .toRef()
diff --git a/test/downgrade/tighten_test.dart b/test/downgrade/tighten_test.dart
index 7505b83..3cec338 100644
--- a/test/downgrade/tighten_test.dart
+++ b/test/downgrade/tighten_test.dart
@@ -30,4 +30,35 @@
       ),
     );
   });
+
+  test('--tighten works for workspace with internal dependencies', () async {
+    await servePackages();
+
+    await d.dir(appPath, [
+      d.libPubspec(
+        'myapp',
+        '1.2.3',
+        extras: {
+          'workspace': ['pkgs/a'],
+        },
+        sdk: '^3.5.0',
+      ),
+      d.dir('pkgs', [
+        d.dir('a', [
+          d.libPubspec(
+            'a',
+            '1.1.1',
+            deps: {'myapp': '^1.0.0'},
+            resolutionWorkspace: true,
+          ),
+        ]),
+      ]),
+    ]).create();
+
+    await pubDowngrade(
+      args: ['--tighten'],
+      output: contains('myapp: ^1.0.0 -> ^1.2.3'),
+      environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+    );
+  });
 }
diff --git a/test/test_pub.dart b/test/test_pub.dart
index 1816670..463b4dc 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -1130,7 +1130,7 @@
 /// of maps, one of them having the property `k` with value `v`, recurse into
 /// that map.
 ///
-/// Cast the result as a <T>.
+/// Cast the result as a `<T>`.
 T dig<T>(dynamic json, List<dynamic> path) {
   for (var i = 0; i < path.length; i++) {
     switch (path[i]) {