Split ActionMetadata into ActionAnalysisMetadata and ActionExecutionMetadata.
Except in action execution logic (ActionExecutionFunction, SkyframeActionExecutor, etc.), switch Action interface references to either ActionAnalysisMetadata if possible or ActionExecutionMetadata.

--
MOS_MIGRATED_REVID=120723431
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
index 968c721..00f918a 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
@@ -395,7 +395,7 @@
   }
 
   @Override
-  public boolean shouldReportPathPrefixConflict(Action action) {
+  public boolean shouldReportPathPrefixConflict(ActionAnalysisMetadata action) {
     return this != action;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Action.java b/src/main/java/com/google/devtools/build/lib/actions/Action.java
index 51514af..85d22ef 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Action.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Action.java
@@ -77,7 +77,7 @@
  * known set of fields is covered, not that all fields are covered), so carefully check all changes
  * to action subclasses.
  */
-public interface Action extends ActionMetadata, Describable {
+public interface Action extends ActionExecutionMetadata, Describable {
 
   /**
    * Prepares for executing this action; called by the Builder prior to
@@ -192,14 +192,6 @@
   @Nullable ResourceSet estimateResourceConsumption(Executor executor);
 
   /**
-   * @return true iff path prefix conflict (conflict where two actions generate
-   *         two output artifacts with one of the artifact's path being the
-   *         prefix for another) between this action and another action should
-   *         be reported.
-   */
-  boolean shouldReportPathPrefixConflict(Action action);
-
-  /**
    * Returns true if the output should bypass output filtering. This is used for test actions.
    */
   boolean showsOutputUnconditionally();
@@ -218,38 +210,4 @@
    * a different thread than the one this action is executed on.
    */
   ExtraActionInfo.Builder getExtraActionInfo();
-
-  /**
-   * Returns the action type. Must not be {@code null}.
-   */
-  MiddlemanType getActionType();
-
-  /**
-   * The action type.
-   */
-  public enum MiddlemanType {
-
-    /** A normal action. */
-    NORMAL,
-
-    /** A normal middleman, which just encapsulates a list of artifacts. */
-    AGGREGATING_MIDDLEMAN,
-
-    /**
-     * A middleman that enforces action ordering, is not validated by the dependency checker, but
-     * allows errors to be propagated.
-     */
-    ERROR_PROPAGATING_MIDDLEMAN,
-
-    /**
-     * A runfiles middleman, which is validated by the dependency checker, but is not expanded
-     * in blaze. Instead, the runfiles manifest is sent to remote execution client, which
-     * performs the expansion.
-     */
-    RUNFILES_MIDDLEMAN;
-
-    public boolean isMiddleman() {
-      return this != NORMAL;
-    }
-  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionMetadata.java b/src/main/java/com/google/devtools/build/lib/actions/ActionAnalysisMetadata.java
similarity index 64%
rename from src/main/java/com/google/devtools/build/lib/actions/ActionMetadata.java
rename to src/main/java/com/google/devtools/build/lib/actions/ActionAnalysisMetadata.java
index 08b501c..a3e73b3 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionMetadata.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionAnalysisMetadata.java
@@ -16,26 +16,11 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 
-import javax.annotation.Nullable;
-
 /**
- * Side-effect free query methods for information about an {@link Action}.
- *
- * <p>This method is intended for use in situations when the intention is to pass around information
- * about an action without allowing actual execution of the action.
- *
- * <p>The split between {@link Action} and {@link ActionMetadata} is somewhat arbitrary, other than
- * that all methods with side effects must belong to the former.
+ * An Analysis phase interface for an {@link Action} or Action-like object, containing only
+ * side-effect-free query methods for information needed during action analysis.
  */
-public interface ActionMetadata {
-  /**
-   * If this executable can supply verbose information, returns a string that can be used as a
-   * progress message while this executable is running. A return value of {@code null} indicates no
-   * message should be reported.
-   */
-  @Nullable
-  String getProgressMessage();
-
+public interface ActionAnalysisMetadata {
   /**
    * Returns the owner of this executable if this executable can supply verbose information. This is
    * typically the rule that constructed it; see ActionOwner class comment for details. Returns
@@ -158,63 +143,40 @@
   Iterable<Artifact> getMandatoryInputs();
 
   /**
-   * <p>Returns a string encoding all of the significant behaviour of this
-   * Action that might affect the output.  The general contract of
-   * <code>getKey</code> is this: if the work to be performed by the
-   * execution of this action changes, the key must change. </p>
-   *
-   * <p>As a corollary, the build system is free to omit the execution of an
-   * Action <code>a1</code> if (a) at some time in the past, it has already
-   * executed an Action <code>a0</code> with the same key as
-   * <code>a1</code>, and (b) the names and contents of the input files listed
-   * by <code>a1.getInputs()</code> are identical to the names and contents of
-   * the files listed by <code>a0.getInputs()</code>. </p>
-   *
-   * <p>Examples of changes that should affect the key are:
-   * <ul>
-   *  <li>Changes to the BUILD file that materially affect the rule which gave
-   *  rise to this Action.</li>
-   *
-   *  <li>Changes to the command-line options, environment, or other global
-   *  configuration resources which affect the behaviour of this kind of Action
-   *  (other than changes to the names of the input/output files, which are
-   *  handled externally).</li>
-   *
-   *  <li>An upgrade to the build tools which changes the program logic of this
-   *  kind of Action (typically this is achieved by incorporating a UUID into
-   *  the key, which is changed each time the program logic of this action
-   *  changes).</li>
-   *
-   * </ul></p>
+   * @return true iff path prefix conflict (conflict where two actions generate
+   *         two output artifacts with one of the artifact's path being the
+   *         prefix for another) between this action and another action should
+   *         be reported.
    */
-  String getKey();
+  boolean shouldReportPathPrefixConflict(ActionAnalysisMetadata action);
 
-  /**
-   * Returns a human-readable description of the inputs to {@link #getKey()}.
-   * Used in the output from '--explain', and in error messages for
-   * '--check_up_to_date' and '--check_tests_up_to_date'.
-   * May return null, meaning no extra information is available.
-   *
-   * <p>If the return value is non-null, for consistency it should be a multiline message of the
-   * form:
-   * <pre>
-   *   <var>Summary</var>
-   *     <var>Fieldname</var>: <var>value</var>
-   *     <var>Fieldname</var>: <var>value</var>
-   *     ...
-   * </pre>
-   * where each line after the first one is intended two spaces, and where any fields that might
-   * contain newlines or other funny characters are escaped using {@link
-   * com.google.devtools.build.lib.shell.ShellUtils#shellEscape}.
-   * For example:
-   * <pre>
-   *   Compiling foo.cc
-   *     Command: /usr/bin/gcc
-   *     Argument: '-c'
-   *     Argument: foo.cc
-   *     Argument: '-o'
-   *     Argument: foo.o
-   * </pre>
-   */
-  @Nullable String describeKey();
+  /** Returns the action type. Must not be {@code null}. */
+  MiddlemanType getActionType();
+
+  /** The action type. */
+  public enum MiddlemanType {
+
+    /** A normal action. */
+    NORMAL,
+
+    /** A normal middleman, which just encapsulates a list of artifacts. */
+    AGGREGATING_MIDDLEMAN,
+
+    /**
+     * A middleman that enforces action ordering, is not validated by the dependency checker, but
+     * allows errors to be propagated.
+     */
+    ERROR_PROPAGATING_MIDDLEMAN,
+
+    /**
+     * A runfiles middleman, which is validated by the dependency checker, but is not expanded
+     * in blaze. Instead, the runfiles manifest is sent to remote execution client, which
+     * performs the expansion.
+     */
+    RUNFILES_MIDDLEMAN;
+
+    public boolean isMiddleman() {
+      return this != NORMAL;
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
index 4fd06a9..4a97789 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
@@ -16,7 +16,7 @@
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.actions.Action.MiddlemanType;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
 import com.google.devtools.build.lib.actions.cache.ActionCache;
 import com.google.devtools.build.lib.actions.cache.ActionCache.Entry;
 import com.google.devtools.build.lib.actions.cache.Digest;
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionMetadata.java b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionMetadata.java
new file mode 100644
index 0000000..004a37a
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionMetadata.java
@@ -0,0 +1,94 @@
+// Copyright 2014 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// 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;
+
+import javax.annotation.Nullable;
+
+/**
+ * An interface for an {@link Action}, containing only side-effect-free query methods for
+ * information needed during both action analysis and execution.
+ *
+ * <p>The split between {@link Action} and {@link ActionExecutionMetadata} is somewhat arbitrary,
+ * other than that all methods with side effects must belong to the former.
+ */
+public interface ActionExecutionMetadata extends ActionAnalysisMetadata {
+  /**
+   * If this executable can supply verbose information, returns a string that can be used as a
+   * progress message while this executable is running. A return value of {@code null} indicates no
+   * message should be reported.
+   */
+  @Nullable
+  String getProgressMessage();
+
+  /**
+   * <p>Returns a string encoding all of the significant behaviour of this
+   * Action that might affect the output.  The general contract of
+   * <code>getKey</code> is this: if the work to be performed by the
+   * execution of this action changes, the key must change. </p>
+   *
+   * <p>As a corollary, the build system is free to omit the execution of an
+   * Action <code>a1</code> if (a) at some time in the past, it has already
+   * executed an Action <code>a0</code> with the same key as
+   * <code>a1</code>, and (b) the names and contents of the input files listed
+   * by <code>a1.getInputs()</code> are identical to the names and contents of
+   * the files listed by <code>a0.getInputs()</code>. </p>
+   *
+   * <p>Examples of changes that should affect the key are:
+   * <ul>
+   *  <li>Changes to the BUILD file that materially affect the rule which gave
+   *  rise to this Action.</li>
+   *
+   *  <li>Changes to the command-line options, environment, or other global
+   *  configuration resources which affect the behaviour of this kind of Action
+   *  (other than changes to the names of the input/output files, which are
+   *  handled externally).</li>
+   *
+   *  <li>An upgrade to the build tools which changes the program logic of this
+   *  kind of Action (typically this is achieved by incorporating a UUID into
+   *  the key, which is changed each time the program logic of this action
+   *  changes).</li>
+   *
+   * </ul></p>
+   */
+  String getKey();
+
+  /**
+   * Returns a human-readable description of the inputs to {@link #getKey()}.
+   * Used in the output from '--explain', and in error messages for
+   * '--check_up_to_date' and '--check_tests_up_to_date'.
+   * May return null, meaning no extra information is available.
+   *
+   * <p>If the return value is non-null, for consistency it should be a multiline message of the
+   * form:
+   * <pre>
+   *   <var>Summary</var>
+   *     <var>Fieldname</var>: <var>value</var>
+   *     <var>Fieldname</var>: <var>value</var>
+   *     ...
+   * </pre>
+   * where each line after the first one is intended two spaces, and where any fields that might
+   * contain newlines or other funny characters are escaped using {@link
+   * com.google.devtools.build.lib.shell.ShellUtils#shellEscape}.
+   * For example:
+   * <pre>
+   *   Compiling foo.cc
+   *     Command: /usr/bin/gcc
+   *     Argument: '-c'
+   *     Argument: foo.cc
+   *     Argument: '-o'
+   *     Argument: foo.o
+   * </pre>
+   */
+  @Nullable String describeKey();
+}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java
index 7a2a410..fd56653 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java
@@ -57,7 +57,7 @@
    * The status of each action "in flight", i.e. whose ExecuteBuildAction.call() method is active.
    * Used for implementing the "still waiting" message.
    */
-  private final Map<ActionMetadata, Pair<String, Long>> actionStatus =
+  private final Map<ActionExecutionMetadata, Pair<String, Long>> actionStatus =
       new ConcurrentHashMap<>(100);
 
   public static ActionExecutionStatusReporter create(EventHandler eventHandler) {
@@ -98,7 +98,7 @@
     }
   }
 
-  private void setStatus(ActionMetadata action, String message) {
+  private void setStatus(ActionExecutionMetadata action, String message) {
     actionStatus.put(action, Pair.of(message, clock.nanoTime()));
   }
 
@@ -116,14 +116,14 @@
     updateStatus(ActionStatusMessage.preparingStrategy(action));
   }
 
-  public void setRunningFromBuildData(ActionMetadata action) {
+  public void setRunningFromBuildData(ActionExecutionMetadata action) {
     updateStatus(ActionStatusMessage.runningStrategy(action, "unknown"));
   }
 
   @Subscribe
   public void updateStatus(ActionStatusMessage statusMsg) {
     String message = statusMsg.getMessage();
-    ActionMetadata action = statusMsg.getActionMetadata();
+    ActionExecutionMetadata action = statusMsg.getActionMetadata();
     setStatus(action, message);
   }
 
@@ -132,9 +132,10 @@
   }
 
   private static void appendGroupStatus(StringBuilder buffer,
-      Map<ActionMetadata, Pair<String, Long>> statusMap,  String status, long currentTime) {
-    List<Pair<Long, ActionMetadata>> actions = new ArrayList<>();
-    for (Map.Entry<ActionMetadata, Pair<String, Long>> entry : statusMap.entrySet()) {
+      Map<ActionExecutionMetadata, Pair<String, Long>> statusMap,  String status,
+      long currentTime) {
+    List<Pair<Long, ActionExecutionMetadata>> actions = new ArrayList<>();
+    for (Map.Entry<ActionExecutionMetadata, Pair<String, Long>> entry : statusMap.entrySet()) {
       if (entry.getValue().first.equals(status)) {
         actions.add(Pair.of(entry.getValue().second, entry.getKey()));
       }
@@ -142,12 +143,12 @@
     if (actions.isEmpty()) {
       return;
     }
-    Collections.sort(actions, Pair.<Long, ActionMetadata>compareByFirst());
+    Collections.sort(actions, Pair.<Long, ActionExecutionMetadata>compareByFirst());
 
     buffer.append("\n      " + status + ":");
 
     boolean truncateList = actions.size() > MAX_LINES;
-    for (Pair<Long, ActionMetadata> entry : actions.subList(0,
+    for (Pair<Long, ActionExecutionMetadata> entry : actions.subList(0,
         truncateList ? MAX_LINES - 1 : actions.size())) {
       String message = entry.second.getProgressMessage();
       if (message == null) {
@@ -167,7 +168,8 @@
   /**
    * Get message showing currently executing actions.
    */
-  private String getExecutionStatusMessage(Map<ActionMetadata, Pair<String, Long>> statusMap) {
+  private String getExecutionStatusMessage(
+      Map<ActionExecutionMetadata, Pair<String, Long>> statusMap) {
     int count = statusMap.size();
     StringBuilder s = count != 1
         ? new StringBuilder("Still waiting for ").append(count).append(" jobs to complete:")
@@ -177,7 +179,7 @@
 
     // A tree is just as fast as HashSet for small data sets.
     Set<String> statuses = new TreeSet<>();
-    for (Map.Entry<ActionMetadata, Pair<String, Long>> entry : statusMap.entrySet()) {
+    for (Map.Entry<ActionExecutionMetadata, Pair<String, Long>> entry : statusMap.entrySet()) {
       statuses.add(entry.getValue().first);
     }
 
@@ -192,7 +194,7 @@
    */
   public void showCurrentlyExecutingActions(String progressPercentageMessage) {
     // Defensive copy to ensure thread safety.
-    Map<ActionMetadata, Pair<String, Long>> statusMap = new HashMap<>(actionStatus);
+    Map<ActionExecutionMetadata, Pair<String, Long>> statusMap = new HashMap<>(actionStatus);
     if (!statusMap.isEmpty()) {
       eventHandler.handle(
           Event.progress(progressPercentageMessage + getExecutionStatusMessage(statusMap)));
@@ -205,13 +207,13 @@
    */
   void warnAboutCurrentlyExecutingActions() {
     // Defensive copy to ensure thread safety.
-    Map<ActionMetadata, Pair<String, Long>> statusMap = new HashMap<>(actionStatus);
+    Map<ActionExecutionMetadata, Pair<String, Long>> statusMap = new HashMap<>(actionStatus);
     if (statusMap.isEmpty()) {
       // There are no tasks in the queue so there is nothing to report.
       eventHandler.handle(Event.warn("There are no active jobs - stopping the build"));
       return;
     }
-    Iterator<ActionMetadata> iterator = statusMap.keySet().iterator();
+    Iterator<ActionExecutionMetadata> iterator = statusMap.keySet().iterator();
     while (iterator.hasNext()) {
       // Filter out actions that are not executed yet.
       if (statusMap.get(iterator.next()).first.equals(ActionStatusMessage.PREPARING)) {
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionGraph.java b/src/main/java/com/google/devtools/build/lib/actions/ActionGraph.java
index bd105c4..5b850d9 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionGraph.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionGraph.java
@@ -34,5 +34,5 @@
    * are unknown.
    */
   @Nullable
-  Action getGeneratingAction(Artifact artifact);
+  ActionAnalysisMetadata getGeneratingAction(Artifact artifact);
 }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionGraphVisitor.java b/src/main/java/com/google/devtools/build/lib/actions/ActionGraphVisitor.java
index 7e13e5d..6d335a8 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionGraphVisitor.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionGraphVisitor.java
@@ -17,7 +17,8 @@
  * An abstract visitor for the action graph.  Specializes {@link BipartiteVisitor} for artifacts and
  * actions, and takes care of visiting the complete transitive closure.
  */
-public abstract class ActionGraphVisitor extends BipartiteVisitor<Action, Artifact> {
+public abstract class ActionGraphVisitor extends
+    BipartiteVisitor<ActionAnalysisMetadata, Artifact> {
 
   private final ActionGraph actionGraph;
 
@@ -37,7 +38,7 @@
    *
    * @param action
    */
-  protected void visitAction(Action action) {}
+  protected void visitAction(ActionAnalysisMetadata action) {}
 
   /**
    * Whether the given action should be visited. If this returns false, the visitation stops here,
@@ -45,7 +46,7 @@
    *
    * @param action  
    */
-  protected boolean shouldVisit(Action action) {
+  protected boolean shouldVisit(ActionAnalysisMetadata action) {
     return true;
   }
 
@@ -67,14 +68,14 @@
   }
 
   @Override protected void white(Artifact artifact) {
-    Action action = actionGraph.getGeneratingAction(artifact);
+    ActionAnalysisMetadata action = actionGraph.getGeneratingAction(artifact);
     visitArtifact(artifact);
     if (action != null && shouldVisit(action)) {
       visitBlackNode(action);
     }
   }
 
-  @Override protected void black(Action action) {
+  @Override protected void black(ActionAnalysisMetadata action) {
     visitAction(action);
     for (Artifact input : action.getInputs()) {
       if (shouldVisit(input)) {
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java b/src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java
index a4a85d2..26bbb6d 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java
@@ -49,7 +49,7 @@
         // going away anyway.
         Preconditions.checkArgument(mm.isMiddlemanArtifact(),
             "%s is not a middleman artifact", mm);
-        Action middlemanAction = actionGraph.getGeneratingAction(mm);
+        ActionAnalysisMetadata middlemanAction = actionGraph.getGeneratingAction(mm);
         Preconditions.checkState(middlemanAction != null, mm);
         // TODO(bazel-team): Consider expanding recursively or throwing an exception here.
         // Most likely, this code will cause silent errors if we ever have a middleman that
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionRegistry.java b/src/main/java/com/google/devtools/build/lib/actions/ActionRegistry.java
index 8755879..de85ce9 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionRegistry.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionRegistry.java
@@ -23,7 +23,7 @@
   /**
    * This method notifies the registry new actions.
    */
-  void registerAction(Action... actions);
+  void registerAction(ActionAnalysisMetadata... actions);
 
   /**
    * Get the (Label and BuildConfiguration) of the ConfiguredTarget ultimately responsible for all
@@ -37,7 +37,7 @@
   @VisibleForTesting
   public static final ActionRegistry NOP = new ActionRegistry() {
     @Override
-    public void registerAction(Action... actions) {}
+    public void registerAction(ActionAnalysisMetadata... actions) {}
 
     @Override
     public ArtifactOwner getOwner() {
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionStatusMessage.java b/src/main/java/com/google/devtools/build/lib/actions/ActionStatusMessage.java
index 144e862..f0ef8d8 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionStatusMessage.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionStatusMessage.java
@@ -20,16 +20,16 @@
  * used to notify any interested parties.
  */
 public class ActionStatusMessage {
-  private final ActionMetadata action;
+  private final ActionExecutionMetadata action;
   private final String message;
   public static final String PREPARING = "Preparing";
 
-  private ActionStatusMessage(ActionMetadata action, String message) {
+  private ActionStatusMessage(ActionExecutionMetadata action, String message) {
     this.action = action;
     this.message = message;
   }
 
-  public ActionMetadata getActionMetadata() {
+  public ActionExecutionMetadata getActionMetadata() {
     return action;
   }
 
@@ -38,22 +38,23 @@
   }
 
   /** Creates "Analyzing" status message. */
-  public static ActionStatusMessage analysisStrategy(ActionMetadata action) {
+  public static ActionStatusMessage analysisStrategy(ActionExecutionMetadata action) {
     return new ActionStatusMessage(action, "Analyzing");
   }
 
   /** Creates "Preparing" status message. */
-  public static ActionStatusMessage preparingStrategy(ActionMetadata action) {
+  public static ActionStatusMessage preparingStrategy(ActionExecutionMetadata action) {
     return new ActionStatusMessage(action, PREPARING);
   }
 
   /** Creates "Scheduling" status message. */
-  public static ActionStatusMessage schedulingStrategy(ActionMetadata action) {
+  public static ActionStatusMessage schedulingStrategy(ActionExecutionMetadata action) {
     return new ActionStatusMessage(action, "Scheduling");
   }
 
   /** Creates "Running (strategy)" status message. */
-  public static ActionStatusMessage runningStrategy(ActionMetadata action, String strategy) {
+  public static ActionStatusMessage runningStrategy(
+      ActionExecutionMetadata action, String strategy) {
     return new ActionStatusMessage(action, String.format("Running (%s)", strategy));
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Actions.java b/src/main/java/com/google/devtools/build/lib/actions/Actions.java
index 3878fcd..9d74e3b 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Actions.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Actions.java
@@ -51,19 +51,27 @@
    * <p>This method implements an equivalence relationship across actions, based on the action
    * class, the key, and the list of inputs and outputs.
    */
-  public static boolean canBeShared(Action a, Action b) {
+  public static boolean canBeShared(ActionAnalysisMetadata a, ActionAnalysisMetadata b) {
     if (!a.getMnemonic().equals(b.getMnemonic())) {
       return false;
     }
-    if (!a.getKey().equals(b.getKey())) {
+
+    // Non-Actions cannot be shared.
+    if (!(a instanceof Action) || !(b instanceof Action)) {
+      return false;
+    }
+
+    Action actionA = (Action) a;
+    Action actionB = (Action) b;
+    if (!actionA.getKey().equals(actionB.getKey())) {
       return false;
     }
     // Don't bother to check input and output counts first; the expected result for these tests is
     // to always be true (i.e., that this method returns true).
-    if (!Iterables.elementsEqual(a.getMandatoryInputs(), b.getMandatoryInputs())) {
+    if (!Iterables.elementsEqual(actionA.getMandatoryInputs(), actionB.getMandatoryInputs())) {
       return false;
     }
-    if (!Iterables.elementsEqual(a.getOutputs(), b.getOutputs())) {
+    if (!Iterables.elementsEqual(actionA.getOutputs(), actionB.getOutputs())) {
       return false;
     }
     return true;
@@ -80,18 +88,19 @@
    * @throws ActionConflictException iff there are two unshareable actions generating the same
    *     output
    */
-  public static Map<Artifact, Action> filterSharedActionsAndThrowActionConflict(
-      Iterable<Action> actions) throws ActionConflictException {
+  public static Map<Artifact, ActionAnalysisMetadata> filterSharedActionsAndThrowActionConflict(
+      Iterable<? extends ActionAnalysisMetadata> actions) throws ActionConflictException {
     return Actions.maybeFilterSharedActionsAndThrowIfConflict(
         actions, /*allowSharedAction=*/ true);
   }
 
-  private static Map<Artifact, Action> maybeFilterSharedActionsAndThrowIfConflict(
-      Iterable<Action> actions, boolean allowSharedAction) throws ActionConflictException {
-    Map<Artifact, Action> generatingActions = new HashMap<>();
-    for (Action action : actions) {
+  private static Map<Artifact, ActionAnalysisMetadata> maybeFilterSharedActionsAndThrowIfConflict(
+      Iterable<? extends ActionAnalysisMetadata> actions, boolean allowSharedAction)
+      throws ActionConflictException {
+    Map<Artifact, ActionAnalysisMetadata> generatingActions = new HashMap<>();
+    for (ActionAnalysisMetadata action : actions) {
       for (Artifact artifact : action.getOutputs()) {
-        Action previousAction = generatingActions.put(artifact, action);
+        ActionAnalysisMetadata previousAction = generatingActions.put(artifact, action);
         if (previousAction != null && previousAction != action) {
           if (!allowSharedAction || !Actions.canBeShared(previousAction, action)) {
             throw new ActionConflictException(artifact, previousAction, action);
@@ -112,16 +121,17 @@
    * @return A map between actions that generated the conflicting artifacts and their associated
    *     {@link ArtifactPrefixConflictException}.
    */
-  public static Map<Action, ArtifactPrefixConflictException> findArtifactPrefixConflicts(
-      ActionGraph actionGraph, SortedMap<PathFragment, Artifact> artifactPathMap) {
+  public static Map<ActionAnalysisMetadata, ArtifactPrefixConflictException>
+      findArtifactPrefixConflicts(ActionGraph actionGraph,
+      SortedMap<PathFragment, Artifact> artifactPathMap) {
     // No actions in graph -- currently happens only in tests. Special-cased because .next() call
     // below is unconditional.
     if (artifactPathMap.isEmpty()) {
-      return ImmutableMap.<Action, ArtifactPrefixConflictException>of();
+      return ImmutableMap.<ActionAnalysisMetadata, ArtifactPrefixConflictException>of();
     }
 
     // Keep deterministic ordering of bad actions.
-    Map<Action, ArtifactPrefixConflictException> badActions = new LinkedHashMap();
+    Map<ActionAnalysisMetadata, ArtifactPrefixConflictException> badActions = new LinkedHashMap();
     Iterator<PathFragment> iter = artifactPathMap.keySet().iterator();
 
     // Report an error for every derived artifact which is a prefix of another.
@@ -140,9 +150,9 @@
         if (pathJ.startsWith(pathI)) { // prefix conflict.
           Artifact artifactI = Preconditions.checkNotNull(artifactPathMap.get(pathI), pathI);
           Artifact artifactJ = Preconditions.checkNotNull(artifactPathMap.get(pathJ), pathJ);
-          Action actionI =
+          ActionAnalysisMetadata actionI =
               Preconditions.checkNotNull(actionGraph.getGeneratingAction(artifactI), artifactI);
-          Action actionJ =
+          ActionAnalysisMetadata actionJ =
               Preconditions.checkNotNull(actionGraph.getGeneratingAction(artifactJ), artifactJ);
           if (actionI.shouldReportPathPrefixConflict(actionJ)) {
             ArtifactPrefixConflictException exception = new ArtifactPrefixConflictException(pathI,
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
index f28683b..95faf51 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
@@ -22,7 +22,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Ordering;
-import com.google.devtools.build.lib.actions.Action.MiddlemanType;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.shell.ShellUtils;
diff --git a/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java b/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java
index 8e34389..2e3a69d 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java
@@ -44,7 +44,7 @@
   private final ImmutableMap<PathFragment, Artifact> runfilesManifests;
   private final ImmutableSet<PathFragment> optionalOutputFiles;
   private final RunfilesSupplier runfilesSupplier;
-  private final ActionMetadata action;
+  private final ActionExecutionMetadata action;
   private final ResourceSet localResources;
 
   // TODO(bazel-team): When we migrate ActionSpawn to use this constructor decide on and enforce
@@ -57,7 +57,7 @@
       Map<String, String> executionInfo,
       Map<PathFragment, Artifact> runfilesManifests,
       RunfilesSupplier runfilesSupplier,
-      ActionMetadata action,
+      ActionExecutionMetadata action,
       ResourceSet localResources,
       Collection<PathFragment> optionalOutputFiles) {
     this.arguments = ImmutableList.copyOf(arguments);
@@ -78,7 +78,7 @@
      Map<String, String> environment,
      Map<String, String> executionInfo,
      RunfilesSupplier runfilesSupplier,
-     ActionMetadata action,
+     ActionExecutionMetadata action,
      ResourceSet localResources) {
     this(
         arguments,
@@ -99,7 +99,7 @@
       Map<String, String> environment,
       Map<String, String> executionInfo,
       Map<PathFragment, Artifact> runfilesManifests,
-      ActionMetadata action,
+      ActionExecutionMetadata action,
       ResourceSet localResources) {
     this(
         arguments,
@@ -118,7 +118,7 @@
   public BaseSpawn(List<String> arguments,
       Map<String, String> environment,
       Map<String, String> executionInfo,
-      ActionMetadata action,
+      ActionExecutionMetadata action,
       ResourceSet localResources) {
     this(
         arguments,
@@ -134,7 +134,7 @@
       Map<String, String> environment,
       Map<String, String> executionInfo,
       RunfilesSupplier runfilesSupplier,
-      ActionMetadata action,
+      ActionExecutionMetadata action,
       ResourceSet localResources,
       Collection<PathFragment> optionalOutputFiles) {
     this(
@@ -258,7 +258,7 @@
   }
 
   @Override
-  public ActionMetadata getResourceOwner() {
+  public ActionExecutionMetadata getResourceOwner() {
     return action;
   }
 
@@ -291,7 +291,8 @@
    * A local spawn requiring zero resources.
    */
   public static class Local extends BaseSpawn {
-    public Local(List<String> arguments, Map<String, String> environment, ActionMetadata action) {
+    public Local(List<String> arguments, Map<String, String> environment,
+        ActionExecutionMetadata action) {
       super(arguments, environment, ImmutableMap.<String, String>of("local", ""),
           action, ResourceSet.ZERO);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java b/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java
index acb9cd6..d72a686 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java
@@ -100,7 +100,7 @@
   }
 
   @Override
-  public ActionMetadata getResourceOwner() {
+  public ActionExecutionMetadata getResourceOwner() {
     return spawn.getResourceOwner();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/actions/MapBasedActionGraph.java b/src/main/java/com/google/devtools/build/lib/actions/MapBasedActionGraph.java
index 2535a2e..54d3411 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/MapBasedActionGraph.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/MapBasedActionGraph.java
@@ -24,19 +24,19 @@
  */
 @ThreadSafe
 public final class MapBasedActionGraph implements MutableActionGraph {
-  private final ConcurrentMultimapWithHeadElement<Artifact, Action> generatingActionMap =
-      new ConcurrentMultimapWithHeadElement<>();
+  private final ConcurrentMultimapWithHeadElement<Artifact, ActionAnalysisMetadata>
+      generatingActionMap = new ConcurrentMultimapWithHeadElement<>();
 
   @Override
   @Nullable
-  public Action getGeneratingAction(Artifact artifact) {
+  public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
     return generatingActionMap.get(artifact);
   }
 
   @Override
-  public void registerAction(Action action) throws ActionConflictException {
+  public void registerAction(ActionAnalysisMetadata action) throws ActionConflictException {
     for (Artifact artifact : action.getOutputs()) {
-      Action previousAction = generatingActionMap.putAndGet(artifact, action);
+      ActionAnalysisMetadata previousAction = generatingActionMap.putAndGet(artifact, action);
       if (previousAction != null && previousAction != action
           && !Actions.canBeShared(action, previousAction)) {
         generatingActionMap.remove(artifact, action);
@@ -46,10 +46,10 @@
   }
 
   @Override
-  public void unregisterAction(Action action) {
+  public void unregisterAction(ActionAnalysisMetadata action) {
     for (Artifact artifact : action.getOutputs()) {
       generatingActionMap.remove(artifact, action);
-      Action otherAction = generatingActionMap.get(artifact);
+      ActionAnalysisMetadata otherAction = generatingActionMap.get(artifact);
       Preconditions.checkState(otherAction == null
           || (otherAction != action && Actions.canBeShared(action, otherAction)),
           "%s %s", action, otherAction);
diff --git a/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java b/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java
index 24c436c..404b0de 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java
@@ -14,7 +14,7 @@
 package com.google.devtools.build.lib.actions;
 
 import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.actions.Action.MiddlemanType;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.util.Pair;
diff --git a/src/main/java/com/google/devtools/build/lib/actions/MutableActionGraph.java b/src/main/java/com/google/devtools/build/lib/actions/MutableActionGraph.java
index d5da897..50b3fa7 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/MutableActionGraph.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/MutableActionGraph.java
@@ -42,7 +42,7 @@
    * then both conflicts are detected; if either A or C is registered first, then only one conflict
    * is detected.
    */
-  void registerAction(Action action) throws ActionConflictException;
+  void registerAction(ActionAnalysisMetadata action) throws ActionConflictException;
 
   /**
    * Removes an action from this action graph if it is present.
@@ -50,7 +50,7 @@
    * <p>Throws {@link IllegalStateException} if one of the outputs of the action is in fact
    * generated by a different {@link Action} instance (even if they are sharable).
    */
-  void unregisterAction(Action action);
+  void unregisterAction(ActionAnalysisMetadata action);
 
   /**
    * Clear the action graph.
@@ -65,13 +65,13 @@
   public static final class ActionConflictException extends Exception {
 
     private final Artifact artifact;
-    private final Action previousAction;
-    private final Action attemptedAction;
+    private final ActionAnalysisMetadata previousAction;
+    private final ActionAnalysisMetadata attemptedAction;
     
     private static final int MAX_DIFF_ARTIFACTS_TO_REPORT = 5;
 
-    public ActionConflictException(Artifact artifact, Action previousAction,
-        Action attemptedAction) {
+    public ActionConflictException(Artifact artifact, ActionAnalysisMetadata previousAction,
+        ActionAnalysisMetadata attemptedAction) {
       super(
           String.format(
               "for %s, previous action: %s, attempted action: %s",
@@ -145,7 +145,7 @@
     }
 
     // See also Actions.canBeShared()
-    private String suffix(Action a, Action b) {
+    private String suffix(ActionAnalysisMetadata a, ActionAnalysisMetadata b) {
       // Note: the error message reveals to users the names of intermediate files that are not
       // documented in the BUILD language.  This error-reporting logic is rather elaborate but it
       // does help to diagnose some tricky situations.
@@ -162,7 +162,15 @@
       addStringDetail(sb, "Configuration", aNull ? null : aOwner.getConfigurationChecksum(),
           bNull ? null : bOwner.getConfigurationChecksum());
       addStringDetail(sb, "Mnemonic", a.getMnemonic(), b.getMnemonic());
-      addStringDetail(sb, "Progress message", a.getProgressMessage(), b.getProgressMessage());
+
+      if ((a instanceof ActionExecutionMetadata) && (b instanceof ActionExecutionMetadata)) {
+        addStringDetail(
+            sb,
+            "Progress message",
+            ((ActionExecutionMetadata) a).getProgressMessage(),
+            ((ActionExecutionMetadata) b).getProgressMessage());
+      }
+
       addStringDetail(
           sb,
           "PrimaryInput",
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java b/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java
index c263b2d..3ebaee0 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java
@@ -61,16 +61,16 @@
 public class ResourceManager {
 
   /**
-   * A handle returned by {@link #acquireResources(ActionMetadata, ResourceSet)} that must be closed
-   * in order to free the resources again.
+   * A handle returned by {@link #acquireResources(ActionExecutionMetadata, ResourceSet)} that must
+   * be closed in order to free the resources again.
    */
   public static class ResourceHandle implements AutoCloseable {
     final ResourceManager rm;
-    final ActionMetadata actionMetadata;
+    final ActionExecutionMetadata actionMetadata;
     final ResourceSet resourceSet;
 
-    public ResourceHandle(
-        ResourceManager rm, ActionMetadata actionMetadata, ResourceSet resources) {
+    public ResourceHandle(ResourceManager rm, ActionExecutionMetadata actionMetadata,
+        ResourceSet resources) {
       this.rm = rm;
       this.actionMetadata = actionMetadata;
       this.resourceSet = resources;
@@ -200,7 +200,7 @@
    * Acquires requested resource set. Will block if resource is not available.
    * NB! This method must be thread-safe!
    */
-  public ResourceHandle acquireResources(ActionMetadata owner, ResourceSet resources)
+  public ResourceHandle acquireResources(ActionExecutionMetadata owner, ResourceSet resources)
       throws InterruptedException {
     Preconditions.checkNotNull(resources);
     AutoProfiler p = profiled(owner, ProfilerTask.ACTION_LOCK);
@@ -228,7 +228,7 @@
    * Acquires the given resources if available immediately. Does not block.
    * @return true iff the given resources were locked (all or nothing).
    */
-  public boolean tryAcquire(ActionMetadata owner, ResourceSet resources) {
+  public boolean tryAcquire(ActionExecutionMetadata owner, ResourceSet resources) {
     boolean acquired = false;
     synchronized (this) {
       if (areResourcesAvailable(resources)) {
@@ -279,14 +279,14 @@
     this.eventBus = null;
   }
 
-  private void waiting(ActionMetadata owner) {
+  private void waiting(ActionExecutionMetadata owner) {
     if (eventBus != null) {
       // Null only in tests.
       eventBus.post(ActionStatusMessage.schedulingStrategy(owner));
     }
   }
 
-  private void acquired(ActionMetadata owner) {
+  private void acquired(ActionExecutionMetadata owner) {
     if (eventBus != null) {
       // Null only in tests.
       eventBus.post(ActionStatusMessage.runningStrategy(owner, "unknown"));
@@ -298,7 +298,7 @@
    *
    * <p>NB! This method must be thread-safe!
    */
-  public void releaseResources(ActionMetadata owner, ResourceSet resources) {
+  public void releaseResources(ActionExecutionMetadata owner, ResourceSet resources) {
     boolean isConflict = false;
     AutoProfiler p = profiled(owner, ProfilerTask.ACTION_RELEASE);
     try {
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Spawn.java b/src/main/java/com/google/devtools/build/lib/actions/Spawn.java
index b4ed5c7..3e24fdc 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Spawn.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Spawn.java
@@ -129,7 +129,7 @@
   /**
    * Returns the resource owner for local fallback.
    */
-  ActionMetadata getResourceOwner();
+  ActionExecutionMetadata getResourceOwner();
 
   /**
    * Returns the amount of resources needed for local fallback.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
index cf1b16b..dd96b3a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
@@ -17,6 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionRegistry;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.MiddlemanFactory;
@@ -105,13 +106,13 @@
    * If the artifact was created in another analysis environment (e.g. by a different configured
    * target instance) or the artifact is a source artifact, it returns null.
    */
-  Action getLocalGeneratingAction(Artifact artifact);
+  ActionAnalysisMetadata getLocalGeneratingAction(Artifact artifact);
 
   /**
    * Returns the actions that were registered so far with this analysis environment, that is, all
    * the actions that were created by the current target being analyzed.
    */
-  Iterable<Action> getRegisteredActions();
+  Iterable<ActionAnalysisMetadata> getRegisteredActions();
 
   /**
    * Returns the Skyframe SkyFunction.Environment if available. Otherwise, null.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index fb30f60..1251fe1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -27,7 +27,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.eventbus.EventBus;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionGraph;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
@@ -552,7 +552,7 @@
           getArtifactFactory(),
           CoverageReportValue.ARTIFACT_OWNER);
       if (actionsWrapper != null) {
-        ImmutableList <Action> actions = actionsWrapper.getActions();
+        ImmutableList<ActionAnalysisMetadata> actions = actionsWrapper.getActions();
         skyframeExecutor.injectCoverageReportData(actions);
         artifactsToBuild.addAll(actionsWrapper.getCoverageOutputs());
       }
@@ -571,7 +571,7 @@
     final ActionGraph actionGraph = new ActionGraph() {
       @Nullable
       @Override
-      public Action getGeneratingAction(Artifact artifact) {
+      public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
         ArtifactOwner artifactOwner = artifact.getArtifactOwner();
         if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) {
           SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
index 4d1d787..2f8762d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
@@ -17,7 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
@@ -90,7 +90,7 @@
    * The list of actions registered by the configured target this analysis environment is
    * responsible for. May get cleared out at the end of the analysis of said target.
    */
-  final List<Action> actions = new ArrayList<>();
+  final List<ActionAnalysisMetadata> actions = new ArrayList<>();
 
   public CachingAnalysisEnvironment(ArtifactFactory artifactFactory,
       ArtifactOwner owner, boolean isSystemEnv, boolean extendedSanityChecks,
@@ -119,7 +119,7 @@
     skyframeEnv = null;
   }
 
-  private static StringBuilder shortDescription(Action action) {
+  private static StringBuilder shortDescription(ActionAnalysisMetadata action) {
     if (action == null) {
       return new StringBuilder("null Action");
     }
@@ -138,7 +138,7 @@
     List<String> checkedActions = null;
     if (!orphanArtifacts.isEmpty()) {
       checkedActions = Lists.newArrayListWithCapacity(actions.size());
-      for (Action action : actions) {
+      for (ActionAnalysisMetadata action : actions) {
         StringBuilder sb = shortDescription(action);
         for (Artifact o : action.getOutputs()) {
           sb.append("\n    ");
@@ -166,7 +166,7 @@
   private Map<Artifact, String> getOrphanArtifactMap() {
     // Construct this set to avoid poor performance under large --runs_per_test.
     Set<Artifact> artifactsWithActions = new HashSet<>();
-    for (Action action : actions) {
+    for (ActionAnalysisMetadata action : actions) {
       // Don't bother checking that every Artifact only appears once; that test is performed
       // elsewhere (see #testNonUniqueOutputs in ActionListenerIntegrationTest).
       artifactsWithActions.addAll(action.getOutputs());
@@ -258,7 +258,7 @@
   }
 
   @Override
-  public void registerAction(Action... actions) {
+  public void registerAction(ActionAnalysisMetadata... actions) {
     Preconditions.checkState(enabled);
     if (allowRegisteringActions) {
       Collections.addAll(this.actions, actions);
@@ -266,9 +266,9 @@
   }
 
   @Override
-  public Action getLocalGeneratingAction(Artifact artifact) {
+  public ActionAnalysisMetadata getLocalGeneratingAction(Artifact artifact) {
     Preconditions.checkState(allowRegisteringActions);
-    for (Action action : actions) {
+    for (ActionAnalysisMetadata action : actions) {
       if (action.getOutputs().contains(artifact)) {
         return action;
       }
@@ -277,7 +277,7 @@
   }
 
   @Override
-  public Collection<Action> getRegisteredActions() {
+  public Collection<ActionAnalysisMetadata> getRegisteredActions() {
     return Collections.unmodifiableCollection(actions);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
index 645cd6d..7f3db2a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
@@ -20,7 +20,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.UnmodifiableIterator;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -174,7 +174,8 @@
       addProvider(
           ExtraActionArtifactsProvider.class,
           createExtraActionProvider(
-              ImmutableSet.<Action>of() /* actionsWithoutExtraAction */, ruleContext));
+              ImmutableSet.<ActionAnalysisMetadata>of() /* actionsWithoutExtraAction */,
+              ruleContext));
 
       return new ConfiguredAspect(name, ImmutableMap.copyOf(providers));
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionUtils.java b/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionUtils.java
index 829e637..782eaa2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionUtils.java
@@ -16,7 +16,7 @@
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Multimap;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.ExtraActionArtifactsProvider.ExtraArtifactSet;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
@@ -44,7 +44,7 @@
    * bookkeeping.
    */
   static ExtraActionArtifactsProvider createExtraActionProvider(
-      Set<Action> actionsWithoutExtraAction, RuleContext ruleContext) {
+      Set<ActionAnalysisMetadata> actionsWithoutExtraAction, RuleContext ruleContext) {
     BuildConfiguration configuration = ruleContext.getConfiguration();
     if (configuration.isHostConfiguration()) {
       return ExtraActionArtifactsProvider.EMPTY;
@@ -61,7 +61,7 @@
 
       // The action list is modified within the body of the loop by the maybeAddExtraAction() call,
       // thus the copy
-      for (Action action :
+      for (ActionAnalysisMetadata action :
           ImmutableList.copyOf(ruleContext.getAnalysisEnvironment().getRegisteredActions())) {
         if (!actionsWithoutExtraAction.contains(action)) {
           visitor.maybeAddExtraAction(action);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionsVisitor.java b/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionsVisitor.java
index 3b4069e..db10173 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionsVisitor.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ExtraActionsVisitor.java
@@ -17,8 +17,8 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionGraph;
 import com.google.devtools.build.lib.actions.ActionGraphVisitor;
 import com.google.devtools.build.lib.actions.Artifact;
@@ -26,7 +26,6 @@
 
 import java.util.Collection;
 import java.util.List;
-import java.util.Set;
 
 import javax.annotation.Nullable;
 
@@ -37,7 +36,6 @@
   private final RuleContext ruleContext;
   private final Multimap<String, ExtraActionSpec> mnemonicToExtraActionMap;
   private final List<Artifact> extraArtifacts;
-  public final Set<Action> actions = Sets.newHashSet();
 
   /** Creates a new visitor for the extra actions associated with the given target. */
   public ExtraActionsVisitor(RuleContext ruleContext,
@@ -48,21 +46,23 @@
     extraArtifacts = Lists.newArrayList();
   }
 
-  void maybeAddExtraAction(Action original) {
-    if (original.extraActionCanAttach()) {
-      Collection<ExtraActionSpec> extraActions =
-          mnemonicToExtraActionMap.get(original.getMnemonic());
-      if (extraActions != null) {
-        for (ExtraActionSpec extraAction : extraActions) {
-          extraArtifacts.addAll(extraAction.addExtraAction(ruleContext, original));
+  void maybeAddExtraAction(ActionAnalysisMetadata original) {
+    if (original instanceof Action) {
+      Action action = (Action) original;
+      if (action.extraActionCanAttach()) {
+        Collection<ExtraActionSpec> extraActions =
+            mnemonicToExtraActionMap.get(action.getMnemonic());
+        if (extraActions != null) {
+          for (ExtraActionSpec extraAction : extraActions) {
+            extraArtifacts.addAll(extraAction.addExtraAction(ruleContext, action));
+          }
         }
       }
     }
   }
 
   @Override
-  protected void visitAction(Action action) {
-    actions.add(action);
+  protected void visitAction(ActionAnalysisMetadata action) {
     maybeAddExtraAction(action);
   }
 
@@ -78,7 +78,7 @@
     return new ActionGraph() {
       @Override
       @Nullable
-      public Action getGeneratingAction(Artifact artifact) {
+      public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
         return ruleContext.getAnalysisEnvironment().getLocalGeneratingAction(artifact);
       }
     };
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/PrintActionVisitor.java b/src/main/java/com/google/devtools/build/lib/analysis/PrintActionVisitor.java
index 2878092..abe62c1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/PrintActionVisitor.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/PrintActionVisitor.java
@@ -16,7 +16,7 @@
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionGraph;
 import com.google.devtools.build.lib.actions.ActionGraphVisitor;
 import com.google.devtools.build.lib.actions.ActionOwner;
@@ -28,8 +28,8 @@
  */
 public final class PrintActionVisitor extends ActionGraphVisitor {
   private final ConfiguredTarget target;
-  private final List<Action> actions;
-  private final Predicate<Action> actionMnemonicMatcher;
+  private final List<ActionAnalysisMetadata> actions;
+  private final Predicate<ActionAnalysisMetadata> actionMnemonicMatcher;
   private final String targetConfigurationChecksum;
 
   /**
@@ -37,7 +37,7 @@
    * mnemonic.
    */
   public PrintActionVisitor(ActionGraph actionGraph, ConfiguredTarget target,
-      Predicate<Action> actionMnemonicMatcher) {
+      Predicate<ActionAnalysisMetadata> actionMnemonicMatcher) {
     super(actionGraph);
     this.target = target;
     this.actionMnemonicMatcher = actionMnemonicMatcher;
@@ -46,21 +46,21 @@
   }
 
   @Override
-  protected boolean shouldVisit(Action action) {
+  protected boolean shouldVisit(ActionAnalysisMetadata action) {
     ActionOwner owner = action.getOwner();
     return owner != null && target.getLabel().equals(owner.getLabel())
         && targetConfigurationChecksum.equals(owner.getConfigurationChecksum());
   }
 
   @Override
-  protected void visitAction(Action action) {
+  protected void visitAction(ActionAnalysisMetadata action) {
     if (actionMnemonicMatcher.apply(action)) {
       actions.add(action);
     }
   }
 
   /** Retrieves the collected actions since this method was last called and clears the list. */
-  public ImmutableList<Action> getActions() {
+  public ImmutableList<ActionAnalysisMetadata> getActions() {
     return ImmutableList.copyOf(actions);
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
index 07b0d86..853fdf7 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
@@ -18,7 +18,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -62,7 +62,7 @@
   private NestedSet<Artifact> filesToBuild = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
   private RunfilesSupport runfilesSupport;
   private Artifact executable;
-  private ImmutableSet<Action> actionsWithoutExtraAction = ImmutableSet.of();
+  private ImmutableSet<ActionAnalysisMetadata> actionsWithoutExtraAction = ImmutableSet.of();
 
   public RuleConfiguredTargetBuilder(RuleContext ruleContext) {
     this.ruleContext = ruleContext;
@@ -341,7 +341,8 @@
   /**
    * Set the extra action pseudo actions.
    */
-  public RuleConfiguredTargetBuilder setActionsWithoutExtraAction(ImmutableSet<Action> actions) {
+  public RuleConfiguredTargetBuilder setActionsWithoutExtraAction(
+      ImmutableSet<ActionAnalysisMetadata> actions) {
     this.actionsWithoutExtraAction = actions;
     return this;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index fef9393..cc3118b 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -29,6 +29,7 @@
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.ActionRegistry;
 import com.google.devtools.build.lib.actions.Artifact;
@@ -379,7 +380,7 @@
   }
 
   @Override
-  public void registerAction(Action... action) {
+  public void registerAction(ActionAnalysisMetadata... action) {
     getAnalysisEnvironment().registerAction(action);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoCollection.java
index 39b1d96..18a147e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoCollection.java
@@ -14,7 +14,7 @@
 package com.google.devtools.build.lib.analysis.buildinfo;
 
 import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 
 import java.util.List;
@@ -23,19 +23,19 @@
  * A collection of build-info files for both stamped and unstamped modes.
  */
 public final class BuildInfoCollection {
-  private final ImmutableList<Action> actions;
+  private final ImmutableList<ActionAnalysisMetadata> actions;
   private final ImmutableList<Artifact> stampedBuildInfo;
   private final ImmutableList<Artifact> redactedBuildInfo;
 
-  public BuildInfoCollection(List<? extends Action> actions, List<Artifact> stampedBuildInfo,
-      List<Artifact> redactedBuildInfo) {
+  public BuildInfoCollection(List<? extends ActionAnalysisMetadata> actions,
+      List<Artifact> stampedBuildInfo, List<Artifact> redactedBuildInfo) {
     // Do not remove <Action>: workaround for Java 7 type inference.
-    this.actions = ImmutableList.<Action>copyOf(actions);
+    this.actions = ImmutableList.<ActionAnalysisMetadata>copyOf(actions);
     this.stampedBuildInfo = ImmutableList.copyOf(stampedBuildInfo);
     this.redactedBuildInfo = ImmutableList.copyOf(redactedBuildInfo);
   }
 
-  public ImmutableList<Action> getActions() {
+  public ImmutableList<ActionAnalysisMetadata> getActions() {
     return actions;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java
index f688fd2..75ba75e 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnStrategy.java
@@ -19,10 +19,10 @@
 import com.google.common.hash.Hashing;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
+import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
 import com.google.devtools.build.lib.actions.ActionInput;
 import com.google.devtools.build.lib.actions.ActionInputFileCache;
 import com.google.devtools.build.lib.actions.ActionInputHelper;
-import com.google.devtools.build.lib.actions.ActionMetadata;
 import com.google.devtools.build.lib.actions.ExecException;
 import com.google.devtools.build.lib.actions.ExecutionStrategy;
 import com.google.devtools.build.lib.actions.Executor;
@@ -84,7 +84,7 @@
     }
 
     Executor executor = actionExecutionContext.getExecutor();
-    ActionMetadata actionMetadata = spawn.getResourceOwner();
+    ActionExecutionMetadata actionMetadata = spawn.getResourceOwner();
     ActionInputFileCache inputFileCache = actionExecutionContext.getActionInputFileCache();
     EventHandler eventHandler = executor.getEventHandler();
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
index e1c1348..9c9b19c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -19,7 +19,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.FileProvider;
@@ -72,7 +72,7 @@
     public void collectMetadataArtifacts(Iterable<Artifact> objectFiles,
         AnalysisEnvironment analysisEnvironment, NestedSetBuilder<Artifact> metadataFilesBuilder) {
       for (Artifact artifact : objectFiles) {
-        Action action = analysisEnvironment.getLocalGeneratingAction(artifact);
+        ActionAnalysisMetadata action = analysisEnvironment.getLocalGeneratingAction(artifact);
         if (action instanceof CppCompileAction) {
           addOutputs(metadataFilesBuilder, action, CppFileTypes.COVERAGE_NOTES);
         }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java
index e3250cab..b8a6854 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java
@@ -16,7 +16,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.AbstractAction;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
 import com.google.devtools.build.lib.actions.ActionExecutionException;
 import com.google.devtools.build.lib.actions.ActionOwner;
@@ -224,7 +224,7 @@
   }
 
   @Override
-  public boolean shouldReportPathPrefixConflict(Action action) {
+  public boolean shouldReportPathPrefixConflict(ActionAnalysisMetadata action) {
     return false; // Always ignore path prefix conflict for the SolibSymlinkAction.
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
index 7fa48b1..b4650d2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java
@@ -18,7 +18,7 @@
 import com.google.common.collect.ImmutableList.Builder;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.AnalysisUtils;
@@ -86,7 +86,7 @@
     public void collectMetadataArtifacts(Iterable<Artifact> objectFiles,
         AnalysisEnvironment analysisEnvironment, NestedSetBuilder<Artifact> metadataFilesBuilder) {
       for (Artifact artifact : objectFiles) {
-        Action action = analysisEnvironment.getLocalGeneratingAction(artifact);
+        ActionAnalysisMetadata action = analysisEnvironment.getLocalGeneratingAction(artifact);
         if (action instanceof JavaCompileAction) {
           addOutputs(metadataFilesBuilder, action, JavaSemantics.COVERAGE_METADATA);
         }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
index 8fe7df3..57e5215 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
@@ -55,6 +55,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ParameterFile;
 import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
@@ -1354,7 +1355,7 @@
         AnalysisEnvironment analysisEnvironment,
         NestedSetBuilder<Artifact> metadataFilesBuilder) {
       for (Artifact artifact : artifacts) {
-        Action action = analysisEnvironment.getLocalGeneratingAction(artifact);
+        ActionAnalysisMetadata action = analysisEnvironment.getLocalGeneratingAction(artifact);
         if (action.getMnemonic().equals("ObjcCompile")) {
           addOutputs(metadataFilesBuilder, action, ObjcRuleClasses.COVERAGE_NOTES);
         }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/CoverageReportActionFactory.java b/src/main/java/com/google/devtools/build/lib/rules/test/CoverageReportActionFactory.java
index 3c81ee5..621b352 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/CoverageReportActionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/CoverageReportActionFactory.java
@@ -16,7 +16,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
@@ -43,16 +43,16 @@
    */
 
   public static final class CoverageReportActionsWrapper {
-    private final Action lcovWriteAction;
-    private final Action coverageReportAction;
+    private final ActionAnalysisMetadata lcovWriteAction;
+    private final ActionAnalysisMetadata coverageReportAction;
 
     public CoverageReportActionsWrapper (
-        Action lcovWriteAction, Action coverageReportAction) {
+        ActionAnalysisMetadata lcovWriteAction, ActionAnalysisMetadata coverageReportAction) {
       this.lcovWriteAction = lcovWriteAction;
       this.coverageReportAction = coverageReportAction;
     }
 
-    public ImmutableList<Action> getActions() {
+    public ImmutableList<ActionAnalysisMetadata> getActions() {
       return ImmutableList.of(lcovWriteAction, coverageReportAction);
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java
index 4b62f41..9951f63 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java
@@ -14,7 +14,7 @@
 package com.google.devtools.build.lib.rules.test;
 
 import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.FileProvider;
@@ -234,7 +234,7 @@
      * @param fileType the filetype of outputs which should be collected
      */
     protected void addOutputs(NestedSetBuilder<Artifact> metadataFilesBuilder,
-                              Action action, FileType fileType) {
+                              ActionAnalysisMetadata action, FileType fileType) {
       for (Artifact output : action.getOutputs()) {
         if (fileType.matches(output.getFilename())) {
           metadataFilesBuilder.add(output);
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 5a39dbb..a6a110c 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
@@ -92,6 +92,7 @@
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env) throws ActionExecutionFunctionException,
       InterruptedException {
+    Preconditions.checkArgument(skyKey.argument() instanceof Action);
     Action action = (Action) skyKey.argument();
     // TODO(bazel-team): Non-volatile NotifyOnActionCacheHit actions perform worse in Skyframe than
     // legacy when they are not at the top of the action graph. In legacy, they are stored
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java
index fdce7c6..e56ef46 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionValue.java
@@ -18,7 +18,7 @@
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.actions.Action;
-import com.google.devtools.build.lib.actions.Action.MiddlemanType;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionLookupValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionLookupValue.java
index e40817c..db23b45 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionLookupValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionLookupValue.java
@@ -16,7 +16,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Actions;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
@@ -34,10 +34,10 @@
  * actions of target completion values and build info artifacts also fall into this category.
  */
 public class ActionLookupValue implements SkyValue {
-  protected final ImmutableMap<Artifact, Action> generatingActionMap;
+  protected final ImmutableMap<Artifact, ActionAnalysisMetadata> generatingActionMap;
 
-  private static Map<Artifact, Action> filterSharedActionsAndThrowRuntimeIfConflict(
-      Iterable<Action> actions) {
+  private static Map<Artifact, ActionAnalysisMetadata> filterSharedActionsAndThrowRuntimeIfConflict(
+      Iterable<ActionAnalysisMetadata> actions) {
     try {
       return Actions.filterSharedActionsAndThrowActionConflict(actions);
     } catch (ActionConflictException e) {
@@ -46,24 +46,24 @@
     }
   }
 
-  ActionLookupValue(Iterable<Action> actions) {
+  ActionLookupValue(Iterable<ActionAnalysisMetadata> actions) {
     this(filterSharedActionsAndThrowRuntimeIfConflict(actions));
   }
 
-  ActionLookupValue(Action action) {
+  ActionLookupValue(ActionAnalysisMetadata action) {
     this(ImmutableList.of(action));
   }
 
-  ActionLookupValue(Map<Artifact, Action> generatingActionMap) {
+  ActionLookupValue(Map<Artifact, ActionAnalysisMetadata> generatingActionMap) {
     this.generatingActionMap = ImmutableMap.copyOf(generatingActionMap);
   }
 
-  public Action getGeneratingAction(Artifact artifact) {
+  public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
     return generatingActionMap.get(artifact);
   }
 
   /** To be used only when checking consistency of the action graph -- not by other values. */
-  ImmutableMap<Artifact, Action> getMapForConsistencyCheck() {
+  ImmutableMap<Artifact, ActionAnalysisMetadata> getMapForConsistencyCheck() {
     return generatingActionMap;
   }
 
@@ -71,7 +71,7 @@
    * To be used only when setting the owners of deserialized artifacts whose owners were unknown at
    * creation time -- not by other callers or values.
    */
-  Iterable<Action> getActionsForFindingArtifactOwners() {
+  Iterable<ActionAnalysisMetadata> getActionsForFindingArtifactOwners() {
     return generatingActionMap.values();
   }
 
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 312feef..c8022d5 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
@@ -16,7 +16,8 @@
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.Action;
-import com.google.devtools.build.lib.actions.Action.MiddlemanType;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
 import com.google.devtools.build.lib.actions.ActionExecutionException;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
@@ -65,11 +66,16 @@
       }
     }
 
-    Action action = extractActionFromArtifact(artifact, env);
-    if (action == null) {
+    ActionAnalysisMetadata actionMetadata = extractActionFromArtifact(artifact, env);
+    if (actionMetadata == null) {
       return null;
     }
 
+    Preconditions.checkState(
+        actionMetadata instanceof Action,
+        "%s is not a proper Action object and therefore cannot be executed",
+        actionMetadata);
+    Action action = (Action) actionMetadata;
     ActionExecutionValue actionValue =
         (ActionExecutionValue) env.getValue(ActionExecutionValue.key(action));
     if (actionValue == null) {
@@ -165,8 +171,8 @@
     return FileArtifactValue.create(artifact, data);
   }
 
-  private AggregatingArtifactValue createAggregatingValue(Artifact artifact, Action action,
-      FileArtifactValue value, SkyFunction.Environment env) {
+  private AggregatingArtifactValue createAggregatingValue(Artifact artifact,
+      ActionAnalysisMetadata action, FileArtifactValue value, SkyFunction.Environment env) {
     // This artifact aggregates other artifacts. Keep track of them so callers can find them.
     ImmutableList.Builder<Pair<Artifact, FileArtifactValue>> inputs = ImmutableList.builder();
     for (Map.Entry<SkyKey, SkyValue> entry :
@@ -190,7 +196,7 @@
    * see if the action is an aggregating middleman action. However, may include runfiles middleman
    * actions and Fileset artifacts in the future.
    */
-  private static boolean isAggregatingValue(Action action) {
+  private static boolean isAggregatingValue(ActionAnalysisMetadata action) {
     return action.getActionType() == MiddlemanType.AGGREGATING_MIDDLEMAN;
   }
 
@@ -199,7 +205,8 @@
     return Label.print(((OwnedArtifact) skyKey.argument()).getArtifact().getOwner());
   }
 
-  private Action extractActionFromArtifact(Artifact artifact, SkyFunction.Environment env) {
+  private ActionAnalysisMetadata extractActionFromArtifact(
+      Artifact artifact, SkyFunction.Environment env) {
     ArtifactOwner artifactOwner = artifact.getArtifactOwner();
 
     Preconditions.checkState(artifactOwner instanceof ActionLookupKey, "", artifact, artifactOwner);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index 56878b1..f37e5e2 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -16,7 +16,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ListMultimap;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
 import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
@@ -288,7 +288,7 @@
         originalTarget.getLabel(),
         originalTarget.getLocation(),
         ConfiguredAspect.forAlias(real.getConfiguredAspect()),
-        ImmutableList.<Action>of(),
+        ImmutableList.<ActionAnalysisMetadata>of(),
         transitivePackages);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java
index effd33f..33cf880 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java
@@ -15,7 +15,7 @@
 package com.google.devtools.build.lib.skyframe;
 
 import com.google.common.base.Objects;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.cmdline.Label;
@@ -247,7 +247,7 @@
       Label label,
       Location location,
       ConfiguredAspect configuredAspect,
-      Iterable<Action> actions,
+      Iterable<ActionAnalysisMetadata> actions,
       NestedSet<Package> transitivePackages) {
     super(actions);
     this.aspect = aspect;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index 0a5caf0..6fb86c8 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -23,7 +23,7 @@
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Actions;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
@@ -846,7 +846,7 @@
     analysisEnvironment.disable(target);
     Preconditions.checkNotNull(configuredTarget, target);
 
-    Map<Artifact, Action> generatingActions;
+    Map<Artifact, ActionAnalysisMetadata> generatingActions;
     // Check for conflicting actions within this configured target (that indicates a bug in the
     // rule implementation).
     try {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetValue.java
index 3918bf7..7f32c1e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetValue.java
@@ -16,7 +16,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -46,12 +46,13 @@
 
   // We overload this variable to check whether the value has been clear()ed. We don't use a
   // separate variable in order to save memory.
-  @Nullable private volatile Iterable<Action> actions;
+  @Nullable private volatile Iterable<ActionAnalysisMetadata> actions;
 
   private final NestedSet<Package> transitivePackages;
 
   ConfiguredTargetValue(ConfiguredTarget configuredTarget,
-      Map<Artifact, Action> generatingActionMap, NestedSet<Package> transitivePackages) {
+      Map<Artifact, ActionAnalysisMetadata> generatingActionMap,
+      NestedSet<Package> transitivePackages) {
     super(generatingActionMap);
     this.configuredTarget = configuredTarget;
     this.actions = generatingActionMap.values();
@@ -65,7 +66,7 @@
   }
 
   @VisibleForTesting
-  public Iterable<Action> getActions() {
+  public Iterable<ActionAnalysisMetadata> getActions() {
     return Preconditions.checkNotNull(actions, configuredTarget);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java
index 0a13579..53d7a86 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportFunction.java
@@ -16,7 +16,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.skyframe.SkyFunction;
@@ -35,14 +35,14 @@
         CoverageReportValue.SKY_KEY.equals(skyKey), String.format(
             "Expected %s for SkyKey but got %s instead", CoverageReportValue.SKY_KEY, skyKey));
 
-    ImmutableList <Action> actions = PrecomputedValue.COVERAGE_REPORT_KEY.get(env);
+    ImmutableList<ActionAnalysisMetadata> actions = PrecomputedValue.COVERAGE_REPORT_KEY.get(env);
     if (actions == null) {
       return null;
     }
 
     ImmutableSet.Builder<Artifact> outputs = new ImmutableSet.Builder<>();
 
-    for (Action action : actions) {
+    for (ActionAnalysisMetadata action : actions) {
       outputs.addAll(action.getOutputs());
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportValue.java
index 44722b5..27ace76 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/CoverageReportValue.java
@@ -16,7 +16,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
 import com.google.devtools.build.skyframe.SkyFunctionName;
@@ -34,7 +34,7 @@
   public static final ArtifactOwner ARTIFACT_OWNER = new CoverageReportKey();
 
   public CoverageReportValue(ImmutableSet<Artifact> coverageReportArtifacts,
-      ImmutableList <Action> coverageReportActions) {
+      ImmutableList <ActionAnalysisMetadata> coverageReportActions) {
     super(coverageReportActions);
     this.coverageReportArtifacts = coverageReportArtifacts;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
index 878caec..c33e599 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
@@ -18,7 +18,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.Dependency;
 import com.google.devtools.build.lib.analysis.LabelAndConfiguration;
@@ -72,14 +72,15 @@
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env)
       throws SkyFunctionException, InterruptedException {
-    ImmutableMap<Action, ConflictException> badActions = PrecomputedValue.BAD_ACTIONS.get(env);
+    ImmutableMap<ActionAnalysisMetadata, ConflictException> badActions =
+        PrecomputedValue.BAD_ACTIONS.get(env);
     ConfiguredTargetValue ctValue = (ConfiguredTargetValue)
         env.getValue(ConfiguredTargetValue.key((ConfiguredTargetKey) skyKey.argument()));
     if (env.valuesMissing()) {
       return null;
     }
 
-    for (Action action : ctValue.getActions()) {
+    for (ActionAnalysisMetadata action : ctValue.getActions()) {
       if (badActions.containsKey(action)) {
         throw new ActionConflictFunctionException(badActions.get(action));
       }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
index 0746b62..8d20b9e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
@@ -18,7 +18,7 @@
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
 import com.google.devtools.build.lib.analysis.WorkspaceStatusAction;
@@ -89,7 +89,7 @@
   static final Precomputed<WorkspaceStatusAction> WORKSPACE_STATUS_KEY =
       new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "workspace_status_action"));
 
-  static final Precomputed<ImmutableList<Action>> COVERAGE_REPORT_KEY =
+  static final Precomputed<ImmutableList<ActionAnalysisMetadata>> COVERAGE_REPORT_KEY =
       new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "coverage_report_actions"));
 
   static final Precomputed<TopLevelArtifactContext> TOP_LEVEL_CONTEXT =
@@ -101,7 +101,7 @@
   public static final Precomputed<BlazeDirectories> BLAZE_DIRECTORIES =
       new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "blaze_directories"));
 
-  static final Precomputed<ImmutableMap<Action, ConflictException>> BAD_ACTIONS =
+  static final Precomputed<ImmutableMap<ActionAnalysisMetadata, ConflictException>> BAD_ACTIONS =
       new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "bad_actions"));
 
   public static final Precomputed<PathPackageLocator> PATH_PACKAGE_LOCATOR =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
index 520cc0f..3e0f2a5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
@@ -21,6 +21,7 @@
 import com.google.common.eventbus.EventBus;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionCacheChecker;
 import com.google.devtools.build.lib.actions.ActionCacheChecker.Token;
 import com.google.devtools.build.lib.actions.ActionCompletionEvent;
@@ -126,7 +127,7 @@
   // Errors found when examining all actions in the graph are stored here, so that they can be
   // thrown when execution of the action is requested. This field is set during each call to
   // findAndStoreArtifactConflicts, and is preserved across builds otherwise.
-  private ImmutableMap<Action, ConflictException> badActionMap = ImmutableMap.of();
+  private ImmutableMap<ActionAnalysisMetadata, ConflictException> badActionMap = ImmutableMap.of();
   private boolean keepGoing;
   private boolean hadExecutionError;
   private ActionInputFileCache perBuildFileCache;
@@ -179,7 +180,7 @@
    * Return the map of mostly recently executed bad actions to their corresponding exception.
    * See {#findAndStoreArtifactConflicts()}.
    */
-  public ImmutableMap<Action, ConflictException> badActions() {
+  public ImmutableMap<ActionAnalysisMetadata, ConflictException> badActions() {
     // TODO(bazel-team): Move badActions() and findAndStoreArtifactConflicts() to SkyframeBuildView
     // now that it's done in the analysis phase.
     return badActionMap;
@@ -215,15 +216,16 @@
    */
   void findAndStoreArtifactConflicts(Iterable<ActionLookupValue> actionLookupValues)
       throws InterruptedException {
-    ConcurrentMap<Action, ConflictException> temporaryBadActionMap = new ConcurrentHashMap<>();
+    ConcurrentMap<ActionAnalysisMetadata, ConflictException> temporaryBadActionMap =
+        new ConcurrentHashMap<>();
     Pair<ActionGraph, SortedMap<PathFragment, Artifact>> result;
     result = constructActionGraphAndPathMap(actionLookupValues, temporaryBadActionMap);
     ActionGraph actionGraph = result.first;
     SortedMap<PathFragment, Artifact> artifactPathMap = result.second;
 
-    Map<Action, ArtifactPrefixConflictException> actionsWithArtifactPrefixConflict =
+    Map<ActionAnalysisMetadata, ArtifactPrefixConflictException> actionsWithArtifactPrefixConflict =
         Actions.findArtifactPrefixConflicts(actionGraph, artifactPathMap);
-    for (Map.Entry<Action, ArtifactPrefixConflictException> actionExceptionPair :
+    for (Map.Entry<ActionAnalysisMetadata, ArtifactPrefixConflictException> actionExceptionPair :
         actionsWithArtifactPrefixConflict.entrySet()) {
       temporaryBadActionMap.put(
           actionExceptionPair.getKey(), new ConflictException(actionExceptionPair.getValue()));
@@ -240,7 +242,8 @@
   private static Pair<ActionGraph, SortedMap<PathFragment, Artifact>>
       constructActionGraphAndPathMap(
           Iterable<ActionLookupValue> values,
-          ConcurrentMap<Action, ConflictException> badActionMap) throws InterruptedException {
+          ConcurrentMap<ActionAnalysisMetadata, ConflictException> badActionMap)
+      throws InterruptedException {
     MutableActionGraph actionGraph = new MapBasedActionGraph();
     ConcurrentNavigableMap<PathFragment, Artifact> artifactPathMap = new ConcurrentSkipListMap<>();
     // Action graph construction is CPU-bound.
@@ -274,14 +277,15 @@
       final List<ActionLookupValue> values,
       final MutableActionGraph actionGraph,
       final ConcurrentMap<PathFragment, Artifact> artifactPathMap,
-      final ConcurrentMap<Action, ConflictException> badActionMap) {
+      final ConcurrentMap<ActionAnalysisMetadata, ConflictException> badActionMap) {
     return new Runnable() {
       @Override
       public void run() {
         for (ActionLookupValue value : values) {
-          Set<Action> registeredActions = new HashSet<>();
-          for (Map.Entry<Artifact, Action> entry : value.getMapForConsistencyCheck().entrySet()) {
-            Action action = entry.getValue();
+          Set<ActionAnalysisMetadata> registeredActions = new HashSet<>();
+          for (Map.Entry<Artifact, ActionAnalysisMetadata> entry :
+              value.getMapForConsistencyCheck().entrySet()) {
+            ActionAnalysisMetadata action = entry.getValue();
             // We have an entry for each <action, artifact> pair. Only try to register each action
             // once.
             if (registeredActions.add(action)) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
index fc00b57..140dfbc 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
@@ -24,7 +24,7 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import com.google.common.eventbus.EventBus;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
 import com.google.devtools.build.lib.actions.ArtifactPrefixConflictException;
@@ -213,7 +213,8 @@
     } finally {
       enableAnalysis(false);
     }
-    ImmutableMap<Action, ConflictException> badActions = skyframeExecutor.findArtifactConflicts();
+    ImmutableMap<ActionAnalysisMetadata, ConflictException> badActions =
+        skyframeExecutor.findArtifactConflicts();
 
     Collection<AspectValue> goodAspects = Lists.newArrayListWithCapacity(values.size());
     NestedSetBuilder<Package> packages = NestedSetBuilder.stableOrder();
@@ -256,7 +257,7 @@
     // TODO(bazel-team): We might want to report the other errors through the event bus but
     // for keeping this code in parity with legacy we just report the first error for now.
     if (!keepGoing) {
-      for (Map.Entry<Action, ConflictException> bad : badActions.entrySet()) {
+      for (Map.Entry<ActionAnalysisMetadata, ConflictException> bad : badActions.entrySet()) {
         ConflictException ex = bad.getValue();
         try {
           ex.rethrowTyped();
@@ -339,7 +340,7 @@
     }
 
     Collection<Exception> reportedExceptions = Sets.newHashSet();
-    for (Map.Entry<Action, ConflictException> bad : badActions.entrySet()) {
+    for (Map.Entry<ActionAnalysisMetadata, ConflictException> bad : badActions.entrySet()) {
       ConflictException ex = bad.getValue();
       try {
         ex.rethrowTyped();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index 25bfc92..beea6b5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -33,7 +33,7 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.Range;
 import com.google.common.eventbus.EventBus;
-import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.ActionCacheChecker;
 import com.google.devtools.build.lib.actions.ActionExecutionContextFactory;
 import com.google.devtools.build.lib.actions.ActionExecutionStatusReporter;
@@ -634,7 +634,7 @@
             artifactFactory.get(), WorkspaceStatusValue.ARTIFACT_OWNER, buildId));
   }
 
-  public void injectCoverageReportData(ImmutableList<Action> actions) {
+  public void injectCoverageReportData(ImmutableList<ActionAnalysisMetadata> actions) {
     PrecomputedValue.COVERAGE_REPORT_KEY.set(injectable(), actions);
   }
 
@@ -1037,8 +1037,8 @@
    * {@link SkyframeActionExecutor#findAndStoreArtifactConflicts} to do the work, since any
    * conflicts found will only be reported during execution.
    */
-  ImmutableMap<Action, SkyframeActionExecutor.ConflictException> findArtifactConflicts()
-      throws InterruptedException {
+  ImmutableMap<ActionAnalysisMetadata, SkyframeActionExecutor.ConflictException>
+      findArtifactConflicts() throws InterruptedException {
     if (skyframeBuildView.isSomeConfiguredTargetEvaluated()
         || skyframeBuildView.isSomeConfiguredTargetInvalidated()) {
       // This operation is somewhat expensive, so we only do it if the graph might have changed in
@@ -1384,7 +1384,7 @@
    */
   public EvaluationResult<PostConfiguredTargetValue> postConfigureTargets(
       EventHandler eventHandler, List<ConfiguredTargetKey> values, boolean keepGoing,
-      ImmutableMap<Action, SkyframeActionExecutor.ConflictException> badActions)
+      ImmutableMap<ActionAnalysisMetadata, SkyframeActionExecutor.ConflictException> badActions)
           throws InterruptedException {
     checkActive();
     PrecomputedValue.BAD_ACTIONS.set(injectable(), badActions);
@@ -1464,7 +1464,7 @@
   /**
    * Returns the generating action of a given artifact ({@code null} if it's a source artifact).
    */
-  private Action getGeneratingAction(EventHandler eventHandler, Artifact artifact)
+  private ActionAnalysisMetadata getGeneratingAction(EventHandler eventHandler, Artifact artifact)
       throws InterruptedException {
     if (artifact.isSourceArtifact()) {
       return null;
@@ -1498,11 +1498,11 @@
   public ActionGraph getActionGraph(final EventHandler eventHandler) {
     return new ActionGraph() {
       @Override
-      public Action getGeneratingAction(final Artifact artifact) {
+      public ActionAnalysisMetadata getGeneratingAction(final Artifact artifact) {
         try {
-          return callUninterruptibly(new Callable<Action>() {
+          return callUninterruptibly(new Callable<ActionAnalysisMetadata>() {
             @Override
-            public Action call() throws InterruptedException {
+            public ActionAnalysisMetadata call() throws InterruptedException {
               return SkyframeExecutor.this.getGeneratingAction(eventHandler, artifact);
             }
           });