Move rewinding-related classes to a `rewinding` package and make some related cleanups.

PiperOrigin-RevId: 440414212
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 3a22a1b..a748ce7 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -345,6 +345,7 @@
         "//src/main/java/com/google/devtools/build/lib/skyframe:top_level_aspects_value",
         "//src/main/java/com/google/devtools/build/lib/skyframe:workspace_info",
         "//src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2:actiongraph_v2",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/rewinding",
         "//src/main/java/com/google/devtools/build/lib/unix",
         "//src/main/java/com/google/devtools/build/lib/util",
         "//src/main/java/com/google/devtools/build/lib/util:TestType",
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CriticalPathComputer.java b/src/main/java/com/google/devtools/build/lib/runtime/CriticalPathComputer.java
index a322f12..3491b33 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/CriticalPathComputer.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/CriticalPathComputer.java
@@ -27,7 +27,6 @@
 import com.google.devtools.build.lib.actions.ActionCompletionEvent;
 import com.google.devtools.build.lib.actions.ActionKeyContext;
 import com.google.devtools.build.lib.actions.ActionMiddlemanEvent;
-import com.google.devtools.build.lib.actions.ActionRewoundEvent;
 import com.google.devtools.build.lib.actions.ActionStartedEvent;
 import com.google.devtools.build.lib.actions.Actions;
 import com.google.devtools.build.lib.actions.AggregatedSpawnMetrics;
@@ -38,6 +37,7 @@
 import com.google.devtools.build.lib.actions.SpawnMetrics;
 import com.google.devtools.build.lib.actions.SpawnResult;
 import com.google.devtools.build.lib.clock.Clock;
+import com.google.devtools.build.lib.skyframe.rewinding.ActionRewoundEvent;
 import java.time.Duration;
 import java.util.Comparator;
 import java.util.List;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
index 957a74a..b1bf5c0 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
@@ -43,7 +43,6 @@
 import com.google.devtools.build.lib.actions.ActionInputMap;
 import com.google.devtools.build.lib.actions.ActionInputMapSink;
 import com.google.devtools.build.lib.actions.ActionLookupData;
-import com.google.devtools.build.lib.actions.ActionRewoundEvent;
 import com.google.devtools.build.lib.actions.Actions;
 import com.google.devtools.build.lib.actions.AlreadyReportedActionExecutionException;
 import com.google.devtools.build.lib.actions.Artifact;
@@ -80,11 +79,13 @@
 import com.google.devtools.build.lib.server.FailureDetails.Execution;
 import com.google.devtools.build.lib.server.FailureDetails.Execution.Code;
 import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
-import com.google.devtools.build.lib.skyframe.ActionRewindStrategy.RewindPlan;
 import com.google.devtools.build.lib.skyframe.ArtifactFunction.MissingArtifactValue;
 import com.google.devtools.build.lib.skyframe.ArtifactFunction.SourceArtifactException;
 import com.google.devtools.build.lib.skyframe.ArtifactNestedSetFunction.ArtifactNestedSetEvalException;
 import com.google.devtools.build.lib.skyframe.SkyframeActionExecutor.ActionPostprocessing;
+import com.google.devtools.build.lib.skyframe.rewinding.ActionRewindStrategy;
+import com.google.devtools.build.lib.skyframe.rewinding.ActionRewindStrategy.RewindPlan;
+import com.google.devtools.build.lib.skyframe.rewinding.ActionRewoundEvent;
 import com.google.devtools.build.lib.util.DetailedExitCode;
 import com.google.devtools.build.lib.util.DetailedExitCode.DetailedExitCodeComparator;
 import com.google.devtools.build.lib.util.Pair;
@@ -136,7 +137,7 @@
  * in-flight primary shared action's execution, this function can abort after declaring an external
  * dep on the execution's completion future.
  */
-public class ActionExecutionFunction implements SkyFunction {
+public final class ActionExecutionFunction implements SkyFunction {
 
   private final ActionRewindStrategy actionRewindStrategy = new ActionRewindStrategy();
   private final SkyframeActionExecutor skyframeActionExecutor;
@@ -1099,7 +1100,7 @@
       return Predicates.alwaysTrue();
     }
 
-    return new Predicate<Artifact>() {
+    return new Predicate<>() {
       // Lazily flatten the NestedSet in case the predicate is never needed. It's only used in the
       // exceptional case of a missing artifact.
       private ImmutableSet<Artifact> mandatoryInputs = null;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionUtils.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionUtils.java
index 3e9897b..aa0f702 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionUtils.java
@@ -23,7 +23,7 @@
 public final class ActionUtils {
 
   @Nullable
-  static Action getActionForLookupData(Environment env, ActionLookupData actionLookupData)
+  public static Action getActionForLookupData(Environment env, ActionLookupData actionLookupData)
       throws InterruptedException {
     ActionLookupValue actionLookupValue =
         ArtifactFunction.getActionLookupValue(actionLookupData.getActionLookupKey(), env);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
index d6350cc..7f2b07f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
@@ -29,7 +29,6 @@
 import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
 import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
 import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ArtifactOwner;
 import com.google.devtools.build.lib.actions.FileArtifactValue;
 import com.google.devtools.build.lib.actions.FileValue;
 import com.google.devtools.build.lib.actions.FilesetTraversalParams.DirectTraversalRoot;
@@ -40,6 +39,7 @@
 import com.google.devtools.build.lib.server.FailureDetails.Execution;
 import com.google.devtools.build.lib.server.FailureDetails.Execution.Code;
 import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
+import com.google.devtools.build.lib.skyframe.ActionTemplateExpansionValue.ActionTemplateExpansionKey;
 import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalFunction.RecursiveFilesystemTraversalException;
 import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFile;
 import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest;
@@ -68,7 +68,8 @@
  * directly from the corresponding {@link ActionExecutionValue}. This SkyFunction is therefore only
  * usable for source, middleman, and tree artifacts.
  */
-class ArtifactFunction implements SkyFunction {
+public final class ArtifactFunction implements SkyFunction {
+
   private final Supplier<Boolean> mkdirForTreeArtifacts;
   private final MetadataConsumerForMetrics sourceArtifactsSeen;
   private final XattrProvider xattrProvider;
@@ -184,21 +185,17 @@
 
   private static TreeArtifactValue createTreeArtifactValueFromActionKey(
       ArtifactDependencies artifactDependencies, Environment env) throws InterruptedException {
-    // Request the list of expanded actions from the ActionTemplate.
-    ActionTemplateExpansion actionTemplateExpansion =
-        artifactDependencies.getActionTemplateExpansion(env);
-    if (actionTemplateExpansion == null) {
-      // The expanded actions are not yet available.
-      return null;
-    }
+    // Request the list of expanded action keys from the ActionTemplate.
     ImmutableList<ActionLookupData> expandedActionExecutionKeys =
-        actionTemplateExpansion.getExpandedActionExecutionKeys();
+        artifactDependencies.getActionTemplateExpansionKeys(env);
+    if (expandedActionExecutionKeys == null) {
+      return null; // The expanded actions are not yet available.
+    }
 
-    SkyframeIterableResult expandedActionValueMap =
+    SkyframeIterableResult expandedActionValues =
         env.getOrderedValuesAndExceptions(expandedActionExecutionKeys);
     if (env.valuesMissing()) {
-      // The execution values of the expanded actions are not yet all available.
-      return null;
+      return null; // The execution values of the expanded actions are not yet all available.
     }
 
     // Aggregate the metadata for individual TreeFileArtifacts into a TreeArtifactValue for the
@@ -210,7 +207,7 @@
     for (ActionLookupData actionKey : expandedActionExecutionKeys) {
       boolean sawTreeChild = false;
       ActionExecutionValue actionExecutionValue =
-          (ActionExecutionValue) expandedActionValueMap.next();
+          (ActionExecutionValue) expandedActionValues.next();
       if (actionExecutionValue == null) {
         return null;
       }
@@ -416,15 +413,8 @@
     return Label.print(((Artifact) skyKey).getOwner());
   }
 
-  static ActionLookupKey getActionLookupKey(Artifact artifact) {
-    ArtifactOwner artifactOwner = artifact.getArtifactOwner();
-    Preconditions.checkState(
-        artifactOwner instanceof ActionLookupKey, "%s %s", artifact, artifactOwner);
-    return (ActionLookupKey) artifactOwner;
-  }
-
   @Nullable
-  static ActionLookupValue getActionLookupValue(
+  public static ActionLookupValue getActionLookupValue(
       ActionLookupKey actionLookupKey, SkyFunction.Environment env) throws InterruptedException {
     ActionLookupValue value = (ActionLookupValue) env.getValue(actionLookupKey);
     if (value == null) {
@@ -484,7 +474,7 @@
   /** Describes dependencies of derived artifacts. */
   // TODO(b/19539699): extend this to comprehensively support all special artifact types (e.g.
   // middleman, etc).
-  static class ArtifactDependencies {
+  public static final class ArtifactDependencies {
     private final DerivedArtifact artifact;
     private final ActionLookupValue actionLookupValue;
 
@@ -498,7 +488,7 @@
      * {@code null} if any dependencies are not yet ready.
      */
     @Nullable
-    static ArtifactDependencies discoverDependencies(
+    public static ArtifactDependencies discoverDependencies(
         Artifact.DerivedArtifact derivedArtifact, SkyFunction.Environment env)
         throws InterruptedException {
 
@@ -512,10 +502,11 @@
       return new ArtifactDependencies(derivedArtifact, actionLookupValue);
     }
 
-    boolean isTemplateActionForTreeArtifact() {
+    public boolean isTemplateActionForTreeArtifact() {
       return maybeGetTemplateActionForTreeArtifact() != null;
     }
 
+    @Nullable
     ActionTemplate<?> maybeGetTemplateActionForTreeArtifact() {
       if (!artifact.isTreeArtifact()) {
         return null;
@@ -526,22 +517,29 @@
     }
 
     /**
-     * Returns action template expansion information or {@code null} if that information is
-     * unavailable.
+     * Returns action template expansion keys or {@code null} if that information is unavailable.
      *
-     * <p>Must not be called if {@code !isTemplateActionForTreeArtifact()}.
+     * <p>Must only be called if {@link #isTemplateActionForTreeArtifact} returns {@code true}.
      */
     @Nullable
-    ActionTemplateExpansion getActionTemplateExpansion(SkyFunction.Environment env)
-        throws InterruptedException {
+    public ImmutableList<ActionLookupData> getActionTemplateExpansionKeys(
+        SkyFunction.Environment env) throws InterruptedException {
       Preconditions.checkState(
           isTemplateActionForTreeArtifact(), "Action is unexpectedly non-template: %s", this);
-      ActionTemplateExpansionValue.ActionTemplateExpansionKey key =
+      ActionTemplateExpansionKey key =
           ActionTemplateExpansionValue.key(
               artifact.getArtifactOwner(), artifact.getGeneratingActionKey().getActionIndex());
-      // This call may throw an ActionExecutionFunction that bubbles up.
       ActionTemplateExpansionValue value = (ActionTemplateExpansionValue) env.getValue(key);
-      return value == null ? null : new ActionTemplateExpansion(value);
+      if (value == null) {
+        return null;
+      }
+      ImmutableList.Builder<ActionLookupData> expandedActionExecutionKeys =
+          ImmutableList.builderWithExpectedSize(value.getNumActions());
+      for (ActionAnalysisMetadata action : value.getActions()) {
+        expandedActionExecutionKeys.add(
+            ((DerivedArtifact) action.getPrimaryOutput()).getGeneratingActionKey());
+      }
+      return expandedActionExecutionKeys.build();
     }
 
     @Override
@@ -554,29 +552,6 @@
     }
   }
 
-  static class ActionTemplateExpansion {
-    private final ActionTemplateExpansionValue value;
-
-    private ActionTemplateExpansion(ActionTemplateExpansionValue value) {
-      this.value = value;
-    }
-
-    ActionTemplateExpansionValue getValue() {
-      return value;
-    }
-
-    ImmutableList<ActionLookupData> getExpandedActionExecutionKeys() {
-      int numActions = value.getNumActions();
-      ImmutableList.Builder<ActionLookupData> expandedActionExecutionKeys =
-          ImmutableList.builderWithExpectedSize(numActions);
-      for (ActionAnalysisMetadata action : value.getActions()) {
-        expandedActionExecutionKeys.add(
-            ((DerivedArtifact) action.getPrimaryOutput()).getGeneratingActionKey());
-      }
-      return expandedActionExecutionKeys.build();
-    }
-  }
-
   static final class SourceArtifactException extends Exception implements DetailedException {
     private final DetailedExitCode detailedExitCode;
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
index 9bcaa0e..4ff1187 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
@@ -8,6 +8,7 @@
         "//src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2:srcs",
         "//src/main/java/com/google/devtools/build/lib/skyframe/packages:srcs",
         "//src/main/java/com/google/devtools/build/lib/skyframe/proto:srcs",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/rewinding:srcs",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization:srcs",
     ],
     visibility = ["//src:__subpackages__"],
@@ -88,7 +89,6 @@
         ":action_input_map_helper",
         ":action_lookup_conflict_finding_value",
         ":action_metadata_handler",
-        ":action_rewind_strategy",
         ":action_template_expansion_function",
         ":action_template_expansion_value",
         ":action_utils",
@@ -312,6 +312,7 @@
         "//src/main/java/com/google/devtools/build/lib/rules:repository/resolved_file_value",
         "//src/main/java/com/google/devtools/build/lib/rules:repository/workspace_file_helper",
         "//src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2:actiongraph_v2",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/rewinding",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
         "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec:serialization-constant",
         "//src/main/java/com/google/devtools/build/lib/util",
@@ -485,35 +486,6 @@
 )
 
 java_library(
-    name = "action_rewind_strategy",
-    srcs = [
-        "ActionRewindStrategy.java",
-        "ActionRewindingStats.java",
-    ],
-    deps = [
-        ":action_utils",
-        ":artifact_function",
-        ":artifact_nested_set_key",
-        ":skyframe_aware_action",
-        "//src/main/java/com/google/devtools/build/lib/actions",
-        "//src/main/java/com/google/devtools/build/lib/actions:action_lookup_data",
-        "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
-        "//src/main/java/com/google/devtools/build/lib/bugreport",
-        "//src/main/java/com/google/devtools/build/lib/collect/nestedset",
-        "//src/main/java/com/google/devtools/build/lib/events",
-        "//src/main/java/com/google/devtools/build/lib/skyframe/proto:action_rewind_event_java_proto",
-        "//src/main/java/com/google/devtools/build/lib/util:detailed_exit_code",
-        "//src/main/java/com/google/devtools/build/skyframe",
-        "//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
-        "//src/main/protobuf:failure_details_java_proto",
-        "//third_party:auto_value",
-        "//third_party:flogger",
-        "//third_party:guava",
-        "//third_party:jsr305",
-    ],
-)
-
-java_library(
     name = "action_template_expansion_function",
     srcs = ["ActionTemplateExpansionFunction.java"],
     deps = [
@@ -641,7 +613,6 @@
         "//src/main/java/com/google/devtools/build/lib/actions",
         "//src/main/java/com/google/devtools/build/lib/actions:action_lookup_data",
         "//src/main/java/com/google/devtools/build/lib/actions:action_lookup_key",
-        "//src/main/java/com/google/devtools/build/lib/actions:artifact_owner",
         "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
         "//src/main/java/com/google/devtools/build/lib/actions:file_metadata",
         "//src/main/java/com/google/devtools/build/lib/actions:middleman_type",
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionRewindStrategy.java b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewindStrategy.java
similarity index 94%
rename from src/main/java/com/google/devtools/build/lib/skyframe/ActionRewindStrategy.java
rename to src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewindStrategy.java
index 5539f97..b25bd25 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionRewindStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewindStrategy.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.devtools.build.lib.skyframe;
+package com.google.devtools.build.lib.skyframe.rewinding;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -23,7 +23,6 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Collections2;
 import com.google.common.collect.ConcurrentHashMultiset;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -53,6 +52,10 @@
 import com.google.devtools.build.lib.server.FailureDetails.ActionRewinding;
 import com.google.devtools.build.lib.server.FailureDetails.ActionRewinding.Code;
 import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
+import com.google.devtools.build.lib.skyframe.ActionUtils;
+import com.google.devtools.build.lib.skyframe.ArtifactFunction.ArtifactDependencies;
+import com.google.devtools.build.lib.skyframe.ArtifactNestedSetKey;
+import com.google.devtools.build.lib.skyframe.SkyframeAwareAction;
 import com.google.devtools.build.lib.skyframe.proto.ActionRewind.ActionRewindEvent;
 import com.google.devtools.build.lib.util.DetailedExitCode;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
@@ -73,7 +76,8 @@
  * actions, this finds the actions which generated them and the set of Skyframe nodes which must be
  * restarted in order to recreate the lost inputs.
  */
-public class ActionRewindStrategy {
+public final class ActionRewindStrategy {
+
   private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
   @VisibleForTesting public static final int MAX_REPEATED_LOST_INPUTS = 20;
   @VisibleForTesting public static final int MAX_ACTION_REWIND_EVENTS = 5;
@@ -91,8 +95,9 @@
    * <ol>
    *   <li>the Skyframe nodes to restart to recreate the lost inputs specified by {@code
    *       lostInputsException}
-   *   <li>the actions whose execution state (in {@link SkyframeActionExecutor}) must be reset
-   *       (aside from failedAction, which the caller already knows must be reset)
+   *   <li>the actions whose execution state (in {@link
+   *       com.google.devtools.build.lib.skyframe.SkyframeActionExecutor}) must be reset (aside from
+   *       failedAction, which the caller already knows must be reset)
    * </ol>
    *
    * <p>Note that all Skyframe nodes between the currently executing (failed) action's node and the
@@ -103,7 +108,7 @@
    * @throws ActionExecutionException if any lost inputs have been seen by this action as lost
    *     before, or if any lost inputs are not the outputs of previously executed actions
    */
-  RewindPlan getRewindPlan(
+  public RewindPlan getRewindPlan(
       Action failedAction,
       ActionLookupData actionLookupData,
       Set<SkyKey> failedActionDeps,
@@ -136,7 +141,7 @@
             inputDepOwners,
             ImmutableSet.<SkyKey>builder()
                 .addAll(failedActionDeps)
-                .addAll(Collections2.transform(nestedSetKeys.keySet(), Artifact::key))
+                .addAll(Artifact.keys(nestedSetKeys.keySet()))
                 .build(),
             failedAction,
             lostInputsException);
@@ -182,7 +187,7 @@
    * Log the top N action rewind events and clear the history of failed actions' lost inputs and
    * rewind plans.
    */
-  void reset(ExtendedEventHandler eventHandler) {
+  public void reset(ExtendedEventHandler eventHandler) {
     ImmutableList<ActionRewindEvent> topActionRewindEvents =
         rewindPlansStats.stream()
             .collect(
@@ -535,8 +540,8 @@
     if (!lostInput.isTreeArtifact()) {
       return ImmutableSet.of(lostInput.getGeneratingActionKey());
     }
-    ArtifactFunction.ArtifactDependencies artifactDependencies =
-        ArtifactFunction.ArtifactDependencies.discoverDependencies(lostInput, env);
+    ArtifactDependencies artifactDependencies =
+        ArtifactDependencies.discoverDependencies(lostInput, env);
     if (artifactDependencies == null) {
       return null;
     }
@@ -544,14 +549,15 @@
     if (!artifactDependencies.isTemplateActionForTreeArtifact()) {
       return ImmutableSet.of(lostInput.getGeneratingActionKey());
     }
-    ArtifactFunction.ActionTemplateExpansion actionTemplateExpansion =
-        artifactDependencies.getActionTemplateExpansion(env);
-    if (actionTemplateExpansion == null) {
-      return null;
-    }
+
     // This ignores the ActionTemplateExpansionKey dependency of the template artifact because we
     // expect to never need to rewind that.
-    return ImmutableSet.copyOf(actionTemplateExpansion.getExpandedActionExecutionKeys());
+    ImmutableList<ActionLookupData> actionTemplateExpansionKeys =
+        artifactDependencies.getActionTemplateExpansionKeys(env);
+    if (actionTemplateExpansionKeys == null) {
+      return null;
+    }
+    return ImmutableSet.copyOf(actionTemplateExpansionKeys);
   }
 
   private static void assertSkyframeAwareRewindingGraph(
@@ -614,20 +620,24 @@
                 .build()));
   }
 
-  static class RewindPlan {
+  /**
+   * Specifies the Skyframe nodes and actions that need to be restarted in order to recreate lost
+   * inputs.
+   */
+  public static final class RewindPlan {
     private final Restart nodesToRestart;
     private final ImmutableList<Action> additionalActionsToRestart;
 
-    RewindPlan(Restart nodesToRestart, ImmutableList<Action> additionalActionsToRestart) {
+    private RewindPlan(Restart nodesToRestart, ImmutableList<Action> additionalActionsToRestart) {
       this.nodesToRestart = nodesToRestart;
       this.additionalActionsToRestart = additionalActionsToRestart;
     }
 
-    Restart getNodesToRestart() {
+    public Restart getNodesToRestart() {
       return nodesToRestart;
     }
 
-    ImmutableList<Action> getAdditionalActionsToRestart() {
+    public ImmutableList<Action> getAdditionalActionsToRestart() {
       return additionalActionsToRestart;
     }
   }
@@ -701,9 +711,10 @@
    * <p>More formally, a key-value pair {@code (Artifact k, ArtifactNestedSetKey v)} is present in
    * the returned map iff {@code deps.contains(v) && v.getSet().toList().contains(k)}.
    *
-   * <p>When {@link ActionExecutionFunction} requests input deps, it unwraps a single layer of
-   * {@linkplain Action#getInputs the action's inputs}, thus requesting an {@link
-   * ArtifactNestedSetKey} for each of {@code action.getInputs().getNonLeaves()}.
+   * <p>When {@link com.google.devtools.build.lib.skyframe.ActionExecutionFunction} requests input
+   * deps, it unwraps a single layer of {@linkplain Action#getInputs the action's inputs}, thus
+   * requesting an {@link ArtifactNestedSetKey} for each of {@code
+   * action.getInputs().getNonLeaves()}.
    */
   private static Multimap<Artifact, ArtifactNestedSetKey> expandNestedSetKeys(Set<SkyKey> deps) {
     Multimap<Artifact, ArtifactNestedSetKey> map =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionRewindingStats.java b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewindingStats.java
similarity index 85%
rename from src/main/java/com/google/devtools/build/lib/skyframe/ActionRewindingStats.java
rename to src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewindingStats.java
index 2d306eb..5b0f1cf 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionRewindingStats.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewindingStats.java
@@ -12,26 +12,28 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.devtools.build.lib.skyframe;
+package com.google.devtools.build.lib.skyframe.rewinding;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.ImmutableList.toImmutableList;
 
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
-import com.google.devtools.build.lib.skyframe.ActionRewindStrategy.RewindPlanStats;
 import com.google.devtools.build.lib.skyframe.proto.ActionRewind.ActionDescription;
 import com.google.devtools.build.lib.skyframe.proto.ActionRewind.ActionRewindEvent;
 import com.google.devtools.build.lib.skyframe.proto.ActionRewind.LostInput;
+import com.google.devtools.build.lib.skyframe.rewinding.ActionRewindStrategy.RewindPlanStats;
 
 /** Event that encapsulates data about action rewinding during a build. */
-public class ActionRewindingStats implements ExtendedEventHandler.Postable {
+public final class ActionRewindingStats implements ExtendedEventHandler.Postable {
+
   private final int lostInputsCount;
   private final ImmutableList<ActionRewindEvent> actionRewindEvents;
 
   ActionRewindingStats(int lostInputsCount, ImmutableList<ActionRewindEvent> actionRewindEvents) {
     this.lostInputsCount = lostInputsCount;
-    this.actionRewindEvents = actionRewindEvents;
+    this.actionRewindEvents = checkNotNull(actionRewindEvents);
   }
 
   public int lostInputsCount() {
@@ -42,7 +44,7 @@
     return actionRewindEvents;
   }
 
-  public static ActionRewindEvent toActionRewindEventProto(RewindPlanStats rewindPlanStats) {
+  static ActionRewindEvent toActionRewindEventProto(RewindPlanStats rewindPlanStats) {
     ActionOwner failedActionOwner = rewindPlanStats.failedAction().getOwner();
     return ActionRewindEvent.newBuilder()
         .setActionDescription(
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionRewoundEvent.java b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewoundEvent.java
similarity index 86%
rename from src/main/java/com/google/devtools/build/lib/actions/ActionRewoundEvent.java
rename to src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewoundEvent.java
index ee5f8b9..76c9af1 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionRewoundEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/ActionRewoundEvent.java
@@ -11,16 +11,16 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-package com.google.devtools.build.lib.actions;
+package com.google.devtools.build.lib.skyframe.rewinding;
 
+import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.events.ExtendedEventHandler.ProgressLike;
 
 /**
  * This event is fired during the build for an action that failed because of lost inputs, and that
- * will try to recover through rewinding (see {@link
- * com.google.devtools.build.lib.skyframe.ActionRewindStrategy}).
+ * will try to recover through rewinding (see {@link ActionRewindStrategy}).
  */
-public class ActionRewoundEvent implements ProgressLike {
+public final class ActionRewoundEvent implements ProgressLike {
 
   private final long relativeActionStartTime;
   private final Action failedRewoundAction;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/BUILD
new file mode 100644
index 0000000..cb08b65
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/BUILD
@@ -0,0 +1,41 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+package(default_visibility = ["//src:__subpackages__"])
+
+licenses(["notice"])
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]),
+    visibility = ["//src:__subpackages__"],
+)
+
+java_library(
+    name = "rewinding",
+    srcs = [
+        "ActionRewindStrategy.java",
+        "ActionRewindingStats.java",
+        "ActionRewoundEvent.java",
+    ],
+    deps = [
+        "//src/main/java/com/google/devtools/build/lib/actions",
+        "//src/main/java/com/google/devtools/build/lib/actions:action_lookup_data",
+        "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
+        "//src/main/java/com/google/devtools/build/lib/bugreport",
+        "//src/main/java/com/google/devtools/build/lib/collect/nestedset",
+        "//src/main/java/com/google/devtools/build/lib/events",
+        "//src/main/java/com/google/devtools/build/lib/skyframe:action_utils",
+        "//src/main/java/com/google/devtools/build/lib/skyframe:artifact_function",
+        "//src/main/java/com/google/devtools/build/lib/skyframe:artifact_nested_set_key",
+        "//src/main/java/com/google/devtools/build/lib/skyframe:skyframe_aware_action",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/proto:action_rewind_event_java_proto",
+        "//src/main/java/com/google/devtools/build/lib/util:detailed_exit_code",
+        "//src/main/java/com/google/devtools/build/skyframe",
+        "//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
+        "//src/main/protobuf:failure_details_java_proto",
+        "//third_party:auto_value",
+        "//third_party:flogger",
+        "//third_party:guava",
+        "//third_party:jsr305",
+    ],
+)