fix: force a single version per Gradle module when pinning (#1608)

Gradle selects one version per group:artifact and ignores classifiers,
so forcing each classified root separately (e.g. a main jar and its
test-fixtures jar at different versions) made resolution unsatisfiable.
Group roots by module and force only the defining version: the
unclassified root, or the highest classified request.

Also stop the resolver plugin's detached-configuration retry from
undermining pins: skip it when the main configuration fully resolved,
and re-apply the forced modules when it runs, since detached
configurations never see `configurations.all`.

Co-Authored-By: Claude <noreply@anthropic.com>
diff --git a/MODULE.bazel b/MODULE.bazel
index 1ffd2ff..cf48fe5 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -320,6 +320,21 @@
     testonly = "true",
     coordinates = "org.junit.jupiter:junit-jupiter-api",
 )
+
+# Requests the main jar and the test-fixtures jar of one module at different
+# versions. Gradle selects a single version per module, so the pinned policy
+# must only force one of them.
+# https://github.com/bazel-contrib/rules_jvm_external/pull/1608
+dev_maven.install(
+    name = "gradle_classifier_pinning",
+    artifacts = [
+        "com.squareup.misk:misk-feature:2026.07.11.061457-fa37275",
+        "com.squareup.misk:misk-feature:jar:test-fixtures:2026.06.30.120630-d342aab",
+    ],
+    lock_file = "//tests/custom_maven_install:gradle_classifier_pinning_install.json",
+    resolver = "gradle",
+    version_conflict_policy = "pinned",
+)
 dev_maven.install(
     name = "global_exclusion_testing",
     artifacts = [
@@ -1044,6 +1059,7 @@
     "forcing_versions",
     "from_files",
     "global_exclusion_testing",
+    "gradle_classifier_pinning",
     "m2local_testing",
     "m2local_testing_ignore_empty_files",
 
diff --git a/private/extensions/maven.bzl b/private/extensions/maven.bzl
index 0aa500d..d64709a 100644
--- a/private/extensions/maven.bzl
+++ b/private/extensions/maven.bzl
@@ -598,11 +598,50 @@
         if k != "to_json" and k != "to_proto" and getattr(s, k, None)
     } | {"version": getattr(s, "version", "")}
 
+def _defines_gradle_module_version(candidate, current):
+    """Whether candidate should force the Gradle module version instead of current."""
+    candidate_classified = bool(getattr(candidate, "classifier", None))
+    current_classified = bool(getattr(current, "classifier", None))
+    if candidate_classified != current_classified:
+        # An unclassified root defines the module version.
+        return current_classified
+    return compare_maven_versions(candidate.version, current.version) == 1
+
+def _select_gradle_forced_versions(artifacts):
+    """Selects the single version to force for each Gradle group:artifact module.
+
+    Gradle resolves one version per module regardless of classifier, so forcing
+    two versions of the same module (for example a main jar and its
+    test-fixtures jar) makes resolution unsatisfiable.
+    """
+    winners = {}
+    for artifact in artifacts:
+        if not getattr(artifact, "version", None):
+            continue
+        key = "%s:%s" % (artifact.group, artifact.artifact)
+        current = winners.get(key)
+        if current == None or _defines_gradle_module_version(artifact, current):
+            winners[key] = artifact
+    return {key: winner.version for key, winner in winners.items()}
+
+def _forces_gradle_module_version(artifact, forced_versions):
+    version = getattr(artifact, "version", None)
+    if not version:
+        return False
+    return version == forced_versions.get("%s:%s" % (artifact.group, artifact.artifact))
+
 def apply_root_version_conflict_policy(artifacts, resolver, version_conflict_policy):
     """Applies the install-level conflict policy to root module artifacts."""
     if resolver not in ["gradle", "maven"] or version_conflict_policy != "pinned":
         return artifacts
 
+    if resolver == "gradle":
+        forced_versions = _select_gradle_forced_versions(artifacts)
+        return [
+            struct(**(remove_fields(artifact) | {"force_version": True})) if _forces_gradle_module_version(artifact, forced_versions) else artifact
+            for artifact in artifacts
+        ]
+
     return [
         struct(**(remove_fields(artifact) | {"force_version": True})) if getattr(artifact, "version", None) else artifact
         for artifact in artifacts
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/gradle/plugin/GradleDependencyModelBuilder.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/gradle/plugin/GradleDependencyModelBuilder.java
index b53b27c..f1c8b3c 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/gradle/plugin/GradleDependencyModelBuilder.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/gradle/plugin/GradleDependencyModelBuilder.java
@@ -121,6 +121,16 @@
 
     Configuration detachedCfg =
         project.getConfigurations().detachedConfiguration(detachedDeps.toArray(new Dependency[0]));
+    // Detached configurations are not covered by `configurations.all`, so the forced module
+    // versions from the generated build script do not apply to them automatically. Without
+    // them, pinned modules can resolve at a different version during the retry.
+    Set<String> forcedModules =
+        cfg.getResolutionStrategy().getForcedModules().stream()
+            .map(m -> m.getGroup() + ":" + m.getName() + ":" + m.getVersion())
+            .collect(Collectors.toSet());
+    if (!forcedModules.isEmpty()) {
+      detachedCfg.getResolutionStrategy().force(forcedModules.toArray());
+    }
     // Ensure the detached configuration respects the same exclude rules as the original
     // configuration
     if (!cfg.getExcludeRules().isEmpty()) {
@@ -134,9 +144,15 @@
     }
 
     // build the updated dependency graph with the detached configuration for all the
-    // dependencies that we couldn't resolve with the default configuration
+    // dependencies that we couldn't resolve with the default configuration. When everything
+    // resolved, skip the retry: the detached configuration resolves without the main
+    // configuration's attributes, so it can fail or pick different versions, and merging
+    // those results would corrupt an already-complete graph.
+    boolean retryUnresolved = !unresolvedDependenciesRuntimeClasspath.isEmpty();
     List<GradleResolvedDependency> resolvedDetachedRoots =
-        resolveDetachedGraph(detachedCfg, variantGradleResolvedDependencyMap);
+        retryUnresolved
+            ? resolveDetachedGraph(detachedCfg, variantGradleResolvedDependencyMap)
+            : List.of();
 
     List<GradleResolvedDependency> roots =
         Streams.concat(resolvedRoots.stream(), resolvedDetachedRoots.stream())
@@ -149,9 +165,11 @@
     gradleDependencyModel.getResolvedDependencies().addAll(roots);
 
     // if anything is still unresolved, then add it for reporting
-    gradleDependencyModel
-        .getUnresolvedDependencies()
-        .addAll(getUnresolvedDependencies(detachedCfg));
+    if (retryUnresolved) {
+      gradleDependencyModel
+          .getUnresolvedDependencies()
+          .addAll(getUnresolvedDependencies(detachedCfg));
+    }
     return gradleDependencyModel;
   }
 
diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD
index 1898ee7..711baa3 100644
--- a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD
+++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD
@@ -72,7 +72,9 @@
         "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc",
         "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote",
         "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui",
+        "//resolver",
         "//tests/com/github/bazelbuild/rules_jvm_external/resolver",
+        "@rules_jvm_external_deps//:org_apache_maven_maven_model",
         artifact(
             "junit:junit",
             repository_name = "regression_testing_coursier",
diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java
index 1e872cb..c7449bd 100644
--- a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java
+++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java
@@ -21,8 +21,10 @@
 import static org.junit.Assert.fail;
 
 import com.github.bazelbuild.rules_jvm_external.Coordinates;
+import com.github.bazelbuild.rules_jvm_external.resolver.Artifact;
 import com.github.bazelbuild.rules_jvm_external.resolver.DependencyInfo;
 import com.github.bazelbuild.rules_jvm_external.resolver.MavenRepo;
+import com.github.bazelbuild.rules_jvm_external.resolver.ResolutionRequest;
 import com.github.bazelbuild.rules_jvm_external.resolver.ResolutionResult;
 import com.github.bazelbuild.rules_jvm_external.resolver.ResolvedArtifact;
 import com.github.bazelbuild.rules_jvm_external.resolver.Resolver;
@@ -43,12 +45,16 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
 import javax.xml.stream.XMLStreamException;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.DependencyManagement;
+import org.apache.maven.model.Model;
 import org.junit.Test;
 
 @AutoBazelRepository
@@ -388,6 +394,169 @@
   }
 
   @Test
+  public void forcedModuleVersionSweepsUpTestFixturesRequestedAtOlderVersion()
+      throws IOException, XMLStreamException {
+    // With `version_conflict_policy = "pinned"` only the unclassified root is forced. Gradle
+    // selects a single version per module regardless of classifier, so the test-fixtures root
+    // requested at an older version must follow the forced module version.
+    Coordinates mainCoordinates = new Coordinates("com.example:sample:2.0");
+    Coordinates olderTestFixturesCoordinates =
+        new Coordinates("com.example:sample:jar:test-fixtures:1.0");
+    Coordinates selectedTestFixturesCoordinates =
+        new Coordinates("com.example:sample:jar:test-fixtures:2.0");
+    Coordinates mainDepCoordinates = new Coordinates("com.example:main-dep:1.0");
+    Coordinates testFixturesDepCoordinates = new Coordinates("com.example:tf-dep:1.0");
+
+    MavenRepo mavenRepo =
+        MavenRepo.create().add(mainDepCoordinates).add(testFixturesDepCoordinates);
+    GradleModuleMetadataHelper moduleMetadataHelper = new GradleModuleMetadataHelper(mavenRepo);
+
+    Runfiles runfiles =
+        Runfiles.preload().withSourceRepository(AutoBazelRepository_GradleResolverTest.NAME);
+    for (String version : List.of("1.0", "2.0")) {
+      Path metadataPath =
+          Paths.get(
+              runfiles.rlocation(
+                  "rules_jvm_external/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/testFixturesVariant/sample-"
+                      + version
+                      + ".module"));
+      moduleMetadataHelper.addToMavenRepo(
+          new Coordinates("com.example:sample:" + version), Files.readString(metadataPath));
+      mavenRepo.addArtifactOnly(new Coordinates("com.example:sample:jar:test-fixtures:" + version));
+    }
+
+    ResolutionRequest request =
+        new ResolutionRequest()
+            .addRepository(mavenRepo.getPath().toUri())
+            .addArtifact(new Artifact(mainCoordinates, Set.of(), true))
+            .addArtifact(new Artifact(olderTestFixturesCoordinates));
+
+    Graph<Coordinates> resolved = resolver.resolve(request).getResolution();
+
+    assertTrue(resolved.nodes().contains(mainCoordinates));
+    assertTrue(resolved.nodes().contains(selectedTestFixturesCoordinates));
+    assertFalse(resolved.nodes().contains(olderTestFixturesCoordinates));
+    for (Coordinates node : resolved.nodes()) {
+      assertFalse(node.toString(), node.getVersion() == null || node.getVersion().isEmpty());
+    }
+
+    // The variants keep their distinct dependency sets at the selected version.
+    assertEquals(Set.of(mainDepCoordinates), resolved.successors(mainCoordinates));
+    assertEquals(
+        Set.of(mainCoordinates, testFixturesDepCoordinates),
+        resolved.successors(selectedTestFixturesCoordinates));
+  }
+
+  @Test
+  public void forcedVersionOverridesHigherTransitiveRequirementWithoutFailures() {
+    // A forced root version must silently win over transitive requests for a higher version.
+    // Expressing the pin as a strict constraint instead makes Gradle fail those selectors, and
+    // the failures cascade into spurious graph nodes.
+    Coordinates pinned = new Coordinates("com.example:lib:1.0");
+    Coordinates higher = new Coordinates("com.example:lib:2.0");
+    Coordinates app = new Coordinates("com.example:app:1.0");
+
+    Path repo = MavenRepo.create().add(pinned).add(higher).add(app, higher).getPath();
+
+    ResolutionRequest request =
+        new ResolutionRequest()
+            .addRepository(repo.toUri())
+            .addArtifact(new Artifact(app))
+            .addArtifact(new Artifact(pinned, Set.of(), true));
+
+    Graph<Coordinates> resolved = resolver.resolve(request).getResolution();
+
+    assertTrue(resolved.nodes().contains(pinned));
+    assertFalse(resolved.nodes().contains(higher));
+    for (Coordinates node : resolved.nodes()) {
+      assertFalse(node.toString(), node.getVersion() == null || node.getVersion().isEmpty());
+    }
+  }
+
+  @Test
+  public void forcedVersionBelowBomConstraintKeepsBomManagedRootsResolvable() {
+    // Mirrors the Cash Loanstar shape: a BOM manages `lib` at 2.0 while the root pins it at
+    // 1.0 with force_version, and another root is versionless, relying on the BOM. The pin
+    // must win without poisoning the BOM-managed root's resolution.
+    Coordinates pinned = new Coordinates("com.example:lib:1.0");
+    Coordinates higher = new Coordinates("com.example:lib:2.0");
+    Coordinates managed = new Coordinates("com.example:managed:1.0");
+    Coordinates bom = new Coordinates("com.example:bom:1.0");
+
+    Model bomModel = createModel(bom);
+    bomModel.setPackaging("pom");
+    DependencyManagement managedDeps = new DependencyManagement();
+    Dependency libDep = new Dependency();
+    libDep.setGroupId(pinned.getGroupId());
+    libDep.setArtifactId(pinned.getArtifactId());
+    libDep.setVersion(higher.getVersion());
+    managedDeps.addDependency(libDep);
+    Dependency managedDep = new Dependency();
+    managedDep.setGroupId(managed.getGroupId());
+    managedDep.setArtifactId(managed.getArtifactId());
+    managedDep.setVersion(managed.getVersion());
+    managedDeps.addDependency(managedDep);
+    bomModel.setDependencyManagement(managedDeps);
+
+    Path repo =
+        MavenRepo.create().add(pinned).add(higher).add(managed).add(bomModel).getPath();
+
+    ResolutionRequest request =
+        new ResolutionRequest()
+            .addRepository(repo.toUri())
+            .addBom(bom)
+            .addArtifact(new Artifact(pinned, Set.of(), true))
+            .addArtifact(new Artifact(new Coordinates("com.example:managed")));
+
+    Graph<Coordinates> resolved = resolver.resolve(request).getResolution();
+
+    assertTrue(resolved.nodes().contains(pinned));
+    assertTrue(resolved.nodes().contains(managed));
+    assertFalse(resolved.nodes().contains(higher));
+    for (Coordinates node : resolved.nodes()) {
+      assertFalse(node.toString(), node.getVersion() == null || node.getVersion().isEmpty());
+    }
+  }
+
+  @Test
+  public void forcedVersionSurvivesDetachedConfigurationRetries()
+      throws IOException, XMLStreamException {
+    // The plugin re-resolves all declared dependencies in a detached configuration, which does
+    // not inherit `configurations.all { resolutionStrategy.force(...) }`. Without the force, a
+    // transitive strict constraint deadlocks against the pinned version there, and the failed
+    // selectors leak into the graph.
+    Coordinates pinned = new Coordinates("com.example:lib:1.0");
+    Coordinates higher = new Coordinates("com.example:lib:2.0");
+    Coordinates appCoordinates = new Coordinates("com.example:app:1.0");
+
+    MavenRepo mavenRepo = MavenRepo.create().add(pinned).add(higher);
+    GradleModuleMetadataHelper moduleMetadataHelper = new GradleModuleMetadataHelper(mavenRepo);
+
+    Runfiles runfiles =
+        Runfiles.preload().withSourceRepository(AutoBazelRepository_GradleResolverTest.NAME);
+    Path metadataPath =
+        Paths.get(
+            runfiles.rlocation(
+                "rules_jvm_external/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/strictTransitiveConstraint/app-1.0.module"));
+    // app depends on lib with `strictly 2.0` in its Gradle module metadata.
+    moduleMetadataHelper.addToMavenRepo(appCoordinates, Files.readString(metadataPath));
+
+    ResolutionRequest request =
+        new ResolutionRequest()
+            .addRepository(mavenRepo.getPath().toUri())
+            .addArtifact(new Artifact(appCoordinates))
+            .addArtifact(new Artifact(pinned, Set.of(), true));
+
+    Graph<Coordinates> resolved = resolver.resolve(request).getResolution();
+
+    assertTrue(resolved.nodes().contains(pinned));
+    assertFalse(resolved.nodes().contains(higher));
+    for (Coordinates node : resolved.nodes()) {
+      assertFalse(node.toString(), node.getVersion() == null || node.getVersion().isEmpty());
+    }
+  }
+
+  @Test
   public void shouldRecordCorrectShaForResolvedVersionNotConflictingVersion() {
     // When there's a version conflict, the paths map should contain only the resolved version,
     // not the conflicting lower version. This ensures we record the correct SHA for the artifact.
diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/BUILD b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/BUILD
index 06dbbfe..d1543dc 100644
--- a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/BUILD
+++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/BUILD
@@ -8,7 +8,9 @@
         "jvmAndAndroidVariants/sample-jvm-1.0.module",
         "simpleJvmVariant/sample-1.0.module",
         "simpleJvmVariant/sample-jvm-1.0.module",
+        "strictTransitiveConstraint/app-1.0.module",
         "testFixturesVariant/sample-1.0.module",
+        "testFixturesVariant/sample-2.0.module",
     ],
     visibility = ["//tests/com/github/bazelbuild/rules_jvm_external:__subpackages__"],
 )
diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/strictTransitiveConstraint/app-1.0.module b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/strictTransitiveConstraint/app-1.0.module
new file mode 100644
index 0000000..8803eec
--- /dev/null
+++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/strictTransitiveConstraint/app-1.0.module
@@ -0,0 +1,65 @@
+{
+  "formatVersion": "1.1",
+  "component": {
+    "group": "com.example",
+    "module": "app",
+    "version": "1.0",
+    "attributes": { "org.gradle.status": "release" }
+  },
+  "variants": [
+    {
+      "name": "apiElements",
+      "attributes": {
+        "org.gradle.category": "library",
+        "org.gradle.dependency.bundling": "external",
+        "org.gradle.jvm.environment": "standard-jvm",
+        "org.gradle.jvm.version": 11,
+        "org.gradle.libraryelements": "jar",
+        "org.gradle.usage": "java-api"
+      },
+      "dependencies": [
+        {
+          "group": "com.example",
+          "module": "lib",
+          "version": { "strictly": "2.0" }
+        }
+      ],
+      "files": [
+        {
+          "name": "app-1.0.jar",
+          "url": "app-1.0.jar",
+          "size": 100,
+          "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+          "md5": "d41d8cd98f00b204e9800998ecf8427e"
+        }
+      ]
+    },
+    {
+      "name": "runtimeElements",
+      "attributes": {
+        "org.gradle.category": "library",
+        "org.gradle.dependency.bundling": "external",
+        "org.gradle.jvm.environment": "standard-jvm",
+        "org.gradle.jvm.version": 11,
+        "org.gradle.libraryelements": "jar",
+        "org.gradle.usage": "java-runtime"
+      },
+      "dependencies": [
+        {
+          "group": "com.example",
+          "module": "lib",
+          "version": { "strictly": "2.0" }
+        }
+      ],
+      "files": [
+        {
+          "name": "app-1.0.jar",
+          "url": "app-1.0.jar",
+          "size": 100,
+          "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+          "md5": "d41d8cd98f00b204e9800998ecf8427e"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/testFixturesVariant/sample-2.0.module b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/testFixturesVariant/sample-2.0.module
new file mode 100644
index 0000000..898613d
--- /dev/null
+++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/fixtures/testFixturesVariant/sample-2.0.module
@@ -0,0 +1,141 @@
+{
+  "formatVersion": "1.1",
+  "component": {
+    "group": "com.example",
+    "module": "sample",
+    "version": "2.0",
+    "attributes": { "org.gradle.status": "release" }
+  },
+  "variants": [
+    {
+      "name": "apiElements",
+      "attributes": {
+        "org.gradle.category": "library",
+        "org.gradle.dependency.bundling": "external",
+        "org.gradle.jvm.environment": "standard-jvm",
+        "org.gradle.jvm.version": 11,
+        "org.gradle.libraryelements": "jar",
+        "org.gradle.usage": "java-api"
+      },
+      "dependencies": [
+        {
+          "group": "com.example",
+          "module": "main-dep",
+          "version": { "requires": "1.0" }
+        }
+      ],
+      "files": [
+        {
+          "name": "sample-2.0.jar",
+          "url": "sample-2.0.jar",
+          "size": 100,
+          "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+          "md5": "d41d8cd98f00b204e9800998ecf8427e"
+        }
+      ]
+    },
+    {
+      "name": "runtimeElements",
+      "attributes": {
+        "org.gradle.category": "library",
+        "org.gradle.dependency.bundling": "external",
+        "org.gradle.jvm.environment": "standard-jvm",
+        "org.gradle.jvm.version": 11,
+        "org.gradle.libraryelements": "jar",
+        "org.gradle.usage": "java-runtime"
+      },
+      "dependencies": [
+        {
+          "group": "com.example",
+          "module": "main-dep",
+          "version": { "requires": "1.0" }
+        }
+      ],
+      "files": [
+        {
+          "name": "sample-2.0.jar",
+          "url": "sample-2.0.jar",
+          "size": 100,
+          "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+          "md5": "d41d8cd98f00b204e9800998ecf8427e"
+        }
+      ]
+    },
+    {
+      "name": "testFixturesApiElements",
+      "attributes": {
+        "org.gradle.category": "library",
+        "org.gradle.dependency.bundling": "external",
+        "org.gradle.jvm.version": 11,
+        "org.gradle.libraryelements": "jar",
+        "org.gradle.usage": "java-api"
+      },
+      "dependencies": [
+        {
+          "group": "com.example",
+          "module": "sample",
+          "version": { "requires": "2.0" }
+        },
+        {
+          "group": "com.example",
+          "module": "tf-dep",
+          "version": { "requires": "1.0" }
+        }
+      ],
+      "files": [
+        {
+          "name": "sample-2.0-test-fixtures.jar",
+          "url": "sample-2.0-test-fixtures.jar",
+          "size": 100,
+          "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+          "md5": "d41d8cd98f00b204e9800998ecf8427e"
+        }
+      ],
+      "capabilities": [
+        {
+          "group": "com.example",
+          "name": "sample-test-fixtures",
+          "version": "2.0"
+        }
+      ]
+    },
+    {
+      "name": "testFixturesRuntimeElements",
+      "attributes": {
+        "org.gradle.category": "library",
+        "org.gradle.dependency.bundling": "external",
+        "org.gradle.jvm.version": 11,
+        "org.gradle.libraryelements": "jar",
+        "org.gradle.usage": "java-runtime"
+      },
+      "dependencies": [
+        {
+          "group": "com.example",
+          "module": "sample",
+          "version": { "requires": "2.0" }
+        },
+        {
+          "group": "com.example",
+          "module": "tf-dep",
+          "version": { "requires": "1.0" }
+        }
+      ],
+      "files": [
+        {
+          "name": "sample-2.0-test-fixtures.jar",
+          "url": "sample-2.0-test-fixtures.jar",
+          "size": 100,
+          "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+          "md5": "d41d8cd98f00b204e9800998ecf8427e"
+        }
+      ],
+      "capabilities": [
+        {
+          "group": "com.example",
+          "name": "sample-test-fixtures",
+          "version": "2.0"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/custom_maven_install/gradle_classifier_pinning_install.json b/tests/custom_maven_install/gradle_classifier_pinning_install.json
new file mode 100644
index 0000000..713990e
--- /dev/null
+++ b/tests/custom_maven_install/gradle_classifier_pinning_install.json
@@ -0,0 +1,2234 @@
+{
+  "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
+  "__INPUT_ARTIFACTS_HASH": {
+    "com.squareup.misk:misk-feature": 1393237427,
+    "repositories": -1949687017
+  },
+  "__RESOLVED_ARTIFACTS_HASH": {
+    "aopalliance:aopalliance": 1403132272,
+    "app.cash.tempest:tempest-bom": -1879634545,
+    "app.cash.wisp:wisp-config": -265982753,
+    "app.cash.wisp:wisp-deployment": 260119237,
+    "app.cash.wisp:wisp-feature": -470998697,
+    "app.cash.wisp:wisp-feature-testing": 887768407,
+    "app.cash.wisp:wisp-logging": 1557040646,
+    "app.cash.wisp:wisp-moshi": 286347900,
+    "app.cash.wisp:wisp-resource-loader": -1032101829,
+    "app.cash.wisp:wisp-sampling": -75096483,
+    "com.fasterxml.jackson.core:jackson-annotations": 1145483352,
+    "com.fasterxml.jackson.core:jackson-core": 2050651888,
+    "com.fasterxml.jackson.core:jackson-databind": -1570896391,
+    "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml": -2044012716,
+    "com.fasterxml.jackson.datatype:jackson-datatype-jsr310": 1727571259,
+    "com.fasterxml.jackson.module:jackson-module-kotlin": 1800534476,
+    "com.fasterxml.jackson:jackson-bom": -426451146,
+    "com.google.errorprone:error_prone_annotations": 1527418394,
+    "com.google.guava:failureaccess": 1715931538,
+    "com.google.guava:guava": -1587873388,
+    "com.google.guava:guava-bom": -1977259012,
+    "com.google.guava:listenablefuture": 1079558157,
+    "com.google.inject:guice": 705254129,
+    "com.google.inject:guice-bom": -1956074999,
+    "com.google.j2objc:j2objc-annotations": -1008747351,
+    "com.sksamuel.hoplite:hoplite-core": -268445711,
+    "com.sksamuel.hoplite:hoplite-hocon": -672469505,
+    "com.sksamuel.hoplite:hoplite-json": -95232757,
+    "com.sksamuel.hoplite:hoplite-toml": 69276386,
+    "com.sksamuel.hoplite:hoplite-yaml": 2110886743,
+    "com.squareup.misk:misk-actions": 1747342526,
+    "com.squareup.misk:misk-api": -1065500127,
+    "com.squareup.misk:misk-bom": -854758943,
+    "com.squareup.misk:misk-config": 1186956235,
+    "com.squareup.misk:misk-feature": -1782538676,
+    "com.squareup.misk:misk-feature:jar:test-fixtures": 2070536049,
+    "com.squareup.misk:misk-hotwire": -903162124,
+    "com.squareup.misk:misk-inject": -1819279524,
+    "com.squareup.misk:misk-logging": 1715412273,
+    "com.squareup.misk:misk-moshi": -1026059657,
+    "com.squareup.misk:misk-sampling": 755796976,
+    "com.squareup.misk:misk-service": 793155643,
+    "com.squareup.misk:misk-tailwind": -1968636072,
+    "com.squareup.misk:misk-testing-api": 2115450372,
+    "com.squareup.moshi:moshi": -844038858,
+    "com.squareup.moshi:moshi-adapters": 290811961,
+    "com.squareup.moshi:moshi-kotlin": 1840181771,
+    "com.squareup.okhttp3:okhttp": -610940879,
+    "com.squareup.okhttp3:okhttp-jvm": 1525485671,
+    "com.squareup.okio:okio": 1676801613,
+    "com.squareup.okio:okio-jvm": 267084012,
+    "com.squareup.wire:wire-bom": -1956074999,
+    "com.squareup.wire:wire-grpc-client": 953771492,
+    "com.squareup.wire:wire-grpc-client-jvm": -413146073,
+    "com.squareup.wire:wire-moshi-adapter": -247201577,
+    "com.squareup.wire:wire-runtime": 661990221,
+    "com.squareup.wire:wire-runtime-jvm": -1551598996,
+    "com.typesafe:config": 1294804214,
+    "io.github.microutils:kotlin-logging": -1124668210,
+    "io.github.microutils:kotlin-logging-jvm": -918149230,
+    "io.grpc:grpc-bom": 1931854008,
+    "io.micrometer:micrometer-commons": -497857416,
+    "io.micrometer:micrometer-core": 676088806,
+    "io.micrometer:micrometer-observation": 104243727,
+    "io.netty:netty-bom": 263091508,
+    "io.prometheus:simpleclient_bom": 550728912,
+    "jakarta.inject:jakarta.inject-api": 188991469,
+    "javax.inject:javax.inject": 698155243,
+    "org.antlr:antlr4-runtime": 745607488,
+    "org.apache.commons:commons-lang3": 1244192954,
+    "org.bouncycastle:bcprov-jdk18on": 1777508792,
+    "org.checkerframework:checker-qual": 216193902,
+    "org.eclipse.jetty:jetty-bom": -686968461,
+    "org.glassfish.jersey:jersey-bom": 554180093,
+    "org.hdrhistogram:HdrHistogram": 310945399,
+    "org.jetbrains.kotlin:kotlin-bom": 728770814,
+    "org.jetbrains.kotlin:kotlin-reflect": 1533004278,
+    "org.jetbrains.kotlin:kotlin-stdlib": 58909863,
+    "org.jetbrains.kotlin:kotlin-stdlib-common": 849864077,
+    "org.jetbrains.kotlin:kotlin-stdlib-jdk7": -1162164559,
+    "org.jetbrains.kotlin:kotlin-stdlib-jdk8": 1062613682,
+    "org.jetbrains.kotlinx:kotlinx-coroutines-bom": 328043797,
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core": 2089326430,
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": 2069021185,
+    "org.jetbrains.kotlinx:kotlinx-html-jvm": 858271213,
+    "org.jetbrains:annotations": -1663747638,
+    "org.jspecify:jspecify": 117231129,
+    "org.slf4j:slf4j-api": -1521593912,
+    "org.tomlj:tomlj": -1571850465,
+    "org.yaml:snakeyaml": 1308413731
+  },
+  "artifacts": {
+    "aopalliance:aopalliance": {
+      "shasums": {
+        "jar": "0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08"
+      },
+      "version": "1.0"
+    },
+    "app.cash.tempest:tempest-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "2026.03.24.151442-d6de1b3"
+    },
+    "app.cash.wisp:wisp-config": {
+      "shasums": {
+        "jar": "fcde53794d0ea850be149014fc8068d1f207549ee1816eca3bc955577ec8a1fe"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "app.cash.wisp:wisp-deployment": {
+      "shasums": {
+        "jar": "ff8e67330474d548adfa7e348706e35e845e742935b58b608d12c05b6716b7f5"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "app.cash.wisp:wisp-feature": {
+      "shasums": {
+        "jar": "697d0b56c58e02d08ef98a2bfd758ef8714fe93205072073b644b2bd001feeda"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "app.cash.wisp:wisp-feature-testing": {
+      "shasums": {
+        "jar": "ddd851a44099967d64a948195cc04c32158845f04b15146363e6cac216838f19"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "app.cash.wisp:wisp-logging": {
+      "shasums": {
+        "jar": "0e344e6a195d104e95038eaee6b67776fa1edf3d2582c6159103cd07c692fa60"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "app.cash.wisp:wisp-moshi": {
+      "shasums": {
+        "jar": "90d023d27217e6f8bd59c08b61fb1beffd27ea6ef12cc4909930551a72c40699"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "app.cash.wisp:wisp-resource-loader": {
+      "shasums": {
+        "jar": "a1498d5ce15c26e67f394fcca1e692805e72d77edb63989caafb44158d530e68"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "app.cash.wisp:wisp-sampling": {
+      "shasums": {
+        "jar": "4cccd29698a80c8d9cb1edba7266a88e4d0fb55de6bca9f9324fb006cee7e4c7"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.fasterxml.jackson.core:jackson-annotations": {
+      "shasums": {
+        "jar": "53ca085f4a150f703f49e1aabd935bd03b43e1ea3d55d135438292af22cef56b"
+      },
+      "version": "2.21"
+    },
+    "com.fasterxml.jackson.core:jackson-core": {
+      "shasums": {
+        "jar": "12e8655b100267b44d0f14d01b1f5082a5105e616174dc4307be1a761e92407b"
+      },
+      "version": "2.21.2"
+    },
+    "com.fasterxml.jackson.core:jackson-databind": {
+      "shasums": {
+        "jar": "8c982f01f148d805f0aaac2339011244757e0df7c6ff8951f2fa3f433b8ed849"
+      },
+      "version": "2.21.2"
+    },
+    "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml": {
+      "shasums": {
+        "jar": "d25551812fa0c14f37cabaa9401e63eadcea42ce36311183af5622d5bc8a1bc7"
+      },
+      "version": "2.21.2"
+    },
+    "com.fasterxml.jackson.datatype:jackson-datatype-jsr310": {
+      "shasums": {
+        "jar": "a083d57cd1c4a28fefcc6bd071740779eb7fc1c22a3c1b40451b5477c443f02f"
+      },
+      "version": "2.21.2"
+    },
+    "com.fasterxml.jackson.module:jackson-module-kotlin": {
+      "shasums": {
+        "jar": "9194d794a2879106be90e36becae6e16ee8716f14224144970c82717be0004ce"
+      },
+      "version": "2.21.2"
+    },
+    "com.fasterxml.jackson:jackson-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "2.21.2"
+    },
+    "com.google.errorprone:error_prone_annotations": {
+      "shasums": {
+        "jar": "a56e782b5b50811ac204073a355a21d915a2107fce13ec711331ad036f660fcc"
+      },
+      "version": "2.41.0"
+    },
+    "com.google.guava:failureaccess": {
+      "shasums": {
+        "jar": "cbfc3906b19b8f55dd7cfd6dfe0aa4532e834250d7f080bd8d211a3e246b59cb"
+      },
+      "version": "1.0.3"
+    },
+    "com.google.guava:guava": {
+      "shasums": {
+        "jar": "1e301f0c52ac248b0b14fdc3d12283c77252d4d6f48521d572e7d8c4c2cc4ac7"
+      },
+      "version": "33.5.0-jre"
+    },
+    "com.google.guava:guava-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "33.5.0-jre"
+    },
+    "com.google.guava:listenablefuture": {
+      "shasums": {
+        "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99"
+      },
+      "version": "9999.0-empty-to-avoid-conflict-with-guava"
+    },
+    "com.google.inject:guice": {
+      "shasums": {
+        "jar": "b4d4f7ec5e8fc17b4f98dee9d3f6cf6ae3ae13e2e5ed4b2f7bbf09bc4bb675d5"
+      },
+      "version": "6.0.0"
+    },
+    "com.google.inject:guice-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "6.0.0"
+    },
+    "com.google.j2objc:j2objc-annotations": {
+      "shasums": {
+        "jar": "84d3a150518485f8140ea99b8a985656749629f6433c92b80c75b36aba3b099b"
+      },
+      "version": "3.1"
+    },
+    "com.sksamuel.hoplite:hoplite-core": {
+      "shasums": {
+        "jar": "dc33aaf45b7b8d0e7485cb23bb771c37fec2a0e8e7416f34f0e146b2a4be474b"
+      },
+      "version": "2.7.5"
+    },
+    "com.sksamuel.hoplite:hoplite-hocon": {
+      "shasums": {
+        "jar": "15aa2bb4ffbaf986e8c1c532179bda5295001542d8ba22165dd23fe19bc9158f"
+      },
+      "version": "2.7.5"
+    },
+    "com.sksamuel.hoplite:hoplite-json": {
+      "shasums": {
+        "jar": "31f0a788f642730fba1d7244cecc7c22722066645cae4ee299af63a456080277"
+      },
+      "version": "2.7.5"
+    },
+    "com.sksamuel.hoplite:hoplite-toml": {
+      "shasums": {
+        "jar": "7780496fa80b08f9b1bef3d67b541aa9b16c0d0461e5b39f253f2ff949fdc368"
+      },
+      "version": "2.7.5"
+    },
+    "com.sksamuel.hoplite:hoplite-yaml": {
+      "shasums": {
+        "jar": "a6990a592b9917beb332a28e9bbd2b904de42520a270f41a99c24cc9983923c0"
+      },
+      "version": "2.7.5"
+    },
+    "com.squareup.misk:misk-actions": {
+      "shasums": {
+        "jar": "d6be56ab3b8d936988d42b80132d4a2561ca8934909674e78d6454bd745ce06b"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-api": {
+      "shasums": {
+        "jar": "d5dd0bdad669514f3620cdab929bfe6b807ec413aa2b77b8094bce02cc92cd68"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-config": {
+      "shasums": {
+        "jar": "03e57b1476f026528b11d613eb3270944e87d1eb192096819bd631d32ab3a26f"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-feature": {
+      "shasums": {
+        "jar": "b5fa6e0cde8c138582c905dc8e1e99ecc5a423670fd8957c40e9e63ec2ae1a31",
+        "test-fixtures": "c57c13aab72ee5fa76f3fbf2c6535db8cbd358fe3292174df2c790173e80d811"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-hotwire": {
+      "shasums": {
+        "jar": "cd9a0bf377516bdfae671382b8bfbcf9f38dd1a58fe3925dd5d739238adad1de"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-inject": {
+      "shasums": {
+        "jar": "be7ef3f89933def9134430d2dff9ff0f5f51baa08614e709dccd1d44a8560228"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-logging": {
+      "shasums": {
+        "jar": "e5df1c3ace15d79cb573cc02e64c3c586f7688a4218ab11d9c2dfa249768a3eb"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-moshi": {
+      "shasums": {
+        "jar": "5891ce629480c90ce3e85a22ce96d6edd8f43f1de6dea0901b94e5bcb545305d"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-sampling": {
+      "shasums": {
+        "jar": "9ad2b86fcae05cd8358b364c27f157a4967f6a4e79675327e2785d30334780d6"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-service": {
+      "shasums": {
+        "jar": "e8402933c9405c7f7b5a293f80e548405055bc96afc8e0ec096ea4d780aa7146"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-tailwind": {
+      "shasums": {
+        "jar": "b8f346bc9add35378a749c14cffca72cebf59eb8641a6ba3f14d5bf34cbab852"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.misk:misk-testing-api": {
+      "shasums": {
+        "jar": "88a233c92b9157a04d9eeda3cb32398144024b32eb1fda2ccbc431b22a793327"
+      },
+      "version": "2026.07.11.061457-fa37275"
+    },
+    "com.squareup.moshi:moshi": {
+      "shasums": {
+        "jar": "767f7592c6c61eb693549a26d333c121f5383826bd287b899867aa326dae55e4"
+      },
+      "version": "1.15.2"
+    },
+    "com.squareup.moshi:moshi-adapters": {
+      "shasums": {
+        "jar": "efa90fb3419a5a88bd5e029cbafdcecce1812430b15cb86770f60eaf0b45c409"
+      },
+      "version": "1.15.2"
+    },
+    "com.squareup.moshi:moshi-kotlin": {
+      "shasums": {
+        "jar": "5c39cd77e83b111af9c54708173af96a89fd3b09d15019a11da355e83e97d75a"
+      },
+      "version": "1.15.2"
+    },
+    "com.squareup.okhttp3:okhttp": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "5.4.0"
+    },
+    "com.squareup.okhttp3:okhttp-jvm": {
+      "shasums": {
+        "jar": "b15e605ca0a4b12c62ea7f657dad413c236c947e875854767349cdbe20df473c"
+      },
+      "version": "5.4.0"
+    },
+    "com.squareup.okio:okio": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "3.17.0"
+    },
+    "com.squareup.okio:okio-jvm": {
+      "shasums": {
+        "jar": "3b13dcc3e1573047c2d507fc4f7fcb0bb0cbcd9d395da21d20e09406e2cd6a73"
+      },
+      "version": "3.17.0"
+    },
+    "com.squareup.wire:wire-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "6.0.0"
+    },
+    "com.squareup.wire:wire-grpc-client": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "6.0.0"
+    },
+    "com.squareup.wire:wire-grpc-client-jvm": {
+      "shasums": {
+        "jar": "65c80c03f71577ed4aa2ad6c5b081aee46705bad3dcfa9300b94acab7a39ff74"
+      },
+      "version": "6.0.0"
+    },
+    "com.squareup.wire:wire-moshi-adapter": {
+      "shasums": {
+        "jar": "9cc29cabf77bc13301407ca774d5f0195895b53fc2c0fd792b64684aa5c6ebcd"
+      },
+      "version": "6.0.0"
+    },
+    "com.squareup.wire:wire-runtime": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "6.0.0"
+    },
+    "com.squareup.wire:wire-runtime-jvm": {
+      "shasums": {
+        "jar": "ca10c9f2b016b9b1027d8b20a6f06ea24505bd67657204e2094e4f6d8a5133df"
+      },
+      "version": "6.0.0"
+    },
+    "com.typesafe:config": {
+      "shasums": {
+        "jar": "0076c249b4387d8369146528fd5dacb3efba098dc02ecf9ac81debdfc2e12fd5"
+      },
+      "version": "1.4.2"
+    },
+    "io.github.microutils:kotlin-logging": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "3.0.5"
+    },
+    "io.github.microutils:kotlin-logging-jvm": {
+      "shasums": {
+        "jar": "2a9477a4138487bb7fbb057ee3ac0f455b58f8d4bed94c885fa64260de59e4dc"
+      },
+      "version": "3.0.5"
+    },
+    "io.grpc:grpc-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "1.75.0"
+    },
+    "io.micrometer:micrometer-commons": {
+      "shasums": {
+        "jar": "03919dc71e2417ec4b5c254c4ba924963c972e124190f73cdcb68ed51c6eede6"
+      },
+      "version": "1.17.0"
+    },
+    "io.micrometer:micrometer-core": {
+      "shasums": {
+        "jar": "73503e701a377fafeaf33b71b9b8910a8d7884cbba88ab27971b33b3753b65aa"
+      },
+      "version": "1.17.0"
+    },
+    "io.micrometer:micrometer-observation": {
+      "shasums": {
+        "jar": "2fc95a327578d3b2a81c3ff40e646a4a21e46b0153ccbbf91690142bf80d9661"
+      },
+      "version": "1.17.0"
+    },
+    "io.netty:netty-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "4.2.14.Final"
+    },
+    "io.prometheus:simpleclient_bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "0.16.0"
+    },
+    "jakarta.inject:jakarta.inject-api": {
+      "shasums": {
+        "jar": "f7dc98062fccf14126abb751b64fab12c312566e8cbdc8483598bffcea93af7c"
+      },
+      "version": "2.0.1"
+    },
+    "javax.inject:javax.inject": {
+      "shasums": {
+        "jar": "91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff"
+      },
+      "version": "1"
+    },
+    "org.antlr:antlr4-runtime": {
+      "shasums": {
+        "jar": "e06c6553c1ccc14d36052ec4b0fc6f13b808cf957b5b1dc3f61bf401996ada59"
+      },
+      "version": "4.11.1"
+    },
+    "org.apache.commons:commons-lang3": {
+      "shasums": {
+        "jar": "32733ab4bc90b45b63eb72677d886961003fd4ed113e07b1028f9877cb2ac735"
+      },
+      "version": "3.19.0"
+    },
+    "org.bouncycastle:bcprov-jdk18on": {
+      "shasums": {
+        "jar": "14cde2fdfaa8890480a8e5b67aceef0c90f96682c1e23c133bafdc9e0b3255ce"
+      },
+      "version": "1.82"
+    },
+    "org.checkerframework:checker-qual": {
+      "shasums": {
+        "jar": "7e8554c902b9b839e61396cfe3a64c84ecabfb8eb652c410bfd8e4f5c1a8ece8"
+      },
+      "version": "3.21.2"
+    },
+    "org.eclipse.jetty:jetty-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "11.0.26"
+    },
+    "org.glassfish.jersey:jersey-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "3.1.11"
+    },
+    "org.hdrhistogram:HdrHistogram": {
+      "shasums": {
+        "jar": "22d1d4316c4ec13a68b559e98c8256d69071593731da96136640f864fa14fad8"
+      },
+      "version": "2.2.2"
+    },
+    "org.jetbrains.kotlin:kotlin-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "2.2.21"
+    },
+    "org.jetbrains.kotlin:kotlin-reflect": {
+      "shasums": {
+        "jar": "44380abf37d245ce5c0f294f43512d1c39a59642bfa463922c74e96877cf49f8"
+      },
+      "version": "2.2.21"
+    },
+    "org.jetbrains.kotlin:kotlin-stdlib": {
+      "shasums": {
+        "jar": "6558a3d233da56a20934b32159f9db5f86ed5816ef098f78a2c223dc6abb79dd"
+      },
+      "version": "2.2.21"
+    },
+    "org.jetbrains.kotlin:kotlin-stdlib-common": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "2.2.21"
+    },
+    "org.jetbrains.kotlin:kotlin-stdlib-jdk7": {
+      "shasums": {
+        "jar": "b785922f11e6d91a6dd1d75cb0aef1ce37b83f8de0e3a2139139dfb823bb8a2c"
+      },
+      "version": "2.2.21"
+    },
+    "org.jetbrains.kotlin:kotlin-stdlib-jdk8": {
+      "shasums": {
+        "jar": "c62275c50ee591ca2f82c7ba42696b791600c25844f47e84bd9460302a0d5238"
+      },
+      "version": "2.2.21"
+    },
+    "org.jetbrains.kotlinx:kotlinx-coroutines-bom": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "1.10.2"
+    },
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core": {
+      "shasums": {
+        "jar": null
+      },
+      "version": "1.10.2"
+    },
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": {
+      "shasums": {
+        "jar": "5ca175b38df331fd64155b35cd8cae1251fa9ee369709b36d42e0a288ccce3fd"
+      },
+      "version": "1.10.2"
+    },
+    "org.jetbrains.kotlinx:kotlinx-html-jvm": {
+      "shasums": {
+        "jar": "f854126f39acbd963fd54e0cd226000a151a76f7225ee28185d52f44e262befb"
+      },
+      "version": "0.12.0"
+    },
+    "org.jetbrains:annotations": {
+      "shasums": {
+        "jar": "7b0f19724082cbfcbc66e5abea2b9bc92cf08a1ea11e191933ed43801eb3cd05"
+      },
+      "version": "23.0.0"
+    },
+    "org.jspecify:jspecify": {
+      "shasums": {
+        "jar": "1fad6e6be7557781e4d33729d49ae1cdc8fdda6fe477bb0cc68ce351eafdfbab"
+      },
+      "version": "1.0.0"
+    },
+    "org.slf4j:slf4j-api": {
+      "shasums": {
+        "jar": "7b751d952061954d5abfed7181c1f645d336091b679891591d63329c622eb832"
+      },
+      "version": "2.0.17"
+    },
+    "org.tomlj:tomlj": {
+      "shasums": {
+        "jar": "4dd5c4927d4cb1eb5ad9561445b19baa9292a7ac84ecdc2d024777e723791800"
+      },
+      "version": "1.1.0"
+    },
+    "org.yaml:snakeyaml": {
+      "shasums": {
+        "jar": "e6682acf1ace77508ef13649cbf4f8d09d2cf5457bdb61d25ffb6ac0233d78dd"
+      },
+      "version": "2.5"
+    }
+  },
+  "conflict_resolution": {
+    "com.fasterxml.jackson.core:jackson-annotations": "com.fasterxml.jackson.core:jackson-annotations:2.21",
+    "com.fasterxml.jackson.core:jackson-core": "com.fasterxml.jackson.core:jackson-core:2.21.2",
+    "com.fasterxml.jackson.core:jackson-databind": "com.fasterxml.jackson.core:jackson-databind:2.21.2",
+    "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml": "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.21.2",
+    "com.fasterxml.jackson.datatype:jackson-datatype-jsr310": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.21.2",
+    "com.fasterxml.jackson.module:jackson-module-kotlin": "com.fasterxml.jackson.module:jackson-module-kotlin:2.21.2",
+    "com.google.guava:guava:31.0.1-jre": "com.google.guava:guava:33.5.0-jre",
+    "com.google.inject:guice": "com.google.inject:guice:6.0.0",
+    "com.squareup.misk:misk-feature:jar:test-fixtures:2026.06.30.120630-d342aab": "com.squareup.misk:misk-feature:jar:test-fixtures:2026.07.11.061457-fa37275",
+    "com.squareup.okhttp3:okhttp:5.3.2": "com.squareup.okhttp3:okhttp:5.4.0",
+    "com.squareup.okio:okio:3.16.4": "com.squareup.okio:okio:3.17.0",
+    "org.jetbrains.kotlin:kotlin-reflect:2.1.21": "org.jetbrains.kotlin:kotlin-reflect:2.2.21",
+    "org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0": "org.jetbrains.kotlin:kotlin-stdlib-common:2.2.21",
+    "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21": "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.21",
+    "org.jetbrains.kotlin:kotlin-stdlib:2.0.21": "org.jetbrains.kotlin:kotlin-stdlib:2.2.21",
+    "org.jetbrains:annotations:13.0": "org.jetbrains:annotations:23.0.0",
+    "org.slf4j:slf4j-api:2.0.3": "org.slf4j:slf4j-api:2.0.17",
+    "org.yaml:snakeyaml:2.0": "org.yaml:snakeyaml:2.5"
+  },
+  "dependencies": {
+    "app.cash.wisp:wisp-config": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-resource-loader",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.sksamuel.hoplite:hoplite-core",
+      "com.sksamuel.hoplite:hoplite-hocon",
+      "com.sksamuel.hoplite:hoplite-json",
+      "com.sksamuel.hoplite:hoplite-toml",
+      "com.sksamuel.hoplite:hoplite-yaml",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "app.cash.wisp:wisp-deployment": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "app.cash.wisp:wisp-feature": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.moshi:moshi",
+      "com.squareup.wire:wire-bom",
+      "io.github.microutils:kotlin-logging",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "app.cash.wisp:wisp-feature-testing": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-config",
+      "app.cash.wisp:wisp-feature",
+      "app.cash.wisp:wisp-moshi",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.moshi:moshi",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "app.cash.wisp:wisp-logging": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-sampling",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-api",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.wire:wire-bom",
+      "io.github.microutils:kotlin-logging",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.slf4j:slf4j-api"
+    ],
+    "app.cash.wisp:wisp-moshi": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.moshi:moshi",
+      "com.squareup.moshi:moshi-kotlin",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "jakarta.inject:jakarta.inject-api",
+      "javax.inject:javax.inject",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "app.cash.wisp:wisp-resource-loader": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-logging",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.okio:okio",
+      "com.squareup.wire:wire-bom",
+      "io.github.microutils:kotlin-logging",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.bouncycastle:bcprov-jdk18on",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "app.cash.wisp:wisp-sampling": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "com.fasterxml.jackson.core:jackson-core": [
+      "com.fasterxml.jackson:jackson-bom"
+    ],
+    "com.fasterxml.jackson.core:jackson-databind": [
+      "com.fasterxml.jackson.core:jackson-annotations",
+      "com.fasterxml.jackson.core:jackson-core",
+      "com.fasterxml.jackson:jackson-bom"
+    ],
+    "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml": [
+      "com.fasterxml.jackson.core:jackson-core",
+      "com.fasterxml.jackson.core:jackson-databind",
+      "com.fasterxml.jackson:jackson-bom",
+      "org.yaml:snakeyaml"
+    ],
+    "com.fasterxml.jackson.datatype:jackson-datatype-jsr310": [
+      "com.fasterxml.jackson.core:jackson-annotations",
+      "com.fasterxml.jackson.core:jackson-core",
+      "com.fasterxml.jackson.core:jackson-databind",
+      "com.fasterxml.jackson:jackson-bom"
+    ],
+    "com.fasterxml.jackson.module:jackson-module-kotlin": [
+      "com.fasterxml.jackson.core:jackson-annotations",
+      "com.fasterxml.jackson.core:jackson-databind",
+      "com.fasterxml.jackson:jackson-bom",
+      "org.jetbrains.kotlin:kotlin-reflect"
+    ],
+    "com.google.guava:guava": [
+      "com.google.errorprone:error_prone_annotations",
+      "com.google.guava:failureaccess",
+      "com.google.guava:listenablefuture",
+      "com.google.j2objc:j2objc-annotations",
+      "org.jspecify:jspecify"
+    ],
+    "com.google.inject:guice": [
+      "aopalliance:aopalliance",
+      "com.google.guava:guava",
+      "jakarta.inject:jakarta.inject-api",
+      "javax.inject:javax.inject"
+    ],
+    "com.sksamuel.hoplite:hoplite-core": [
+      "org.jetbrains.kotlin:kotlin-reflect",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.sksamuel.hoplite:hoplite-hocon": [
+      "com.sksamuel.hoplite:hoplite-core",
+      "com.typesafe:config",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.sksamuel.hoplite:hoplite-json": [
+      "com.fasterxml.jackson.core:jackson-core",
+      "com.fasterxml.jackson.core:jackson-databind",
+      "com.sksamuel.hoplite:hoplite-core",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.sksamuel.hoplite:hoplite-toml": [
+      "com.sksamuel.hoplite:hoplite-core",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
+      "org.tomlj:tomlj"
+    ],
+    "com.sksamuel.hoplite:hoplite-yaml": [
+      "com.sksamuel.hoplite:hoplite-core",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
+      "org.yaml:snakeyaml"
+    ],
+    "com.squareup.misk:misk-actions": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.misk:misk-inject",
+      "com.squareup.okhttp3:okhttp",
+      "com.squareup.okio:okio",
+      "com.squareup.wire:wire-bom",
+      "com.squareup.wire:wire-grpc-client",
+      "com.squareup.wire:wire-runtime",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.misk:misk-api": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.okhttp3:okhttp",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "com.squareup.misk:misk-config": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-deployment",
+      "app.cash.wisp:wisp-resource-loader",
+      "com.fasterxml.jackson.core:jackson-annotations",
+      "com.fasterxml.jackson.core:jackson-core",
+      "com.fasterxml.jackson.core:jackson-databind",
+      "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml",
+      "com.fasterxml.jackson.datatype:jackson-datatype-jsr310",
+      "com.fasterxml.jackson.module:jackson-module-kotlin",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.misk:misk-inject",
+      "com.squareup.misk:misk-logging",
+      "com.squareup.misk:misk-tailwind",
+      "com.squareup.moshi:moshi",
+      "com.squareup.okio:okio",
+      "com.squareup.wire:wire-bom",
+      "io.github.microutils:kotlin-logging",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "jakarta.inject:jakarta.inject-api",
+      "org.apache.commons:commons-lang3",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.jetbrains.kotlinx:kotlinx-html-jvm"
+    ],
+    "com.squareup.misk:misk-feature": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-feature",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.misk:misk-feature:jar:test-fixtures": [
+      "app.cash.wisp:wisp-feature",
+      "app.cash.wisp:wisp-feature-testing",
+      "com.google.inject:guice",
+      "com.squareup.misk:misk-feature",
+      "com.squareup.misk:misk-inject",
+      "com.squareup.misk:misk-service",
+      "com.squareup.misk:misk-testing-api",
+      "com.squareup.moshi:moshi",
+      "jakarta.inject:jakarta.inject-api",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.misk:misk-hotwire": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-actions",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.okio:okio",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.jetbrains.kotlinx:kotlinx-html-jvm"
+    ],
+    "com.squareup.misk:misk-inject": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.misk:misk-testing-api",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "jakarta.inject:jakarta.inject-api",
+      "javax.inject:javax.inject",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-reflect",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.misk:misk-logging": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.misk:misk-sampling",
+      "com.squareup.wire:wire-bom",
+      "io.github.microutils:kotlin-logging",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
+      "org.slf4j:slf4j-api"
+    ],
+    "com.squareup.misk:misk-moshi": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-moshi",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.misk:misk-inject",
+      "com.squareup.moshi:moshi",
+      "com.squareup.moshi:moshi-adapters",
+      "com.squareup.okio:okio",
+      "com.squareup.wire:wire-bom",
+      "com.squareup.wire:wire-moshi-adapter",
+      "com.squareup.wire:wire-runtime",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "jakarta.inject:jakarta.inject-api",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "com.squareup.misk:misk-sampling": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.micrometer:micrometer-core",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "jakarta.inject:jakarta.inject-api",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.misk:misk-service": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-moshi",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.misk:misk-config",
+      "com.squareup.misk:misk-inject",
+      "com.squareup.misk:misk-logging",
+      "com.squareup.misk:misk-moshi",
+      "com.squareup.moshi:moshi",
+      "com.squareup.wire:wire-bom",
+      "io.github.microutils:kotlin-logging",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "jakarta.inject:jakarta.inject-api",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.misk:misk-tailwind": [
+      "app.cash.tempest:tempest-bom",
+      "app.cash.wisp:wisp-deployment",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.misk:misk-hotwire",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.jetbrains.kotlinx:kotlinx-html-jvm"
+    ],
+    "com.squareup.misk:misk-testing-api": [
+      "app.cash.tempest:tempest-bom",
+      "com.fasterxml.jackson:jackson-bom",
+      "com.google.guava:guava-bom",
+      "com.google.inject:guice-bom",
+      "com.squareup.misk:misk-bom",
+      "com.squareup.wire:wire-bom",
+      "io.grpc:grpc-bom",
+      "io.netty:netty-bom",
+      "io.prometheus:simpleclient_bom",
+      "org.eclipse.jetty:jetty-bom",
+      "org.glassfish.jersey:jersey-bom",
+      "org.jetbrains.kotlin:kotlin-bom",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "com.squareup.moshi:moshi": [
+      "com.squareup.okio:okio",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.moshi:moshi-adapters": [
+      "com.squareup.moshi:moshi",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.moshi:moshi-kotlin": [
+      "com.squareup.moshi:moshi",
+      "org.jetbrains.kotlin:kotlin-reflect",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+    ],
+    "com.squareup.okhttp3:okhttp": [
+      "com.squareup.okhttp3:okhttp-jvm"
+    ],
+    "com.squareup.okhttp3:okhttp-jvm": [
+      "com.squareup.okio:okio",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "com.squareup.okio:okio": [
+      "com.squareup.okio:okio-jvm"
+    ],
+    "com.squareup.okio:okio-jvm": [
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "com.squareup.wire:wire-grpc-client": [
+      "com.squareup.wire:wire-grpc-client-jvm"
+    ],
+    "com.squareup.wire:wire-grpc-client-jvm": [
+      "com.squareup.okhttp3:okhttp",
+      "com.squareup.okio:okio",
+      "com.squareup.wire:wire-runtime",
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.jetbrains.kotlinx:kotlinx-coroutines-core"
+    ],
+    "com.squareup.wire:wire-moshi-adapter": [
+      "com.squareup.moshi:moshi",
+      "com.squareup.wire:wire-runtime",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "com.squareup.wire:wire-runtime": [
+      "com.squareup.wire:wire-runtime-jvm"
+    ],
+    "com.squareup.wire:wire-runtime-jvm": [
+      "com.squareup.okio:okio",
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "io.github.microutils:kotlin-logging": [
+      "io.github.microutils:kotlin-logging-jvm"
+    ],
+    "io.github.microutils:kotlin-logging-jvm": [
+      "org.jetbrains.kotlin:kotlin-stdlib-common",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
+      "org.slf4j:slf4j-api"
+    ],
+    "io.micrometer:micrometer-commons": [
+      "org.jspecify:jspecify"
+    ],
+    "io.micrometer:micrometer-core": [
+      "io.micrometer:micrometer-commons",
+      "io.micrometer:micrometer-observation",
+      "org.hdrhistogram:HdrHistogram",
+      "org.jspecify:jspecify"
+    ],
+    "io.micrometer:micrometer-observation": [
+      "io.micrometer:micrometer-commons",
+      "org.jspecify:jspecify"
+    ],
+    "org.jetbrains.kotlin:kotlin-reflect": [
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "org.jetbrains.kotlin:kotlin-stdlib": [
+      "org.jetbrains:annotations"
+    ],
+    "org.jetbrains.kotlin:kotlin-stdlib-common": [
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "org.jetbrains.kotlin:kotlin-stdlib-jdk7": [
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "org.jetbrains.kotlin:kotlin-stdlib-jdk8": [
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk7"
+    ],
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core": [
+      "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm"
+    ],
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": [
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.jetbrains.kotlinx:kotlinx-coroutines-bom",
+      "org.jetbrains:annotations"
+    ],
+    "org.jetbrains.kotlinx:kotlinx-html-jvm": [
+      "org.jetbrains.kotlin:kotlin-stdlib"
+    ],
+    "org.tomlj:tomlj": [
+      "org.antlr:antlr4-runtime",
+      "org.checkerframework:checker-qual"
+    ]
+  },
+  "packages": {
+    "aopalliance:aopalliance": [
+      "org.aopalliance.aop",
+      "org.aopalliance.intercept"
+    ],
+    "app.cash.wisp:wisp-config": [
+      "wisp.config"
+    ],
+    "app.cash.wisp:wisp-deployment": [
+      "wisp.deployment"
+    ],
+    "app.cash.wisp:wisp-feature": [
+      "wisp.feature"
+    ],
+    "app.cash.wisp:wisp-feature-testing": [
+      "wisp.feature.testing"
+    ],
+    "app.cash.wisp:wisp-logging": [
+      "wisp.logging"
+    ],
+    "app.cash.wisp:wisp-moshi": [
+      "wisp.moshi"
+    ],
+    "app.cash.wisp:wisp-resource-loader": [
+      "wisp.resources"
+    ],
+    "app.cash.wisp:wisp-sampling": [
+      "wisp.sampling"
+    ],
+    "com.fasterxml.jackson.core:jackson-annotations": [
+      "com.fasterxml.jackson.annotation"
+    ],
+    "com.fasterxml.jackson.core:jackson-core": [
+      "com.fasterxml.jackson.core",
+      "com.fasterxml.jackson.core.async",
+      "com.fasterxml.jackson.core.base",
+      "com.fasterxml.jackson.core.exc",
+      "com.fasterxml.jackson.core.filter",
+      "com.fasterxml.jackson.core.format",
+      "com.fasterxml.jackson.core.internal.shaded.fdp.v2_21_2",
+      "com.fasterxml.jackson.core.io",
+      "com.fasterxml.jackson.core.io.schubfach",
+      "com.fasterxml.jackson.core.json",
+      "com.fasterxml.jackson.core.json.async",
+      "com.fasterxml.jackson.core.sym",
+      "com.fasterxml.jackson.core.type",
+      "com.fasterxml.jackson.core.util"
+    ],
+    "com.fasterxml.jackson.core:jackson-databind": [
+      "com.fasterxml.jackson.databind",
+      "com.fasterxml.jackson.databind.annotation",
+      "com.fasterxml.jackson.databind.cfg",
+      "com.fasterxml.jackson.databind.deser",
+      "com.fasterxml.jackson.databind.deser.impl",
+      "com.fasterxml.jackson.databind.deser.std",
+      "com.fasterxml.jackson.databind.exc",
+      "com.fasterxml.jackson.databind.ext",
+      "com.fasterxml.jackson.databind.introspect",
+      "com.fasterxml.jackson.databind.jdk14",
+      "com.fasterxml.jackson.databind.json",
+      "com.fasterxml.jackson.databind.jsonFormatVisitors",
+      "com.fasterxml.jackson.databind.jsonschema",
+      "com.fasterxml.jackson.databind.jsontype",
+      "com.fasterxml.jackson.databind.jsontype.impl",
+      "com.fasterxml.jackson.databind.module",
+      "com.fasterxml.jackson.databind.node",
+      "com.fasterxml.jackson.databind.ser",
+      "com.fasterxml.jackson.databind.ser.impl",
+      "com.fasterxml.jackson.databind.ser.std",
+      "com.fasterxml.jackson.databind.type",
+      "com.fasterxml.jackson.databind.util",
+      "com.fasterxml.jackson.databind.util.internal"
+    ],
+    "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml": [
+      "com.fasterxml.jackson.dataformat.yaml",
+      "com.fasterxml.jackson.dataformat.yaml.snakeyaml.error",
+      "com.fasterxml.jackson.dataformat.yaml.util"
+    ],
+    "com.fasterxml.jackson.datatype:jackson-datatype-jsr310": [
+      "com.fasterxml.jackson.datatype.jsr310",
+      "com.fasterxml.jackson.datatype.jsr310.deser",
+      "com.fasterxml.jackson.datatype.jsr310.deser.key",
+      "com.fasterxml.jackson.datatype.jsr310.ser",
+      "com.fasterxml.jackson.datatype.jsr310.ser.key",
+      "com.fasterxml.jackson.datatype.jsr310.util"
+    ],
+    "com.fasterxml.jackson.module:jackson-module-kotlin": [
+      "com.fasterxml.jackson.module.kotlin"
+    ],
+    "com.google.errorprone:error_prone_annotations": [
+      "com.google.errorprone.annotations",
+      "com.google.errorprone.annotations.concurrent"
+    ],
+    "com.google.guava:failureaccess": [
+      "com.google.common.util.concurrent.internal"
+    ],
+    "com.google.guava:guava": [
+      "com.google.common.annotations",
+      "com.google.common.base",
+      "com.google.common.base.internal",
+      "com.google.common.cache",
+      "com.google.common.collect",
+      "com.google.common.escape",
+      "com.google.common.eventbus",
+      "com.google.common.graph",
+      "com.google.common.hash",
+      "com.google.common.html",
+      "com.google.common.io",
+      "com.google.common.math",
+      "com.google.common.net",
+      "com.google.common.primitives",
+      "com.google.common.reflect",
+      "com.google.common.util.concurrent",
+      "com.google.common.xml",
+      "com.google.thirdparty.publicsuffix"
+    ],
+    "com.google.inject:guice": [
+      "com.google.inject",
+      "com.google.inject.binder",
+      "com.google.inject.internal",
+      "com.google.inject.internal.aop",
+      "com.google.inject.internal.util",
+      "com.google.inject.matcher",
+      "com.google.inject.multibindings",
+      "com.google.inject.name",
+      "com.google.inject.spi",
+      "com.google.inject.util"
+    ],
+    "com.google.j2objc:j2objc-annotations": [
+      "com.google.j2objc.annotations"
+    ],
+    "com.sksamuel.hoplite:hoplite-core": [
+      "com.sksamuel.hoplite",
+      "com.sksamuel.hoplite.decoder",
+      "com.sksamuel.hoplite.env",
+      "com.sksamuel.hoplite.fp",
+      "com.sksamuel.hoplite.internal",
+      "com.sksamuel.hoplite.parsers",
+      "com.sksamuel.hoplite.preprocessor",
+      "com.sksamuel.hoplite.report",
+      "com.sksamuel.hoplite.secrets",
+      "com.sksamuel.hoplite.sources",
+      "com.sksamuel.hoplite.time"
+    ],
+    "com.sksamuel.hoplite:hoplite-hocon": [
+      "com.sksamuel.hoplite.hocon"
+    ],
+    "com.sksamuel.hoplite:hoplite-json": [
+      "com.sksamuel.hoplite.json"
+    ],
+    "com.sksamuel.hoplite:hoplite-toml": [
+      "com.sksamuel.hoplite.toml"
+    ],
+    "com.sksamuel.hoplite:hoplite-yaml": [
+      "com.sksamuel.hoplite.yaml"
+    ],
+    "com.squareup.misk:misk-actions": [
+      "misk",
+      "misk.exceptions",
+      "misk.security.authz",
+      "misk.web",
+      "misk.web.actions",
+      "misk.web.dashboard",
+      "misk.web.interceptors"
+    ],
+    "com.squareup.misk:misk-api": [
+      "misk.annotation",
+      "misk.api",
+      "misk.client",
+      "misk.logging",
+      "misk.scope",
+      "misk.web",
+      "misk.web.dashboard"
+    ],
+    "com.squareup.misk:misk-config": [
+      "misk.config",
+      "misk.resources",
+      "misk.web.metadata"
+    ],
+    "com.squareup.misk:misk-feature": [
+      "misk.feature"
+    ],
+    "com.squareup.misk:misk-feature:jar:test-fixtures": [
+      "misk.feature.testing"
+    ],
+    "com.squareup.misk:misk-hotwire": [
+      "misk.hotwire",
+      "misk.turbo"
+    ],
+    "com.squareup.misk:misk-inject": [
+      "misk.inject"
+    ],
+    "com.squareup.misk:misk-logging": [
+      "misk.logging"
+    ],
+    "com.squareup.misk:misk-moshi": [
+      "misk.moshi",
+      "misk.moshi.adapters",
+      "misk.moshi.okio",
+      "misk.moshi.time",
+      "misk.moshi.wire"
+    ],
+    "com.squareup.misk:misk-sampling": [
+      "misk.concurrent",
+      "misk.sampling"
+    ],
+    "com.squareup.misk:misk-service": [
+      "misk",
+      "misk.metadata.servicegraph"
+    ],
+    "com.squareup.misk:misk-tailwind": [
+      "misk.tailwind",
+      "misk.tailwind.components",
+      "misk.tailwind.icons",
+      "misk.tailwind.pages"
+    ],
+    "com.squareup.misk:misk-testing-api": [
+      "misk.testing"
+    ],
+    "com.squareup.moshi:moshi": [
+      "com.squareup.moshi",
+      "com.squareup.moshi.internal"
+    ],
+    "com.squareup.moshi:moshi-adapters": [
+      "com.squareup.moshi",
+      "com.squareup.moshi.adapters"
+    ],
+    "com.squareup.moshi:moshi-kotlin": [
+      "com.squareup.moshi",
+      "com.squareup.moshi.kotlin.reflect"
+    ],
+    "com.squareup.okhttp3:okhttp-jvm": [
+      "okhttp3",
+      "okhttp3.internal",
+      "okhttp3.internal.authenticator",
+      "okhttp3.internal.cache",
+      "okhttp3.internal.concurrent",
+      "okhttp3.internal.connection",
+      "okhttp3.internal.graal",
+      "okhttp3.internal.http",
+      "okhttp3.internal.http1",
+      "okhttp3.internal.http2",
+      "okhttp3.internal.http2.flowcontrol",
+      "okhttp3.internal.idn",
+      "okhttp3.internal.platform",
+      "okhttp3.internal.proxy",
+      "okhttp3.internal.publicsuffix",
+      "okhttp3.internal.tls",
+      "okhttp3.internal.url",
+      "okhttp3.internal.ws"
+    ],
+    "com.squareup.okio:okio-jvm": [
+      "okio",
+      "okio.internal"
+    ],
+    "com.squareup.wire:wire-grpc-client-jvm": [
+      "com.squareup.wire",
+      "com.squareup.wire.internal"
+    ],
+    "com.squareup.wire:wire-moshi-adapter": [
+      "com.squareup.wire"
+    ],
+    "com.squareup.wire:wire-runtime-jvm": [
+      "com.squareup.wire",
+      "com.squareup.wire.internal"
+    ],
+    "com.typesafe:config": [
+      "com.typesafe.config",
+      "com.typesafe.config.impl",
+      "com.typesafe.config.parser"
+    ],
+    "io.github.microutils:kotlin-logging-jvm": [
+      "mu",
+      "mu.internal"
+    ],
+    "io.micrometer:micrometer-commons": [
+      "io.micrometer.common",
+      "io.micrometer.common.annotation",
+      "io.micrometer.common.docs",
+      "io.micrometer.common.lang",
+      "io.micrometer.common.lang.internal",
+      "io.micrometer.common.util",
+      "io.micrometer.common.util.internal.logging"
+    ],
+    "io.micrometer:micrometer-core": [
+      "io.micrometer.core.annotation",
+      "io.micrometer.core.aop",
+      "io.micrometer.core.instrument",
+      "io.micrometer.core.instrument.binder",
+      "io.micrometer.core.instrument.binder.cache",
+      "io.micrometer.core.instrument.binder.commonspool2",
+      "io.micrometer.core.instrument.binder.db",
+      "io.micrometer.core.instrument.binder.grpc",
+      "io.micrometer.core.instrument.binder.http",
+      "io.micrometer.core.instrument.binder.httpcomponents",
+      "io.micrometer.core.instrument.binder.httpcomponents.hc5",
+      "io.micrometer.core.instrument.binder.hystrix",
+      "io.micrometer.core.instrument.binder.jersey.server",
+      "io.micrometer.core.instrument.binder.jetty",
+      "io.micrometer.core.instrument.binder.jpa",
+      "io.micrometer.core.instrument.binder.jvm",
+      "io.micrometer.core.instrument.binder.jvm.convention",
+      "io.micrometer.core.instrument.binder.jvm.convention.micrometer",
+      "io.micrometer.core.instrument.binder.jvm.convention.otel",
+      "io.micrometer.core.instrument.binder.kafka",
+      "io.micrometer.core.instrument.binder.logging",
+      "io.micrometer.core.instrument.binder.mongodb",
+      "io.micrometer.core.instrument.binder.netty4",
+      "io.micrometer.core.instrument.binder.okhttp3",
+      "io.micrometer.core.instrument.binder.system",
+      "io.micrometer.core.instrument.binder.tomcat",
+      "io.micrometer.core.instrument.composite",
+      "io.micrometer.core.instrument.config",
+      "io.micrometer.core.instrument.config.validate",
+      "io.micrometer.core.instrument.cumulative",
+      "io.micrometer.core.instrument.distribution",
+      "io.micrometer.core.instrument.distribution.pause",
+      "io.micrometer.core.instrument.docs",
+      "io.micrometer.core.instrument.dropwizard",
+      "io.micrometer.core.instrument.internal",
+      "io.micrometer.core.instrument.kotlin",
+      "io.micrometer.core.instrument.logging",
+      "io.micrometer.core.instrument.noop",
+      "io.micrometer.core.instrument.observation",
+      "io.micrometer.core.instrument.push",
+      "io.micrometer.core.instrument.search",
+      "io.micrometer.core.instrument.simple",
+      "io.micrometer.core.instrument.step",
+      "io.micrometer.core.instrument.util",
+      "io.micrometer.core.ipc.http",
+      "io.micrometer.core.util.internal.logging"
+    ],
+    "io.micrometer:micrometer-observation": [
+      "io.micrometer.observation",
+      "io.micrometer.observation.annotation",
+      "io.micrometer.observation.aop",
+      "io.micrometer.observation.contextpropagation",
+      "io.micrometer.observation.docs",
+      "io.micrometer.observation.transport"
+    ],
+    "jakarta.inject:jakarta.inject-api": [
+      "jakarta.inject"
+    ],
+    "javax.inject:javax.inject": [
+      "javax.inject"
+    ],
+    "org.antlr:antlr4-runtime": [
+      "org.antlr.v4.runtime",
+      "org.antlr.v4.runtime.atn",
+      "org.antlr.v4.runtime.dfa",
+      "org.antlr.v4.runtime.misc",
+      "org.antlr.v4.runtime.tree",
+      "org.antlr.v4.runtime.tree.pattern",
+      "org.antlr.v4.runtime.tree.xpath"
+    ],
+    "org.apache.commons:commons-lang3": [
+      "org.apache.commons.lang3",
+      "org.apache.commons.lang3.arch",
+      "org.apache.commons.lang3.builder",
+      "org.apache.commons.lang3.compare",
+      "org.apache.commons.lang3.concurrent",
+      "org.apache.commons.lang3.concurrent.locks",
+      "org.apache.commons.lang3.event",
+      "org.apache.commons.lang3.exception",
+      "org.apache.commons.lang3.function",
+      "org.apache.commons.lang3.math",
+      "org.apache.commons.lang3.mutable",
+      "org.apache.commons.lang3.reflect",
+      "org.apache.commons.lang3.stream",
+      "org.apache.commons.lang3.text",
+      "org.apache.commons.lang3.text.translate",
+      "org.apache.commons.lang3.time",
+      "org.apache.commons.lang3.tuple",
+      "org.apache.commons.lang3.util"
+    ],
+    "org.bouncycastle:bcprov-jdk18on": [
+      "org.bouncycastle",
+      "org.bouncycastle.asn1",
+      "org.bouncycastle.asn1.anssi",
+      "org.bouncycastle.asn1.bc",
+      "org.bouncycastle.asn1.cryptopro",
+      "org.bouncycastle.asn1.gm",
+      "org.bouncycastle.asn1.nist",
+      "org.bouncycastle.asn1.ocsp",
+      "org.bouncycastle.asn1.pkcs",
+      "org.bouncycastle.asn1.sec",
+      "org.bouncycastle.asn1.teletrust",
+      "org.bouncycastle.asn1.ua",
+      "org.bouncycastle.asn1.util",
+      "org.bouncycastle.asn1.x500",
+      "org.bouncycastle.asn1.x500.style",
+      "org.bouncycastle.asn1.x509",
+      "org.bouncycastle.asn1.x509.qualified",
+      "org.bouncycastle.asn1.x509.sigi",
+      "org.bouncycastle.asn1.x9",
+      "org.bouncycastle.crypto",
+      "org.bouncycastle.crypto.agreement",
+      "org.bouncycastle.crypto.agreement.ecjpake",
+      "org.bouncycastle.crypto.agreement.jpake",
+      "org.bouncycastle.crypto.agreement.kdf",
+      "org.bouncycastle.crypto.agreement.srp",
+      "org.bouncycastle.crypto.commitments",
+      "org.bouncycastle.crypto.constraints",
+      "org.bouncycastle.crypto.digests",
+      "org.bouncycastle.crypto.ec",
+      "org.bouncycastle.crypto.encodings",
+      "org.bouncycastle.crypto.engines",
+      "org.bouncycastle.crypto.examples",
+      "org.bouncycastle.crypto.fpe",
+      "org.bouncycastle.crypto.generators",
+      "org.bouncycastle.crypto.hpke",
+      "org.bouncycastle.crypto.io",
+      "org.bouncycastle.crypto.kems",
+      "org.bouncycastle.crypto.macs",
+      "org.bouncycastle.crypto.modes",
+      "org.bouncycastle.crypto.modes.gcm",
+      "org.bouncycastle.crypto.modes.kgcm",
+      "org.bouncycastle.crypto.paddings",
+      "org.bouncycastle.crypto.params",
+      "org.bouncycastle.crypto.parsers",
+      "org.bouncycastle.crypto.prng",
+      "org.bouncycastle.crypto.prng.drbg",
+      "org.bouncycastle.crypto.signers",
+      "org.bouncycastle.crypto.threshold",
+      "org.bouncycastle.crypto.tls",
+      "org.bouncycastle.crypto.util",
+      "org.bouncycastle.i18n",
+      "org.bouncycastle.i18n.filter",
+      "org.bouncycastle.iana",
+      "org.bouncycastle.internal.asn1.bsi",
+      "org.bouncycastle.internal.asn1.cms",
+      "org.bouncycastle.internal.asn1.cryptlib",
+      "org.bouncycastle.internal.asn1.eac",
+      "org.bouncycastle.internal.asn1.edec",
+      "org.bouncycastle.internal.asn1.gnu",
+      "org.bouncycastle.internal.asn1.iana",
+      "org.bouncycastle.internal.asn1.isara",
+      "org.bouncycastle.internal.asn1.isismtt",
+      "org.bouncycastle.internal.asn1.iso",
+      "org.bouncycastle.internal.asn1.kisa",
+      "org.bouncycastle.internal.asn1.microsoft",
+      "org.bouncycastle.internal.asn1.misc",
+      "org.bouncycastle.internal.asn1.nsri",
+      "org.bouncycastle.internal.asn1.ntt",
+      "org.bouncycastle.internal.asn1.oiw",
+      "org.bouncycastle.internal.asn1.rosstandart",
+      "org.bouncycastle.jcajce",
+      "org.bouncycastle.jcajce.interfaces",
+      "org.bouncycastle.jcajce.io",
+      "org.bouncycastle.jcajce.provider.asymmetric",
+      "org.bouncycastle.jcajce.provider.asymmetric.compositesignatures",
+      "org.bouncycastle.jcajce.provider.asymmetric.dh",
+      "org.bouncycastle.jcajce.provider.asymmetric.dsa",
+      "org.bouncycastle.jcajce.provider.asymmetric.dstu",
+      "org.bouncycastle.jcajce.provider.asymmetric.ec",
+      "org.bouncycastle.jcajce.provider.asymmetric.ecgost",
+      "org.bouncycastle.jcajce.provider.asymmetric.ecgost12",
+      "org.bouncycastle.jcajce.provider.asymmetric.edec",
+      "org.bouncycastle.jcajce.provider.asymmetric.elgamal",
+      "org.bouncycastle.jcajce.provider.asymmetric.gost",
+      "org.bouncycastle.jcajce.provider.asymmetric.ies",
+      "org.bouncycastle.jcajce.provider.asymmetric.mldsa",
+      "org.bouncycastle.jcajce.provider.asymmetric.mlkem",
+      "org.bouncycastle.jcajce.provider.asymmetric.rsa",
+      "org.bouncycastle.jcajce.provider.asymmetric.slhdsa",
+      "org.bouncycastle.jcajce.provider.asymmetric.util",
+      "org.bouncycastle.jcajce.provider.asymmetric.x509",
+      "org.bouncycastle.jcajce.provider.config",
+      "org.bouncycastle.jcajce.provider.digest",
+      "org.bouncycastle.jcajce.provider.drbg",
+      "org.bouncycastle.jcajce.provider.keystore",
+      "org.bouncycastle.jcajce.provider.keystore.bc",
+      "org.bouncycastle.jcajce.provider.keystore.bcfks",
+      "org.bouncycastle.jcajce.provider.keystore.pkcs12",
+      "org.bouncycastle.jcajce.provider.keystore.util",
+      "org.bouncycastle.jcajce.provider.symmetric",
+      "org.bouncycastle.jcajce.provider.symmetric.util",
+      "org.bouncycastle.jcajce.provider.util",
+      "org.bouncycastle.jcajce.spec",
+      "org.bouncycastle.jcajce.util",
+      "org.bouncycastle.jce",
+      "org.bouncycastle.jce.exception",
+      "org.bouncycastle.jce.interfaces",
+      "org.bouncycastle.jce.netscape",
+      "org.bouncycastle.jce.provider",
+      "org.bouncycastle.jce.spec",
+      "org.bouncycastle.math",
+      "org.bouncycastle.math.ec",
+      "org.bouncycastle.math.ec.custom.djb",
+      "org.bouncycastle.math.ec.custom.gm",
+      "org.bouncycastle.math.ec.custom.sec",
+      "org.bouncycastle.math.ec.endo",
+      "org.bouncycastle.math.ec.rfc7748",
+      "org.bouncycastle.math.ec.rfc8032",
+      "org.bouncycastle.math.ec.tools",
+      "org.bouncycastle.math.field",
+      "org.bouncycastle.math.raw",
+      "org.bouncycastle.pqc.asn1",
+      "org.bouncycastle.pqc.crypto",
+      "org.bouncycastle.pqc.crypto.bike",
+      "org.bouncycastle.pqc.crypto.cmce",
+      "org.bouncycastle.pqc.crypto.crystals.dilithium",
+      "org.bouncycastle.pqc.crypto.falcon",
+      "org.bouncycastle.pqc.crypto.frodo",
+      "org.bouncycastle.pqc.crypto.hqc",
+      "org.bouncycastle.pqc.crypto.lms",
+      "org.bouncycastle.pqc.crypto.mayo",
+      "org.bouncycastle.pqc.crypto.mldsa",
+      "org.bouncycastle.pqc.crypto.mlkem",
+      "org.bouncycastle.pqc.crypto.newhope",
+      "org.bouncycastle.pqc.crypto.ntru",
+      "org.bouncycastle.pqc.crypto.ntruprime",
+      "org.bouncycastle.pqc.crypto.picnic",
+      "org.bouncycastle.pqc.crypto.rainbow",
+      "org.bouncycastle.pqc.crypto.saber",
+      "org.bouncycastle.pqc.crypto.slhdsa",
+      "org.bouncycastle.pqc.crypto.snova",
+      "org.bouncycastle.pqc.crypto.sphincs",
+      "org.bouncycastle.pqc.crypto.sphincsplus",
+      "org.bouncycastle.pqc.crypto.util",
+      "org.bouncycastle.pqc.crypto.xmss",
+      "org.bouncycastle.pqc.crypto.xwing",
+      "org.bouncycastle.pqc.jcajce.interfaces",
+      "org.bouncycastle.pqc.jcajce.provider",
+      "org.bouncycastle.pqc.jcajce.provider.bike",
+      "org.bouncycastle.pqc.jcajce.provider.cmce",
+      "org.bouncycastle.pqc.jcajce.provider.dilithium",
+      "org.bouncycastle.pqc.jcajce.provider.falcon",
+      "org.bouncycastle.pqc.jcajce.provider.frodo",
+      "org.bouncycastle.pqc.jcajce.provider.hqc",
+      "org.bouncycastle.pqc.jcajce.provider.kyber",
+      "org.bouncycastle.pqc.jcajce.provider.lms",
+      "org.bouncycastle.pqc.jcajce.provider.mayo",
+      "org.bouncycastle.pqc.jcajce.provider.newhope",
+      "org.bouncycastle.pqc.jcajce.provider.ntru",
+      "org.bouncycastle.pqc.jcajce.provider.ntruprime",
+      "org.bouncycastle.pqc.jcajce.provider.picnic",
+      "org.bouncycastle.pqc.jcajce.provider.saber",
+      "org.bouncycastle.pqc.jcajce.provider.snova",
+      "org.bouncycastle.pqc.jcajce.provider.sphincs",
+      "org.bouncycastle.pqc.jcajce.provider.sphincsplus",
+      "org.bouncycastle.pqc.jcajce.provider.util",
+      "org.bouncycastle.pqc.jcajce.provider.xmss",
+      "org.bouncycastle.pqc.jcajce.spec",
+      "org.bouncycastle.pqc.math.ntru",
+      "org.bouncycastle.pqc.math.ntru.parameters",
+      "org.bouncycastle.util",
+      "org.bouncycastle.util.encoders",
+      "org.bouncycastle.util.io",
+      "org.bouncycastle.util.io.pem",
+      "org.bouncycastle.util.test",
+      "org.bouncycastle.x509",
+      "org.bouncycastle.x509.extension",
+      "org.bouncycastle.x509.util"
+    ],
+    "org.checkerframework:checker-qual": [
+      "org.checkerframework.checker.builder.qual",
+      "org.checkerframework.checker.calledmethods.qual",
+      "org.checkerframework.checker.compilermsgs.qual",
+      "org.checkerframework.checker.fenum.qual",
+      "org.checkerframework.checker.formatter.qual",
+      "org.checkerframework.checker.guieffect.qual",
+      "org.checkerframework.checker.i18n.qual",
+      "org.checkerframework.checker.i18nformatter.qual",
+      "org.checkerframework.checker.index.qual",
+      "org.checkerframework.checker.initialization.qual",
+      "org.checkerframework.checker.interning.qual",
+      "org.checkerframework.checker.lock.qual",
+      "org.checkerframework.checker.mustcall.qual",
+      "org.checkerframework.checker.nullness.qual",
+      "org.checkerframework.checker.optional.qual",
+      "org.checkerframework.checker.propkey.qual",
+      "org.checkerframework.checker.regex.qual",
+      "org.checkerframework.checker.signature.qual",
+      "org.checkerframework.checker.signedness.qual",
+      "org.checkerframework.checker.tainting.qual",
+      "org.checkerframework.checker.units.qual",
+      "org.checkerframework.common.aliasing.qual",
+      "org.checkerframework.common.initializedfields.qual",
+      "org.checkerframework.common.reflection.qual",
+      "org.checkerframework.common.returnsreceiver.qual",
+      "org.checkerframework.common.subtyping.qual",
+      "org.checkerframework.common.util.report.qual",
+      "org.checkerframework.common.value.qual",
+      "org.checkerframework.dataflow.qual",
+      "org.checkerframework.framework.qual"
+    ],
+    "org.hdrhistogram:HdrHistogram": [
+      "org.HdrHistogram",
+      "org.HdrHistogram.packedarray"
+    ],
+    "org.jetbrains.kotlin:kotlin-reflect": [
+      "kotlin.reflect.full",
+      "kotlin.reflect.jvm",
+      "kotlin.reflect.jvm.internal",
+      "kotlin.reflect.jvm.internal.calls",
+      "kotlin.reflect.jvm.internal.impl",
+      "kotlin.reflect.jvm.internal.impl.builtins",
+      "kotlin.reflect.jvm.internal.impl.builtins.functions",
+      "kotlin.reflect.jvm.internal.impl.builtins.jvm",
+      "kotlin.reflect.jvm.internal.impl.descriptors",
+      "kotlin.reflect.jvm.internal.impl.descriptors.annotations",
+      "kotlin.reflect.jvm.internal.impl.descriptors.deserialization",
+      "kotlin.reflect.jvm.internal.impl.descriptors.impl",
+      "kotlin.reflect.jvm.internal.impl.descriptors.java",
+      "kotlin.reflect.jvm.internal.impl.descriptors.runtime.components",
+      "kotlin.reflect.jvm.internal.impl.descriptors.runtime.structure",
+      "kotlin.reflect.jvm.internal.impl.incremental",
+      "kotlin.reflect.jvm.internal.impl.incremental.components",
+      "kotlin.reflect.jvm.internal.impl.km",
+      "kotlin.reflect.jvm.internal.impl.km.internal",
+      "kotlin.reflect.jvm.internal.impl.km.internal.common",
+      "kotlin.reflect.jvm.internal.impl.km.internal.extensions",
+      "kotlin.reflect.jvm.internal.impl.km.jvm",
+      "kotlin.reflect.jvm.internal.impl.km.jvm.internal",
+      "kotlin.reflect.jvm.internal.impl.load.java",
+      "kotlin.reflect.jvm.internal.impl.load.java.components",
+      "kotlin.reflect.jvm.internal.impl.load.java.descriptors",
+      "kotlin.reflect.jvm.internal.impl.load.java.lazy",
+      "kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors",
+      "kotlin.reflect.jvm.internal.impl.load.java.lazy.types",
+      "kotlin.reflect.jvm.internal.impl.load.java.sources",
+      "kotlin.reflect.jvm.internal.impl.load.java.structure",
+      "kotlin.reflect.jvm.internal.impl.load.java.typeEnhancement",
+      "kotlin.reflect.jvm.internal.impl.load.kotlin",
+      "kotlin.reflect.jvm.internal.impl.load.kotlin.header",
+      "kotlin.reflect.jvm.internal.impl.metadata",
+      "kotlin.reflect.jvm.internal.impl.metadata.builtins",
+      "kotlin.reflect.jvm.internal.impl.metadata.deserialization",
+      "kotlin.reflect.jvm.internal.impl.metadata.jvm",
+      "kotlin.reflect.jvm.internal.impl.metadata.jvm.deserialization",
+      "kotlin.reflect.jvm.internal.impl.metadata.serialization",
+      "kotlin.reflect.jvm.internal.impl.name",
+      "kotlin.reflect.jvm.internal.impl.platform",
+      "kotlin.reflect.jvm.internal.impl.protobuf",
+      "kotlin.reflect.jvm.internal.impl.renderer",
+      "kotlin.reflect.jvm.internal.impl.resolve",
+      "kotlin.reflect.jvm.internal.impl.resolve.calls.inference",
+      "kotlin.reflect.jvm.internal.impl.resolve.constants",
+      "kotlin.reflect.jvm.internal.impl.resolve.deprecation",
+      "kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil",
+      "kotlin.reflect.jvm.internal.impl.resolve.jvm",
+      "kotlin.reflect.jvm.internal.impl.resolve.sam",
+      "kotlin.reflect.jvm.internal.impl.resolve.scopes",
+      "kotlin.reflect.jvm.internal.impl.resolve.scopes.receivers",
+      "kotlin.reflect.jvm.internal.impl.serialization",
+      "kotlin.reflect.jvm.internal.impl.serialization.deserialization",
+      "kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins",
+      "kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors",
+      "kotlin.reflect.jvm.internal.impl.storage",
+      "kotlin.reflect.jvm.internal.impl.types",
+      "kotlin.reflect.jvm.internal.impl.types.checker",
+      "kotlin.reflect.jvm.internal.impl.types.error",
+      "kotlin.reflect.jvm.internal.impl.types.extensions",
+      "kotlin.reflect.jvm.internal.impl.types.model",
+      "kotlin.reflect.jvm.internal.impl.types.typeUtil",
+      "kotlin.reflect.jvm.internal.impl.types.typesApproximation",
+      "kotlin.reflect.jvm.internal.impl.util",
+      "kotlin.reflect.jvm.internal.impl.util.capitalizeDecapitalize",
+      "kotlin.reflect.jvm.internal.impl.util.collectionUtils",
+      "kotlin.reflect.jvm.internal.impl.utils",
+      "kotlin.reflect.jvm.internal.impl.utils.addToStdlib"
+    ],
+    "org.jetbrains.kotlin:kotlin-stdlib": [
+      "kotlin",
+      "kotlin.annotation",
+      "kotlin.collections",
+      "kotlin.collections.builders",
+      "kotlin.collections.jdk8",
+      "kotlin.collections.unsigned",
+      "kotlin.comparisons",
+      "kotlin.concurrent",
+      "kotlin.concurrent.atomics",
+      "kotlin.concurrent.internal",
+      "kotlin.contracts",
+      "kotlin.coroutines",
+      "kotlin.coroutines.cancellation",
+      "kotlin.coroutines.intrinsics",
+      "kotlin.coroutines.jvm.internal",
+      "kotlin.enums",
+      "kotlin.experimental",
+      "kotlin.internal",
+      "kotlin.internal.jdk7",
+      "kotlin.internal.jdk8",
+      "kotlin.io",
+      "kotlin.io.encoding",
+      "kotlin.io.path",
+      "kotlin.jdk7",
+      "kotlin.js",
+      "kotlin.jvm",
+      "kotlin.jvm.functions",
+      "kotlin.jvm.internal",
+      "kotlin.jvm.internal.markers",
+      "kotlin.jvm.internal.unsafe",
+      "kotlin.jvm.jdk8",
+      "kotlin.jvm.optionals",
+      "kotlin.math",
+      "kotlin.properties",
+      "kotlin.random",
+      "kotlin.random.jdk8",
+      "kotlin.ranges",
+      "kotlin.reflect",
+      "kotlin.sequences",
+      "kotlin.streams.jdk8",
+      "kotlin.system",
+      "kotlin.text",
+      "kotlin.text.jdk8",
+      "kotlin.time",
+      "kotlin.time.jdk8",
+      "kotlin.uuid"
+    ],
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": [
+      "_COROUTINE",
+      "kotlinx.coroutines",
+      "kotlinx.coroutines.channels",
+      "kotlinx.coroutines.debug.internal",
+      "kotlinx.coroutines.flow",
+      "kotlinx.coroutines.flow.internal",
+      "kotlinx.coroutines.future",
+      "kotlinx.coroutines.internal",
+      "kotlinx.coroutines.intrinsics",
+      "kotlinx.coroutines.scheduling",
+      "kotlinx.coroutines.selects",
+      "kotlinx.coroutines.stream",
+      "kotlinx.coroutines.sync",
+      "kotlinx.coroutines.time"
+    ],
+    "org.jetbrains.kotlinx:kotlinx-html-jvm": [
+      "kotlinx.html",
+      "kotlinx.html.attributes",
+      "kotlinx.html.consumers",
+      "kotlinx.html.dom",
+      "kotlinx.html.impl",
+      "kotlinx.html.org.w3c.dom.events",
+      "kotlinx.html.stream"
+    ],
+    "org.jetbrains:annotations": [
+      "org.intellij.lang.annotations",
+      "org.jetbrains.annotations"
+    ],
+    "org.jspecify:jspecify": [
+      "org.jspecify.annotations"
+    ],
+    "org.slf4j:slf4j-api": [
+      "org.slf4j",
+      "org.slf4j.event",
+      "org.slf4j.helpers",
+      "org.slf4j.spi"
+    ],
+    "org.tomlj:tomlj": [
+      "org.tomlj",
+      "org.tomlj.internal"
+    ],
+    "org.yaml:snakeyaml": [
+      "org.yaml.snakeyaml",
+      "org.yaml.snakeyaml.comments",
+      "org.yaml.snakeyaml.composer",
+      "org.yaml.snakeyaml.constructor",
+      "org.yaml.snakeyaml.emitter",
+      "org.yaml.snakeyaml.env",
+      "org.yaml.snakeyaml.error",
+      "org.yaml.snakeyaml.events",
+      "org.yaml.snakeyaml.extensions.compactnotation",
+      "org.yaml.snakeyaml.external.com.google.gdata.util.common.base",
+      "org.yaml.snakeyaml.inspector",
+      "org.yaml.snakeyaml.internal",
+      "org.yaml.snakeyaml.introspector",
+      "org.yaml.snakeyaml.nodes",
+      "org.yaml.snakeyaml.parser",
+      "org.yaml.snakeyaml.reader",
+      "org.yaml.snakeyaml.representer",
+      "org.yaml.snakeyaml.resolver",
+      "org.yaml.snakeyaml.scanner",
+      "org.yaml.snakeyaml.serializer",
+      "org.yaml.snakeyaml.tokens",
+      "org.yaml.snakeyaml.util"
+    ]
+  },
+  "repositories": {
+    "https://repo1.maven.org/maven2/": [
+      "aopalliance:aopalliance",
+      "app.cash.wisp:wisp-config",
+      "app.cash.wisp:wisp-deployment",
+      "app.cash.wisp:wisp-feature",
+      "app.cash.wisp:wisp-feature-testing",
+      "app.cash.wisp:wisp-logging",
+      "app.cash.wisp:wisp-moshi",
+      "app.cash.wisp:wisp-resource-loader",
+      "app.cash.wisp:wisp-sampling",
+      "com.fasterxml.jackson.core:jackson-annotations",
+      "com.fasterxml.jackson.core:jackson-core",
+      "com.fasterxml.jackson.core:jackson-databind",
+      "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml",
+      "com.fasterxml.jackson.datatype:jackson-datatype-jsr310",
+      "com.fasterxml.jackson.module:jackson-module-kotlin",
+      "com.google.errorprone:error_prone_annotations",
+      "com.google.guava:failureaccess",
+      "com.google.guava:guava",
+      "com.google.guava:listenablefuture",
+      "com.google.inject:guice",
+      "com.google.j2objc:j2objc-annotations",
+      "com.sksamuel.hoplite:hoplite-core",
+      "com.sksamuel.hoplite:hoplite-hocon",
+      "com.sksamuel.hoplite:hoplite-json",
+      "com.sksamuel.hoplite:hoplite-toml",
+      "com.sksamuel.hoplite:hoplite-yaml",
+      "com.squareup.misk:misk-actions",
+      "com.squareup.misk:misk-api",
+      "com.squareup.misk:misk-config",
+      "com.squareup.misk:misk-feature",
+      "com.squareup.misk:misk-feature:jar:test-fixtures",
+      "com.squareup.misk:misk-hotwire",
+      "com.squareup.misk:misk-inject",
+      "com.squareup.misk:misk-logging",
+      "com.squareup.misk:misk-moshi",
+      "com.squareup.misk:misk-sampling",
+      "com.squareup.misk:misk-service",
+      "com.squareup.misk:misk-tailwind",
+      "com.squareup.misk:misk-testing-api",
+      "com.squareup.moshi:moshi",
+      "com.squareup.moshi:moshi-adapters",
+      "com.squareup.moshi:moshi-kotlin",
+      "com.squareup.okhttp3:okhttp-jvm",
+      "com.squareup.okio:okio-jvm",
+      "com.squareup.wire:wire-grpc-client-jvm",
+      "com.squareup.wire:wire-moshi-adapter",
+      "com.squareup.wire:wire-runtime-jvm",
+      "com.typesafe:config",
+      "io.github.microutils:kotlin-logging-jvm",
+      "io.micrometer:micrometer-commons",
+      "io.micrometer:micrometer-core",
+      "io.micrometer:micrometer-observation",
+      "jakarta.inject:jakarta.inject-api",
+      "javax.inject:javax.inject",
+      "org.antlr:antlr4-runtime",
+      "org.apache.commons:commons-lang3",
+      "org.bouncycastle:bcprov-jdk18on",
+      "org.checkerframework:checker-qual",
+      "org.hdrhistogram:HdrHistogram",
+      "org.jetbrains.kotlin:kotlin-reflect",
+      "org.jetbrains.kotlin:kotlin-stdlib",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk7",
+      "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
+      "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm",
+      "org.jetbrains.kotlinx:kotlinx-html-jvm",
+      "org.jetbrains:annotations",
+      "org.jspecify:jspecify",
+      "org.slf4j:slf4j-api",
+      "org.tomlj:tomlj",
+      "org.yaml:snakeyaml"
+    ]
+  },
+  "services": {
+    "com.fasterxml.jackson.core:jackson-core": {
+      "com.fasterxml.jackson.core.JsonFactory": [
+        "com.fasterxml.jackson.core.JsonFactory"
+      ]
+    },
+    "com.fasterxml.jackson.core:jackson-databind": {
+      "com.fasterxml.jackson.core.ObjectCodec": [
+        "com.fasterxml.jackson.databind.ObjectMapper"
+      ]
+    },
+    "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml": {
+      "com.fasterxml.jackson.core.JsonFactory": [
+        "com.fasterxml.jackson.dataformat.yaml.YAMLFactory"
+      ],
+      "com.fasterxml.jackson.core.ObjectCodec": [
+        "com.fasterxml.jackson.dataformat.yaml.YAMLMapper"
+      ]
+    },
+    "com.fasterxml.jackson.datatype:jackson-datatype-jsr310": {
+      "com.fasterxml.jackson.databind.Module": [
+        "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"
+      ]
+    },
+    "com.fasterxml.jackson.module:jackson-module-kotlin": {
+      "com.fasterxml.jackson.databind.Module": [
+        "com.fasterxml.jackson.module.kotlin.KotlinModule"
+      ]
+    },
+    "com.sksamuel.hoplite:hoplite-core": {
+      "com.sksamuel.hoplite.decoder.Decoder": [
+        "com.sksamuel.hoplite.decoder.Base64Decoder",
+        "com.sksamuel.hoplite.decoder.BigDecimalDecoder",
+        "com.sksamuel.hoplite.decoder.BigIntegerDecoder",
+        "com.sksamuel.hoplite.decoder.BooleanArrayDecoder",
+        "com.sksamuel.hoplite.decoder.BooleanDecoder",
+        "com.sksamuel.hoplite.decoder.ByteArrayDecoder",
+        "com.sksamuel.hoplite.decoder.ByteDecoder",
+        "com.sksamuel.hoplite.decoder.CharRangeDecoder",
+        "com.sksamuel.hoplite.decoder.DataClassDecoder",
+        "com.sksamuel.hoplite.decoder.DoubleDecoder",
+        "com.sksamuel.hoplite.decoder.DurationDecoder",
+        "com.sksamuel.hoplite.decoder.EnumDecoder",
+        "com.sksamuel.hoplite.decoder.FileDecoder",
+        "com.sksamuel.hoplite.decoder.FloatDecoder",
+        "com.sksamuel.hoplite.decoder.InetAddressDecoder",
+        "com.sksamuel.hoplite.decoder.InlineClassDecoder",
+        "com.sksamuel.hoplite.decoder.InstantDecoder",
+        "com.sksamuel.hoplite.decoder.IntDecoder",
+        "com.sksamuel.hoplite.decoder.IntRangeDecoder",
+        "com.sksamuel.hoplite.decoder.JavaUtilDateDecoder",
+        "com.sksamuel.hoplite.decoder.KClassDecoder",
+        "com.sksamuel.hoplite.decoder.KotlinDurationDecoder",
+        "com.sksamuel.hoplite.decoder.LinkedHashMapDecoder",
+        "com.sksamuel.hoplite.decoder.ListDecoder",
+        "com.sksamuel.hoplite.decoder.LocalDateDecoder",
+        "com.sksamuel.hoplite.decoder.LocalDateTimeDecoder",
+        "com.sksamuel.hoplite.decoder.LocalTimeDecoder",
+        "com.sksamuel.hoplite.decoder.LocaleDecoder",
+        "com.sksamuel.hoplite.decoder.LongDecoder",
+        "com.sksamuel.hoplite.decoder.LongRangeDecoder",
+        "com.sksamuel.hoplite.decoder.MapDecoder",
+        "com.sksamuel.hoplite.decoder.MinutesDecoder",
+        "com.sksamuel.hoplite.decoder.MonthDayDecoder",
+        "com.sksamuel.hoplite.decoder.PairDecoder",
+        "com.sksamuel.hoplite.decoder.PathDecoder",
+        "com.sksamuel.hoplite.decoder.PeriodDecoder",
+        "com.sksamuel.hoplite.decoder.PrincipalDecoder",
+        "com.sksamuel.hoplite.decoder.PropsDecoder",
+        "com.sksamuel.hoplite.decoder.RegexDecoder",
+        "com.sksamuel.hoplite.decoder.SealedClassDecoder",
+        "com.sksamuel.hoplite.decoder.SecondsDecoder",
+        "com.sksamuel.hoplite.decoder.SecretDecoder",
+        "com.sksamuel.hoplite.decoder.SetDecoder",
+        "com.sksamuel.hoplite.decoder.ShortDecoder",
+        "com.sksamuel.hoplite.decoder.SizeInBytesDecoder",
+        "com.sksamuel.hoplite.decoder.SortedSetDecoder",
+        "com.sksamuel.hoplite.decoder.SqlTimestampDecoder",
+        "com.sksamuel.hoplite.decoder.StringDecoder",
+        "com.sksamuel.hoplite.decoder.TripleDecoder",
+        "com.sksamuel.hoplite.decoder.URIDecoder",
+        "com.sksamuel.hoplite.decoder.URLDecoder",
+        "com.sksamuel.hoplite.decoder.UUIDDecoder",
+        "com.sksamuel.hoplite.decoder.YearDecoder",
+        "com.sksamuel.hoplite.decoder.YearMonthDecoder"
+      ],
+      "com.sksamuel.hoplite.parsers.Parser": [
+        "com.sksamuel.hoplite.parsers.PropsParser"
+      ]
+    },
+    "com.sksamuel.hoplite:hoplite-hocon": {
+      "com.sksamuel.hoplite.parsers.Parser": [
+        "com.sksamuel.hoplite.hocon.HoconParser"
+      ]
+    },
+    "com.sksamuel.hoplite:hoplite-json": {
+      "com.sksamuel.hoplite.parsers.Parser": [
+        "com.sksamuel.hoplite.json.JsonParser"
+      ]
+    },
+    "com.sksamuel.hoplite:hoplite-toml": {
+      "com.sksamuel.hoplite.parsers.Parser": [
+        "com.sksamuel.hoplite.toml.TomlParser"
+      ]
+    },
+    "com.sksamuel.hoplite:hoplite-yaml": {
+      "com.sksamuel.hoplite.parsers.Parser": [
+        "com.sksamuel.hoplite.yaml.YamlParser"
+      ]
+    },
+    "io.micrometer:micrometer-observation": {
+      "io.micrometer.context.ThreadLocalAccessor": [
+        "io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor"
+      ]
+    },
+    "org.bouncycastle:bcprov-jdk18on": {
+      "java.security.Provider": [
+        "org.bouncycastle.jce.provider.BouncyCastleProvider",
+        "org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider"
+      ]
+    },
+    "org.jetbrains.kotlin:kotlin-reflect": {
+      "kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader": [
+        "kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl"
+      ],
+      "kotlin.reflect.jvm.internal.impl.km.internal.extensions.MetadataExtensions": [
+        "kotlin.reflect.jvm.internal.impl.km.jvm.internal.JvmMetadataExtensions"
+      ],
+      "kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition": [
+        "kotlin.reflect.jvm.internal.impl.load.java.ErasedOverridabilityCondition",
+        "kotlin.reflect.jvm.internal.impl.load.java.FieldOverridabilityCondition",
+        "kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition"
+      ]
+    }
+  },
+  "skipped": [
+    "app.cash.tempest:tempest-bom",
+    "com.fasterxml.jackson:jackson-bom",
+    "com.google.guava:guava-bom",
+    "com.google.inject:guice-bom",
+    "com.squareup.misk:misk-bom",
+    "com.squareup.okhttp3:okhttp",
+    "com.squareup.okio:okio",
+    "com.squareup.wire:wire-bom",
+    "com.squareup.wire:wire-grpc-client",
+    "com.squareup.wire:wire-runtime",
+    "io.github.microutils:kotlin-logging",
+    "io.grpc:grpc-bom",
+    "io.netty:netty-bom",
+    "io.prometheus:simpleclient_bom",
+    "org.eclipse.jetty:jetty-bom",
+    "org.glassfish.jersey:jersey-bom",
+    "org.jetbrains.kotlin:kotlin-bom",
+    "org.jetbrains.kotlin:kotlin-stdlib-common",
+    "org.jetbrains.kotlinx:kotlinx-coroutines-bom",
+    "org.jetbrains.kotlinx:kotlinx-coroutines-core"
+  ],
+  "version": "3"
+}
diff --git a/tests/integration/BUILD b/tests/integration/BUILD
index 7b917f2..21848b1 100644
--- a/tests/integration/BUILD
+++ b/tests/integration/BUILD
@@ -98,6 +98,35 @@
     file2 = ":forced-versions-deps-sorted.txt",
 )
 
+# The main jar and the test-fixtures jar of misk-feature are requested at
+# different versions with the "pinned" policy. Gradle selects one version per
+# module, so both must land on the version of the unclassified root.
+genquery(
+    name = "gradle-classifier-pinning-deps",
+    expression = "deps(@gradle_classifier_pinning//:com_squareup_misk_misk_feature_test_fixtures)",
+    opts = [
+        "--nohost_deps",
+        "--noimplicit_deps",
+    ],
+    scope = ["@gradle_classifier_pinning//:com_squareup_misk_misk_feature_test_fixtures"],
+)
+
+genrule(
+    name = "gradle-classifier-pinning-deps-sorted",
+    testonly = 1,
+    srcs = [":gradle-classifier-pinning-deps"],
+    outs = ["gradle-classifier-pinning-deps-sorted.txt"],
+    cmd = "cat $< | grep misk-feature | sed -e 's|^@@|@|g; s|\r||g' | sed -e 's|^@[^/]*[+~]|@|g; s|\r||g' | sort > $@",
+)
+
+# If a version is forced per artifact rather than per Gradle module, the main
+# jar is silently downgraded to the test-fixtures version `2026.06.30.120630-d342aab`
+diff_test(
+    name = "gradle-classifier-pinning-deps-test",
+    file1 = "gradle-classifier-pinning-deps.golden.unix",
+    file2 = ":gradle-classifier-pinning-deps-sorted.txt",
+)
+
 genquery(
     name = "root-wins-deps",
     expression = "deps(@root_wins//:io_netty_netty_buffer)",
diff --git a/tests/integration/gradle-classifier-pinning-deps.golden.unix b/tests/integration/gradle-classifier-pinning-deps.golden.unix
new file mode 100644
index 0000000..0856e4f
--- /dev/null
+++ b/tests/integration/gradle-classifier-pinning-deps.golden.unix
@@ -0,0 +1,4 @@
+@com_squareup_misk_misk_feature_2026_07_11_061457_fa37275//file:v1/com/squareup/misk/misk-feature/2026.07.11.061457-fa37275/misk-feature-2026.07.11.061457-fa37275.jar
+@com_squareup_misk_misk_feature_test_fixtures_2026_07_11_061457_fa37275//file:v1/com/squareup/misk/misk-feature/2026.07.11.061457-fa37275/misk-feature-2026.07.11.061457-fa37275-test-fixtures.jar
+@gradle_classifier_pinning//:com/squareup/misk/misk-feature/2026.07.11.061457-fa37275/misk-feature-2026.07.11.061457-fa37275-test-fixtures.jar
+@gradle_classifier_pinning//:com/squareup/misk/misk-feature/2026.07.11.061457-fa37275/misk-feature-2026.07.11.061457-fa37275.jar
diff --git a/tests/unit/version_conflict_policy_test.bzl b/tests/unit/version_conflict_policy_test.bzl
index 26b7100..b4210a9 100644
--- a/tests/unit/version_conflict_policy_test.bzl
+++ b/tests/unit/version_conflict_policy_test.bzl
@@ -40,9 +40,100 @@
 
 other_policies_leave_root_artifacts_unchanged_test = unittest.make(_other_policies_leave_root_artifacts_unchanged_impl)
 
+def _pinned_policy_forces_one_version_per_gradle_module_impl(ctx):
+    env = unittest.begin(ctx)
+
+    fixtures = unpack_coordinates("com.example:lib:jar:test-fixtures:1.0")
+    main = unpack_coordinates("com.example:lib:2.0")
+    managed = unpack_coordinates("com.example:managed-by-bom")
+
+    artifacts = apply_root_version_conflict_policy(
+        [fixtures, main, managed],
+        "gradle",
+        "pinned",
+    )
+
+    # Gradle selects a single version per group:artifact module, ignoring
+    # classifiers, so only the unclassified root may force the module version.
+    asserts.false(env, getattr(artifacts[0], "force_version", False))
+    asserts.true(env, getattr(artifacts[1], "force_version", False))
+    asserts.false(env, hasattr(artifacts[2], "force_version"))
+
+    return unittest.end(env)
+
+pinned_policy_forces_one_version_per_gradle_module_test = unittest.make(_pinned_policy_forces_one_version_per_gradle_module_impl)
+
+def _pinned_policy_prefers_unclassified_gradle_root_over_newer_classified_impl(ctx):
+    env = unittest.begin(ctx)
+
+    newer_fixtures = unpack_coordinates("com.example:lib:jar:test-fixtures:2.0")
+    older_main = unpack_coordinates("com.example:lib:1.0")
+
+    artifacts = apply_root_version_conflict_policy(
+        [newer_fixtures, older_main],
+        "gradle",
+        "pinned",
+    )
+
+    asserts.false(env, getattr(artifacts[0], "force_version", False))
+    asserts.true(env, getattr(artifacts[1], "force_version", False))
+
+    return unittest.end(env)
+
+pinned_policy_prefers_unclassified_gradle_root_over_newer_classified_test = unittest.make(_pinned_policy_prefers_unclassified_gradle_root_over_newer_classified_impl)
+
+def _pinned_policy_pins_classifier_only_gradle_root_impl(ctx):
+    env = unittest.begin(ctx)
+
+    fixtures = unpack_coordinates("com.example:lib:jar:test-fixtures:1.0")
+
+    artifacts = apply_root_version_conflict_policy([fixtures], "gradle", "pinned")
+
+    asserts.true(env, getattr(artifacts[0], "force_version", False))
+
+    return unittest.end(env)
+
+pinned_policy_pins_classifier_only_gradle_root_test = unittest.make(_pinned_policy_pins_classifier_only_gradle_root_impl)
+
+def _pinned_policy_forces_highest_version_across_classified_only_gradle_roots_impl(ctx):
+    env = unittest.begin(ctx)
+
+    older = unpack_coordinates("com.example:lib:jar:sources:1.0")
+    newer = unpack_coordinates("com.example:lib:jar:test-fixtures:2.0")
+
+    artifacts = apply_root_version_conflict_policy([older, newer], "gradle", "pinned")
+
+    asserts.false(env, getattr(artifacts[0], "force_version", False))
+    asserts.true(env, getattr(artifacts[1], "force_version", False))
+
+    return unittest.end(env)
+
+pinned_policy_forces_highest_version_across_classified_only_gradle_roots_test = unittest.make(_pinned_policy_forces_highest_version_across_classified_only_gradle_roots_impl)
+
+def _pinned_policy_forces_each_maven_root_independently_impl(ctx):
+    env = unittest.begin(ctx)
+
+    main = unpack_coordinates("com.example:lib:2.0")
+    fixtures = unpack_coordinates("com.example:lib:jar:test-fixtures:1.0")
+
+    artifacts = apply_root_version_conflict_policy([main, fixtures], "maven", "pinned")
+
+    # Maven mediates each classified form independently, so both stay forced.
+    asserts.true(env, artifacts[0].force_version)
+    asserts.true(env, artifacts[1].force_version)
+
+    return unittest.end(env)
+
+pinned_policy_forces_each_maven_root_independently_test = unittest.make(_pinned_policy_forces_each_maven_root_independently_impl)
+
 def version_conflict_policy_test_suite():
     unittest.suite(
         "version_conflict_policy_tests",
         partial.make(pinned_policy_forces_versioned_root_artifacts_test, size = "small"),
         partial.make(other_policies_leave_root_artifacts_unchanged_test, size = "small"),
+        partial.make(pinned_policy_forces_one_version_per_gradle_module_test, size = "small"),
+        partial.make(pinned_policy_prefers_unclassified_gradle_root_over_newer_classified_test, size = "small"),
+        partial.make(pinned_policy_pins_classifier_only_gradle_root_test, size = "small"),
+        partial.make(pinned_policy_forces_highest_version_across_classified_only_gradle_roots_test, size = "small"),
+        partial.make(pinned_policy_forces_each_maven_root_independently_test, size = "small"),
     )