Merge "Merge branch 'stable-3.3'"
diff --git a/.zuul.yaml b/.zuul.yaml
index 118ec6a..27c8491 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -7,6 +7,15 @@
         bazelisk_test_targets: "plugins/task/lint_test plugins/task/..."
 
 - project:
+    description: |
+      Build the plugin in check, and also build and publish it after
+      every merged commit.
     check:
       jobs:
         - plugins-task-build
+    post:
+      jobs:
+        - plugins-task-build
+        - gerrit-plugin-publish:
+            dependencies:
+              - plugins-task-build
diff --git a/BUILD b/BUILD
index ea5fe6f..0b04753 100644
--- a/BUILD
+++ b/BUILD
@@ -28,7 +28,7 @@
     size = "medium",
     srcs = ["test/docker/run.sh"],
     args = ["--task-plugin-jar", "$(location :task)"],
-    data = [plugin_name] + glob(["test/**"]),
+    data = [plugin_name] + glob(["test/**"]) + glob(["src/main/resources/Documentation/*"]),
     local = True,
 )
 
diff --git a/src/main/java/com/google/gerrit/common/Container.java b/src/main/java/com/google/gerrit/common/Container.java
index eb0a0f6..6e11534 100644
--- a/src/main/java/com/google/gerrit/common/Container.java
+++ b/src/main/java/com/google/gerrit/common/Container.java
@@ -55,4 +55,21 @@
     }
     return Objects.hash(values);
   }
+
+  @Override
+  public String toString() {
+    List<String> fieldStrings = new ArrayList<>();
+    try {
+      for (Field field : getClass().getDeclaredFields()) {
+        field.setAccessible(true);
+        fieldStrings.add(field.getName() + ": " + Objects.toString(field.get(this)));
+      }
+    } catch (IllegalArgumentException | IllegalAccessException e) {
+    }
+    String fields = String.join(", ", fieldStrings);
+    if (!"".equals(fields)) {
+      fields = "{" + fields + "}";
+    }
+    return getClass().toString() + fields;
+  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java b/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
index f01d74d..3a8d903 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
@@ -59,7 +59,7 @@
     public boolean onlyInvalid = false;
 
     @Option(name = "--evaluation-time", usage = "Include elapsed evaluation time on each task")
-    boolean evaluationTime = false;
+    public boolean evaluationTime = false;
 
     @Option(
         name = "--preview",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
index 93923e1..7896417 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
@@ -59,7 +59,7 @@
     if ("true".equalsIgnoreCase(query)) {
       return true;
     }
-    return cqb.parse(query).asMatchable().match(c);
+    return getPredicate(query).asMatchable().match(c);
   }
 
   protected Predicate<ChangeData> getPredicate(String query) throws QueryParseException {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
index b8bf285..028762c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
@@ -32,30 +32,42 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-/** Use to expand properties like ${_name} for a Task Definition. */
+/** Use to expand properties like ${_name} in the text of various definitions. */
 public class Properties {
-  public Properties(ChangeData changeData, Task definition, Map<String, String> parentProperties)
-      throws StorageException {
-    Map<String, String> expanded = new HashMap<>(parentProperties);
-    expanded.putAll(getInternalProperties(definition, changeData));
-    Map<String, String> unexpanded = definition.properties;
-    unexpanded.putAll(definition.exported);
-    new RecursiveExpander(expanded).expand(unexpanded);
+  /** Use to expand properties specifically for Tasks. */
+  public static class Task extends Expander {
+    public static final Task EMPTY_PARENT = new Task();
 
-    definition.properties = expanded;
-    for (String property : definition.exported.keySet()) {
-      definition.exported.put(property, expanded.get(property));
+    public Task() {
+      super(Collections.emptyMap());
     }
 
-    new Expander(expanded).expandFieldValues(definition, Collections.emptySet());
+    public Task(ChangeData changeData, TaskConfig.Task definition, Task parentProperties)
+        throws StorageException {
+      super(parentProperties.forDescendants());
+      valueByName.putAll(getInternalProperties(definition, changeData));
+      new RecursiveExpander(valueByName).expand(definition.getAllProperties());
+
+      definition.setExpandedProperties(valueByName);
+
+      expandFieldValues(definition, Collections.emptySet());
+    }
+
+    protected Map<String, String> forDescendants() {
+      return new HashMap<>(valueByName);
+    }
   }
 
-  public Properties(NamesFactory namesFactory, Map<String, String> properties) {
-    new Expander(properties).expandFieldValues(namesFactory, Sets.newHashSet(TaskConfig.KEY_TYPE));
+  /** Use to expand properties specifically for NamesFactories. */
+  public static class NamesFactory extends Expander {
+    public NamesFactory(TaskConfig.NamesFactory namesFactory, Task properties) {
+      super(properties.valueByName);
+      expandFieldValues(namesFactory, Sets.newHashSet(TaskConfig.KEY_TYPE));
+    }
   }
 
-  protected static Map<String, String> getInternalProperties(Task definition, ChangeData changeData)
-      throws StorageException {
+  protected static Map<String, String> getInternalProperties(
+      TaskConfig.Task definition, ChangeData changeData) throws StorageException {
     Map<String, String> properties = new HashMap<>();
 
     properties.put("_name", definition.name);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
index 77adee2..5e987ca 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
@@ -14,6 +14,7 @@
 
 package com.googlesource.gerrit.plugins.task;
 
+import com.google.common.primitives.Primitives;
 import com.google.gerrit.common.Container;
 import com.google.gerrit.entities.BranchNameKey;
 import com.google.gerrit.server.git.meta.AbstractVersionedMetaData;
@@ -43,7 +44,7 @@
     }
   }
 
-  private class Section extends Container {
+  protected class Section extends Container {
     public TaskConfig config;
 
     public Section() {
@@ -57,7 +58,6 @@
     public String fail;
     public String failHint;
     public String inProgress;
-    public String name;
     public String pass;
     public String preloadTask;
     public Map<String, String> properties;
@@ -78,7 +78,6 @@
       fail = getString(s, KEY_FAIL, null);
       failHint = getString(s, KEY_FAIL_HINT, null);
       inProgress = getString(s, KEY_IN_PROGRESS, null);
-      name = s.subSection;
       pass = getString(s, KEY_PASS, null);
       preloadTask = getString(s, KEY_PRELOAD_TASK, null);
       properties = getProperties(s, KEY_PROPERTIES_PREFIX);
@@ -90,15 +89,41 @@
     }
 
     protected TaskBase(TaskBase base) {
-      for (Field field : TaskBase.class.getDeclaredFields()) {
+      copyDeclaredFields(TaskBase.class, base);
+    }
+
+    protected <T> void copyDeclaredFields(Class<T> cls, T from) {
+      for (Field field : cls.getDeclaredFields()) {
         try {
           field.setAccessible(true);
-          field.set(this, field.get(base));
+          Class<?> fieldCls = field.getType();
+          Object val = field.get(from);
+          if (field.getType().isPrimitive()
+              || Primitives.isWrapperType(fieldCls)
+              || (val instanceof String)
+              || val == null) {
+            field.set(this, val);
+          } else if (val instanceof List) {
+            List<?> list = List.class.cast(val);
+            field.set(this, new ArrayList<>(list));
+          } else if (val instanceof Map) {
+            Map<?, ?> map = Map.class.cast(val);
+            field.set(this, new HashMap<>(map));
+          } else if (field.getName().equals("this$0")) { // Don't copy internal final field
+          } else {
+            throw new RuntimeException(
+                "Don't know how to deep copy " + fieldValueToString(field, val));
+          }
         } catch (IllegalAccessException e) {
-          throw new RuntimeException(e);
+          throw new RuntimeException(
+              "Cannot access field to copy it " + fieldValueToString(field, "unknown"));
         }
       }
     }
+
+    protected String fieldValueToString(Field field, Object val) {
+      return "field:" + field.getName() + " value:" + val + " type:" + field.getType();
+    }
   }
 
   public class Task extends TaskBase {
@@ -106,12 +131,26 @@
 
     public Task(SubSection s, boolean isVisible, boolean isTrusted) {
       super(s, isVisible, isTrusted);
-      name = getString(s, KEY_NAME, s.subSection);
+      name = s.subSection;
     }
 
     protected Task(TaskBase base) {
       super(base);
     }
+
+    protected Map<String, String> getAllProperties() {
+      Map<String, String> all = new HashMap<>(properties);
+      all.putAll(exported);
+      return all;
+    }
+
+    protected void setExpandedProperties(Map<String, String> expanded) {
+      properties.clear();
+      properties.putAll(expanded);
+      for (String property : exported.keySet()) {
+        exported.put(property, properties.get(property));
+      }
+    }
   }
 
   public class TasksFactory extends TaskBase {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
index 461d14e..9c4b476 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
@@ -40,12 +40,11 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
+import java.util.function.BiFunction;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 
 /**
@@ -94,11 +93,19 @@
     return root.getRootNodes();
   }
 
+  public Node createNodeOrNull(NodeList parent, Task definition) {
+    try {
+      return new Node(parent, definition);
+    } catch (Exception e) {
+      return null;
+    }
+  }
+
   protected class NodeList {
+    protected NodeList parent = null;
     protected LinkedList<String> path = new LinkedList<>();
     protected List<Node> nodes;
     protected Set<String> names = new HashSet<>();
-    protected Map<String, String> properties;
 
     protected void addSubDefinitions(List<Task> defs) {
       for (Task def : defs) {
@@ -107,28 +114,29 @@
     }
 
     protected void addSubDefinition(Task def) {
+      addSubDefinition(def, (d, c) -> createNodeOrNull(d, c));
+    }
+
+    protected void addSubDefinition(Task def, BiFunction<NodeList, Task, Node> nodeConstructor) {
       Node node = null;
       if (def != null && !path.contains(def.name) && names.add(def.name)) {
         // path check above detects looping definitions
         // names check above detects duplicate subtasks
-        try {
-          node = new Node(def, path, properties);
-        } catch (Exception e) {
-        } // bad definition, handled with null
+        node = nodeConstructor.apply(this, def);
       }
       nodes.add(node);
     }
 
     public ChangeData getChangeData() {
-      return TaskTree.this.changeData;
+      return parent == null ? TaskTree.this.changeData : parent.getChangeData();
+    }
+
+    protected Properties.Task getProperties() {
+      return Properties.Task.EMPTY_PARENT;
     }
   }
 
   protected class Root extends NodeList {
-    protected Root() {
-      properties = new HashMap<String, String>();
-    }
-
     public List<Node> getRootNodes() throws ConfigInvalidException, IOException {
       if (nodes == null) {
         nodes = new ArrayList<>();
@@ -144,15 +152,15 @@
 
   public class Node extends NodeList {
     public final Task task;
+    protected final Properties.Task properties;
 
-    public Node(Task definition, List<String> path, Map<String, String> parentProperties)
-        throws ConfigInvalidException, StorageException {
+    public Node(NodeList parent, Task definition) throws ConfigInvalidException, StorageException {
+      this.parent = parent;
       this.task = definition;
-      this.path.addAll(path);
+      this.path.addAll(parent.path);
       this.path.add(definition.name);
       Preloader.preload(definition);
-      new Properties(getChangeData(), definition, parentProperties);
-      properties = definition.properties;
+      properties = new Properties.Task(getChangeData(), definition, parent.getProperties());
     }
 
     public List<Node> getSubNodes() {
@@ -209,13 +217,12 @@
     }
 
     protected void addSubTasksFactoryDefinitions() throws StorageException {
-      List<Task> taskList = new ArrayList<>();
       for (String taskFactoryName : task.subTasksFactories) {
         TasksFactory tasksFactory = task.config.getTasksFactory(taskFactoryName);
         if (tasksFactory != null) {
           NamesFactory namesFactory = task.config.getNamesFactory(tasksFactory.namesFactory);
           if (namesFactory != null && namesFactory.type != null) {
-            new Properties(namesFactory, task.properties);
+            new Properties.NamesFactory(namesFactory, getProperties());
             switch (NamesFactoryType.getNamesFactoryType(namesFactory.type)) {
               case STATIC:
                 addStaticTypeTasksDefinitions(tasksFactory, namesFactory);
@@ -247,7 +254,9 @@
                   .query(changeQueryBuilderProvider.get().parse(namesFactory.changes))
                   .entities();
           for (ChangeData changeData : changeDataList) {
-            addSubDefinition(task.config.createTask(tasksFactory, changeData.getId().toString()));
+            addSubDefinition(
+                task.config.createTask(tasksFactory, changeData.getId().toString()),
+                new ChangeNodeFactory(changeData)::createChangeNodeOrNull);
           }
           return;
         }
@@ -270,6 +279,11 @@
           .getTasks();
     }
 
+    @Override
+    protected Properties.Task getProperties() {
+      return properties;
+    }
+
     protected String resolveTaskFileName(String file) throws ConfigInvalidException {
       if (file == null) {
         throw new ConfigInvalidException("External file not defined");
@@ -295,4 +309,30 @@
       return BranchNameKey.create(allUsers.get(), RefNames.refsUsers(acct));
     }
   }
+
+  public class ChangeNodeFactory {
+    public class ChangeNode extends Node {
+      public ChangeNode(NodeList parent, Task definition) throws ConfigInvalidException {
+        super(parent, definition);
+      }
+
+      public ChangeData getChangeData() {
+        return ChangeNodeFactory.this.changeData;
+      }
+    }
+
+    protected ChangeData changeData;
+
+    public ChangeNodeFactory(ChangeData changeData) {
+      this.changeData = changeData;
+    }
+
+    public ChangeNode createChangeNodeOrNull(NodeList parent, Task definition) {
+      try {
+        return new ChangeNode(parent, definition);
+      } catch (Exception e) {
+        return null;
+      }
+    }
+  }
 }
diff --git a/src/main/resources/Documentation/task.md b/src/main/resources/Documentation/task.md
index 8c1309e..fa5e834 100644
--- a/src/main/resources/Documentation/task.md
+++ b/src/main/resources/Documentation/task.md
@@ -430,13 +430,18 @@
     set-<property-name> = <property-value>
 ```
 
-Subtasks inherit all custom properties from their parents. A task is invalid
-if it attempts to override an already set property.
+Subtasks inherit all custom properties from their parents, however
+subtasks may override inherrited properties and give them new values.
 
 Example:
 ```
     [task "foo-project"]
         set-project-name = foo
+        subtask = sub-project
+        subtask = common-to-many-projects
+
+    [task "sub-project"]
+        set-project-name = sub-foo # Overrides value from 'foo-project'
         subtask = common-to-many-projects
 
     [task "common-to-many-projects"]
@@ -530,5 +535,8 @@
 
 Examples
 --------
-See [task_states](task_states.html) for a comprehensive list of examples
+See [task_states](test/task_states.html) for a comprehensive list of examples
 of task configs and their states.
+
+See what the results will look when [previewing](test/preview.html) a change
+to those states.
diff --git a/src/main/resources/Documentation/task_states.md b/src/main/resources/Documentation/task_states.md
deleted file mode 100644
index 8b0c705..0000000
--- a/src/main/resources/Documentation/task_states.md
+++ /dev/null
@@ -1,1189 +0,0 @@
-@PLUGIN@ States
-===============
-
-Below are sample config files which illustrate many examples of how task
-states are affected by their own criteria and their subtasks' states.
-
-`task.config` file in project `All-Project` on ref `refs/meta/config`.
-
-```
-[root "Root N/A"]
-  applicable = is:closed # Assumes test query is "is:open"
-
-[root "Root APPLICABLE"]
-  applicable = is:open # Assumes test query is "is:open"
-  pass = True
-  subtask = Subtask APPLICABLE
-
-[root "Root PASS"]
-  pass = True
-
-[root "Root FAIL"]
-  fail = True
-
-[root "Root straight PASS"]
-  applicable = is:open
-  pass = is:open
-
-[root "Root straight FAIL"]
-  applicable = is:open
-  fail = is:open
-  pass = is:open
-
-[root "Root PASS-fail"]
-  applicable = is:open
-  fail = NOT is:open
-
-[root "Root pass-FAIL"]
-  applicable = is:open
-  fail = is:open
-
-[root "Root PASS-waiting-fail"]
-  applicable = is:open
-  fail = NOT is:open
-  subtask = Subtask PASS
-
-[root "Root pass-WAITING-fail"]
-  applicable = is:open
-  fail = NOT is:open
-  subtask = Subtask FAIL
-
-[root "Root pass-waiting-FAIL"]
-  applicable = is:open
-  fail = is:open
-  subtask = Subtask PASS
-
-[root "Root grouping PASS (subtask PASS)"]
-  subtask = Subtask PASS
-
-[root "Root grouping WAITING (subtask READY)"]
-  subtask = Subtask READY
-
-[root "Root grouping WAITING (subtask FAIL)"]
-  subtask = Subtask FAIL
-
-[root "Root grouping NA (subtask NA)"]
-  applicable = is:open # Assumes Subtask NA has "applicable = NOT is:open"
-  subtask = Subtask NA
-
-[root "Root READY (subtask PASS)"]
-  applicable = is:open
-  pass = NOT is:open
-  subtask = Subtask PASS
-  ready-hint = You must now run the ready task
-
-[root "Root WAITING (subtask READY)"]
-  applicable = is:open
-  pass = is:open
-  subtask = Subtask READY
-
-[root "Root WAITING (subtask FAIL)"]
-  applicable = is:open
-  pass = is:open
-  subtask = Subtask FAIL
-
-[root "Root IN PROGRESS"]
-   applicable = is:open
-   in-progress = is:open
-   pass = NOT is:open
-
-[root "Root NOT IN PROGRESS"]
-   applicable = is:open
-   in-progress = NOT is:open
-   pass = NOT is:open
-
-[root "Root Optional subtasks"]
-   subtask = OPTIONAL MISSING |
-   subtask = Subtask Optional |
-
-[root "Subtasks File"]
-  subtasks-file = common.config
-
-[root "Subtasks File (Missing)"]
-  subtasks-file = common.config
-  subtasks-file = missing
-
-[root "Subtasks External"]
-  subtasks-external = user special
-
-[root "Subtasks External (Missing)"]
-  subtasks-external = user special
-  subtasks-external = missing
-
-[root "Subtasks External (User Missing)"]
-  subtasks-external = user special
-  subtasks-external = user missing
-
-[root "Subtasks External (File Missing)"]
-  subtasks-external = user special
-  subtasks-external = file missing
-
-[root "Root tasks-factory"]
-  subtasks-factory = tasks-factory static
-  subtasks-factory = tasks-factory change
-
-[root "Root tasks-factory static (empty name)"]
-  subtasks-factory = tasks-factory static (empty name)
-# Grouping task since it has no pass criteria, not output since it has no subtasks
-
-[root "Root tasks-factory static (empty name PASS)"]
-  pass = True
-  subtasks-factory = tasks-factory static (empty name)
-
-[root "Root Properties"]
-  set-root-property = root-value
-  export-root = ${_name}
-  fail = True
-  fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
-  subtask = Subtask Properties
-
-[root "Root Preload"]
-   preload-task = Subtask FAIL
-   subtask = Subtask Preload
-
-[root "Root INVALID Preload"]
-  preload-task = missing
-
-[root "INVALIDS"]
-  subtasks-file = invalids.config
-
-[root "Root NA Pass"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  pass = True
-
-[root "Root NA Fail"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  fail = True
-
-[root "NA INVALIDS"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  subtasks-file = invalids.config
-
-[tasks-factory "tasks-factory static"]
-  names-factory = names-factory static list
-  fail = True
-
-[tasks-factory "tasks-factory static (empty name)"]
-  names-factory = names-factory static (empty name list)
-  fail = True
-
-[tasks-factory "tasks-factory change"]
-  names-factory = names-factory change list
-  fail = True
-
-[task "Subtask APPLICABLE"]
-  applicable = is:open
-  pass = True
-
-[task "Subtask FAIL"]
-  applicable = is:open
-  fail = is:open
-  pass = is:open
-
-[task "Subtask READY"]
-  applicable = is:open
-  pass = NOT is:open
-  subtask = Subtask PASS
-
-[task "Subtask PASS"]
-  applicable = is:open
-  pass = is:open
-
-[task "Subtask Optional"]
-   subtask = Subtask PASS |
-   subtask = OPTIONAL MISSING | Subtask FAIL
-   subtask = OPTIONAL MISSING | OPTIONAL MISSING |
-   subtask = OPTIONAL MISSING | OPTIONAL MISSING | Subtask READY
-
-[task "Subtask NA"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-
-[task "Subtask Properties"]
-  export-subtask = ${_name}
-  subtask = Subtask Properties Hints
-  subtask = Chained ${_name}
-  subtask = Subtask Properties Reset
-  subtasks-factory = TaskFactory Properties Hints
-
-[task "Subtask Properties Hints"]
-  set-first-property = first-value
-  set-second-property = ${first-property} second-extra ${third-property}
-  set-third-property = third-value
-  fail = True
-  fail-hint = Name(${_name}) root-property(${root-property}) first-property(${first-property}) second-property(${second-property}) root(${root})
-
-[task "Chained Subtask Properties"]
-  pass = True
-
-[task "Subtask Properties Reset"]
-  pass = True
-  set-first-property = reset-first-value
-  fail-hint = first-property(${first-property})
-
-[tasks-factory "TaskFactory Properties Hints"]
-  names-factory = NamesFactory Properties
-  fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
-  fail = True
-
-[names-factory "NamesFactory Properties"]
-  type = change
-  changes = change:_change1_number OR change:${_change_number} project:${_change_project} branch:${_change_branch}
-
-[task "Subtask Preload"]
-  preload-task = Subtask READY
-  subtask = Subtask Preload Preload
-  subtask = Subtask Preload Hints PASS
-  subtask = Subtask Preload Hints FAIL
-  subtask = Subtask Preload Override Pass
-  subtask = Subtask Preload Override Fail
-  subtask = Subtask Preload Extend Subtasks
-  subtask = Subtask Preload Optional
-  subtask = Subtask Preload Properties
-
-[task "Subtask Preload Preload"]
-  preload-task = Subtask Preload with Preload
-
-[task "Subtask Preload with Preload"]
-  preload-task = Subtask PASS
-
-[task "Subtask Preload Hints PASS"]
-  preload-task = Subtask Hints
-  pass = False
-
-[task "Subtask Preload Hints FAIL"]
-  preload-task = Subtask Hints
-  fail = True
-
-[task "Subtask Preload Override Pass"]
-  preload-task = Subtask PASS
-  pass = False
-
-[task "Subtask Preload Override Fail"]
-  preload-task = Subtask FAIL
-  fail = False
-
-[task "Subtask Preload Extend Subtasks"]
-  preload-task = Subtask READY
-  subtask = Subtask APPLICABLE
-
-[task "Subtask Preload Optional"]
-  preload-task = Missing | Subtask PASS
-
-[task "Subtask Preload Properties"]
-  preload-task = Subtask Properties Hints
-  set-fourth-property = fourth-value
-  fail-hint = second-property(${second-property}) fourth-property(${fourth-property})
-
-[task "Subtask Hints"] # meant to be preloaded, not a test case in itself
-  ready-hint = Task is ready
-  fail-hint = Task failed
-
-[external "user special"]
-  user = testuser
-  file = special.config
-
-[external "user missing"]
-  user = missing
-  file = special.config
-
-[external "file missing"]
-  user = testuser
-  file = missing
-
-[names-factory "names-factory static list"]
-  name = my a task
-  name = my b task
-  name = my c task
-  name = my d task Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
-  type = static
-
-[names-factory "names-factory static (empty name list)"]
-  type = static
-
-[names-factory "names-factory change list"]
-  changes = change:_change1_number OR change:_change2_number
-  type = change
-
-```
-
-`task/common.config` file in project `All-Projects` on ref `refs/meta/config`.
-
-```
-[task "file task/common.config PASS"]
-  applicable = is:open
-  pass = is:open
-
-[task "file task/common.config FAIL"]
-  applicable = is:open
-  fail = is:open
-```
-
-`task/invalids.config` file in project `All-Projects` on ref `refs/meta/config`.
-
-```
-[task "No PASS criteria"]
-  fail-hint = Invalid without Pass criteria and without subtasks
-
-[task "WAITING (subtask INVALID)"]
-  pass = is:open
-  subtask = Subtask INVALID
-
-[task "WAITING (subtask duplicate)"]
-  subtask = Subtask INVALID
-  subtask = Subtask INVALID
-
-[task "WAITING (subtask missing)"]
-  pass = is:open
-  subtask = MISSING # security bug: subtask name appears in output
-
-[task "Grouping WAITING (subtask INVALID)"]
-  subtask = Subtask INVALID
-
-[task "Grouping WAITING (subtask missing)"]
-  subtask = MISSING  # security bug: subtask name appears in output
-
-[task "Subtask INVALID"]
-  fail-hint = Use when an INVALID subtask is needed, not meant as a test case in itself
-
-[task "Subtask Optional"]
-   subtask = MISSING | MISSING
-
-[task "NA Bad PASS query"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  fail = True
-  pass = has:bad
-
-[task "NA Bad FAIL query"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  pass = True
-  fail = has:bad
-
-[task "NA Bad INPROGRESS query"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  fail = True
-  in-progress = has:bad
-
-[task "Looping"]
-  subtask = Looping
-
-[task "Looping Properties"]
-  set-A = ${B}
-  set-B = ${A}
-  fail = True
-
-[task "task (tasks-factory missing)"]
-  subtasks-factory = missing
-
-[task "task (names-factory type missing)"]
-  subtasks-factory = tasks-factory (names-factory type missing)
-
-[task "task (names-factory type INVALID)"]
-  subtasks-factory = tasks-factory (names-factory type INVALID)
-
-[task "task (names-factory duplicate)"]
-  subtasks-factory = tasks-factory (names-factory duplicate)
-
-[task "task (names-factory changes type missing)"]
-  subtasks-factory = tasks-factory change (names-factory type missing)
-
-[task "task (names-factory changes missing)"]
-  subtasks-factory = tasks-factory change (names-factory changes missing)
-
-[task "task (names-factory changes invalid)"]
-  subtasks-factory = tasks-factory change (names-factory changes invalid)
-
-[task "task (tasks-factory changes loop)"]
-  subtasks-factory = tasks-factory change loop
-
-[tasks-factory "tasks-factory (names-factory type missing)"]
-  names-factory = names-factory (type missing)
-  fail = True
-
-[tasks-factory "tasks-factory (names-factory type INVALID)"]
-  names-factory = name-factory (type INVALID)
-
-[tasks-factory "tasks-factory (names-factory duplicate)"]
-  names-factory = names-factory duplicate
-  fail = True
-
-[tasks-factory "tasks-factory change (names-factory type missing)"]
-  names-factory = names-factory change list (type missing)
-  fail = True
-
-[tasks-factory "tasks-factory change (names-factory changes missing)"]
-  names-factory = names-factory change list (changes missing)
-  fail = True
-
-[tasks-factory "tasks-factory change (names-factory changes invalid)"]
-  names-factory = names-factory change list (changes invalid)
-  fail = True
-
-[tasks-factory "tasks-factory change loop"]
-  names-factory = names-factory change constant
-  subtask = task (tasks-factory changes loop)
-  fail = true
-
-[names-factory "names-factory (type missing)"]
-  name = no type test
-
-[names-factory "names-factory change list (type missing)"]
-  changes = change:_change1_number OR change:_change2_number
-
-[names-factory "names-factory (type INVALID)"]
-  name = invalid type test
-  type = invalid
-
-[names-factory "names-factory duplicate"]
-  name = duplicate
-  name = duplicate
-  type = static
-
-[names-factory "names-factory change list (changes missing)"]
-  type = change
-
-[names-factory "names-factory change list (changes invalid)"]
-  change = change:invalidChange
-  type = change
-
-[names-factory "names-factory change constant"]
-  changes = change:_change1_number OR change:_change2_number
-  type = change
-
-```
-
-`task/special.config` file in project `All-Users` on ref `refs/users/self`.
-
-```
-[task "userfile task/special.config PASS"]
-  applicable = is:open
-  pass = is:open
-
-[task "userfile task/special.config FAIL"]
-  applicable = is:open
-  fail = is:open
-```
-
-The expected output for the above task config looks like:
-
-```
- $  ssh -x -p 29418 review-example gerrit query is:open \
-     --task--applicable --format json|head -1 |json_pp
-{
-   ...,
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "hasPass" : true,
-               "name" : "Root APPLICABLE",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask APPLICABLE",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root PASS",
-               "status" : "PASS"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root straight PASS",
-               "status" : "PASS"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root straight FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root PASS-fail",
-               "status" : "PASS"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root pass-FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root PASS-waiting-fail",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root pass-WAITING-fail",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root pass-waiting-FAIL",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root grouping PASS (subtask PASS)",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "hint" : "You must now run the ready task",
-               "name" : "Root READY (subtask PASS)",
-               "status" : "READY",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "inProgress" : true,
-               "name" : "Root IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "hasPass" : true,
-               "inProgress" : false,
-               "name" : "Root NOT IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root Optional subtasks",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask READY",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks File",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks File (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (File Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root tasks-factory",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "my a task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "my b task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "my c task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "my d task Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "_change1_number",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "_change2_number",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root tasks-factory static (empty name PASS)",
-               "status" : "PASS"
-            },
-            {
-               "exported" : {
-                  "root" : "Root Properties"
-               },
-               "hasPass" : true,
-               "hint" : "Name(Root Properties) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-               "name" : "Root Properties",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "exported" : {
-                        "subtask" : "Subtask Properties"
-                     },
-                     "hasPass" : false,
-                     "name" : "Subtask Properties",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
-                           "name" : "Subtask Properties Hints",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Chained Subtask Properties",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Properties Reset",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Name(_change3_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change3_number",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Name(_change1_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change1_number",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root Preload",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask Preload",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Preload",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Task is ready",
-                           "name" : "Subtask Preload Hints PASS",
-                           "status" : "READY"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Task failed",
-                           "name" : "Subtask Preload Hints FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Pass",
-                           "status" : "READY"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Fail",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Extend Subtasks",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              },
-                              {
-                                 "hasPass" : true,
-                                 "name" : "Subtask APPLICABLE",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Optional",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
-                           "name" : "Subtask Preload Properties",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
-   ...
-```
diff --git a/src/main/resources/Documentation/test/preview.md b/src/main/resources/Documentation/test/preview.md
new file mode 100644
index 0000000..e53b7d8
--- /dev/null
+++ b/src/main/resources/Documentation/test/preview.md
@@ -0,0 +1,603 @@
+[root "INVALIDS Preview"]
+  subtasks-file = invalids.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "INVALIDS Preview",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root PASS Preview"]
+  pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS Preview",
+   "status" : "PASS"
+}
+
+[root "Root READY (subtask PASS) Preview"]
+  applicable = is:open
+  pass = NOT is:open
+  subtask = Subtask PASS Preview
+  ready-hint = You must now run the ready task
+
+[task "Subtask PASS Preview"]
+  applicable = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "hint" : "You must now run the ready task",
+   "name" : "Root READY (subtask PASS) Preview",
+   "status" : "READY",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS Preview",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Subtasks External Preview"]
+  subtasks-external = user special Preview
+
+[external "user special Preview"]
+  user = testuser
+  file = special.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External Preview",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root NA Pass Preview"]
+  applicable = NOT is:open
+  pass = True
+
+{
+   "applicable" : false,
+   "hasPass" : true,
+   "name" : "Root NA Pass Preview",
+   "status" : "PASS"
+}
+
+[root "NA INVALIDS Preview"]
+  applicable = NOT is:open
+  subtasks-file = invalids.config
+
+{
+   "applicable" : false,
+   "hasPass" : false,
+   "name" : "NA INVALIDS Preview",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
diff --git a/src/main/resources/Documentation/test/task_states.md b/src/main/resources/Documentation/test/task_states.md
new file mode 100644
index 0000000..ea09541
--- /dev/null
+++ b/src/main/resources/Documentation/test/task_states.md
@@ -0,0 +1,2093 @@
+@PLUGIN@ States
+===============
+
+Below are sample config files which illustrate many examples of how task
+states are affected by their own criteria and their subtasks' states.
+To better help visualize the output that each `root` example leads to,
+the json output for the root definition (and any definitions that it
+refers to) will be placed inline right after the root. Naturally, this
+json is not a part of the config, however it is part of the expected
+output for task config when running the following:
+
+```
+ $  ssh -x -p 29418 review-example gerrit query is:open \
+     --task--all --format json|head -1 |json_pp
+```
+
+The config below is expected to be in the `task.config` file in project
+`All-Projects` on ref `refs/meta/config`.
+
+```
+[root "Root N/A"]
+  applicable = is:closed # Assumes test query is "is:open"
+
+{
+   "applicable" : false,
+   "hasPass" : false,
+   "name" : "Root N/A",
+   "status" : "INVALID"
+}
+
+[root "Root APPLICABLE"]
+  applicable = is:open # Assumes test query is "is:open"
+  pass = True
+  subtask = Subtask APPLICABLE
+
+[task "Subtask APPLICABLE"]
+  applicable = is:open
+  pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root APPLICABLE",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask APPLICABLE",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root PASS"]
+  pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS",
+   "status" : "PASS"
+}
+
+[root "Root FAIL"]
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root FAIL",
+   "status" : "FAIL"
+}
+
+[root "Root straight PASS"]
+  applicable = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root straight PASS",
+   "status" : "PASS"
+}
+
+[root "Root straight FAIL"]
+  applicable = is:open
+  fail = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root straight FAIL",
+   "status" : "FAIL"
+}
+
+[root "Root PASS-fail"]
+  applicable = is:open
+  fail = NOT is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS-fail",
+   "status" : "PASS"
+}
+
+[root "Root pass-FAIL"]
+  applicable = is:open
+  fail = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root pass-FAIL",
+   "status" : "FAIL"
+}
+
+[root "Root PASS-waiting-fail"]
+  applicable = is:open
+  fail = NOT is:open
+  subtask = Subtask PASS
+
+[task "Subtask PASS"]
+  applicable = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS-waiting-fail",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root pass-WAITING-fail"]
+  applicable = is:open
+  fail = NOT is:open
+  subtask = Subtask FAIL
+
+[task "Subtask FAIL"]
+  applicable = is:open
+  fail = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root pass-WAITING-fail",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root pass-waiting-FAIL"]
+  applicable = is:open
+  fail = is:open
+  subtask = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root pass-waiting-FAIL",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root grouping PASS (subtask PASS)"]
+  subtask = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping PASS (subtask PASS)",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root grouping WAITING (subtask READY)"]
+  subtask = Subtask READY
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping WAITING (subtask READY)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask READY",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root grouping WAITING (subtask FAIL)"]
+  subtask = Subtask FAIL
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping WAITING (subtask FAIL)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root grouping NA (subtask NA)"]
+  applicable = is:open # Assumes Subtask NA has "applicable = NOT is:open"
+  subtask = Subtask NA
+
+[task "Subtask NA"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping NA (subtask NA)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : false,
+         "hasPass" : false,
+         "name" : "Subtask NA",
+         "status" : "INVALID"
+      }
+   ]
+}
+
+[root "Root READY (subtask PASS)"]
+  applicable = is:open
+  pass = NOT is:open
+  subtask = Subtask PASS
+  ready-hint = You must now run the ready task
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "hint" : "You must now run the ready task",
+   "name" : "Root READY (subtask PASS)",
+   "status" : "READY",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root WAITING (subtask READY)"]
+  applicable = is:open
+  pass = is:open
+  subtask = Subtask READY
+
+[task "Subtask READY"]
+  applicable = is:open
+  pass = NOT is:open
+  subtask = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root WAITING (subtask READY)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask READY",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root WAITING (subtask FAIL)"]
+  applicable = is:open
+  pass = is:open
+  subtask = Subtask FAIL
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root WAITING (subtask FAIL)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root IN PROGRESS"]
+   applicable = is:open
+   in-progress = is:open
+   pass = NOT is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "inProgress" : true,
+   "name" : "Root IN PROGRESS",
+   "status" : "READY"
+}
+
+[root "Root NOT IN PROGRESS"]
+   applicable = is:open
+   in-progress = NOT is:open
+   pass = NOT is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "inProgress" : false,
+   "name" : "Root NOT IN PROGRESS",
+   "status" : "READY"
+}
+
+[root "Root OPTIONAL MISSING"]
+   subtask = OPTIONAL MISSING |
+   pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root OPTIONAL MISSING",
+   "status" : "PASS"
+}
+
+[root "Root Optional subtask EXISTS"]
+   subtask = Subtask Optional EXISTS |
+
+[task "Subtask Optional EXISTS"]
+   subtask = Subtask PASS |
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask EXISTS",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional EXISTS",
+         "status" : "PASS",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Optional subtask MISSING then EXISTS"]
+   subtask = Subtask Optional MISSING then EXISTS |
+
+[task "Subtask Optional MISSING then EXISTS"]
+   subtask = OPTIONAL MISSING | Subtask FAIL
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask MISSING then EXISTS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional MISSING then EXISTS",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask FAIL",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Optional subtask MISSING then MISSING"]
+   subtask = Subtask Optional MISSING then MISSING |
+
+[task "Subtask Optional MISSING then MISSING"]
+   subtask = OPTIONAL MISSING | OPTIONAL MISSING |
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask MISSING then MISSING",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional MISSING then MISSING"
+      }
+   ]
+}
+
+[root "Root Optional subtask MISSING then MISSING then EXISTS"]
+   subtask = Subtask Optional MISSING then MISSING then EXISTS |
+
+[task "Subtask Optional MISSING then MISSING then EXISTS"]
+   subtask = OPTIONAL MISSING | OPTIONAL MISSING | Subtask READY
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask MISSING then MISSING then EXISTS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional MISSING then MISSING then EXISTS",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask READY",
+               "status" : "READY",
+               "subTasks" : [
+                  {
+                     "applicable" : true,
+                     "hasPass" : true,
+                     "name" : "Subtask PASS",
+                     "status" : "PASS"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+[root "Subtasks File"]
+  subtasks-file = common.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks File",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Subtasks File (Missing)"]
+  subtasks-file = common.config
+  subtasks-file = missing
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks File (Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Subtasks External"]
+  subtasks-external = user special
+
+[external "user special"]
+  user = testuser
+  file = special.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Subtasks External (Missing)"]
+  subtasks-external = user special
+  subtasks-external = missing
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External (Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      }
+   ]
+}
+
+[root "Subtasks External (User Missing)"]
+  subtasks-external = user special
+  subtasks-external = user missing
+
+[external "user missing"]
+  user = missing
+  file = special.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External (User Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      }
+   ]
+}
+
+[root "Subtasks External (File Missing)"]
+  subtasks-external = user special
+  subtasks-external = file missing
+
+[external "file missing"]
+  user = testuser
+  file = missing
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External (File Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root tasks-factory STATIC"]
+  subtasks-factory = tasks-factory static
+
+[tasks-factory "tasks-factory static"]
+  names-factory = names-factory static list
+  fail = True
+
+[names-factory "names-factory static list"]
+  type = static
+  name = my a task
+  name = my b task
+  name = my c task
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root tasks-factory STATIC",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "my a task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "my b task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "my c task",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root tasks-factory CHANGE"]
+  subtasks-factory = tasks-factory change
+
+[tasks-factory "tasks-factory change"]
+  names-factory = names-factory change list
+  fail = True
+
+[names-factory "names-factory change list"]
+  changes = change:_change1_number OR change:_change2_number
+  type = change
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root tasks-factory CHANGE",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change1_number",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change2_number",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root tasks-factory static (empty name)"]
+  subtasks-factory = tasks-factory static (empty name)
+  # Grouping task since it has no pass criteria, not output since it has no subtasks
+
+[tasks-factory "tasks-factory static (empty name)"]
+  names-factory = names-factory static (empty name list)
+  fail = True
+
+[names-factory "names-factory static (empty name list)"]
+  type = static
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root tasks-factory static (empty name)"
+}
+
+[root "Root tasks-factory static (empty name PASS)"]
+  pass = True
+  subtasks-factory = tasks-factory static (empty name)
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root tasks-factory static (empty name PASS)",
+   "status" : "PASS"
+}
+
+[root "Root Properties"]
+  set-root-property = root-value
+  subtask = Subtask Properties
+
+[task "Subtask Properties"]
+  subtask = Subtask Properties Hints
+
+[task "Subtask Properties Hints"]
+  set-first-property = first-value
+  set-second-property = ${first-property} second-extra ${third-property}
+  set-third-property = third-value
+  fail = True
+  fail-hint = root-property(${root-property}) first-property(${first-property}) second-property(${second-property})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Properties",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value)",
+               "name" : "Subtask Properties Hints",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+
+[root "Root Properties Reset By Subtask"]
+  set-root-to-reset-by-subtask = reset-my-root-value
+  subtask = Subtask Properties Reset
+
+[task "Subtask Properties Reset"]
+  fail = True
+  set-root-to-reset-by-subtask = reset-by-subtask-root-value
+  fail-hint = root-to-reset-by-subtask:(${root-to-reset-by-subtask})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties Reset By Subtask",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "root-to-reset-by-subtask:(reset-by-subtask-root-value)",
+         "name" : "Subtask Properties Reset",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties Exports"]
+  export-root-exported = ${_name}
+  subtask = Subtask Properties Exports
+  fail = True
+  fail-hint = root-exported(${root-exported})
+
+[task "Subtask Properties Exports"]
+  export-subtask-exported = ${_name}
+  fail = True
+  fail-hint = root-exported(${root-exported}) subtask-exported(${subtask-exported})
+
+{
+   "applicable" : true,
+   "exported" : {
+      "root-exported" : "Root Properties Exports"
+   },
+   "hasPass" : true,
+   "hint" : "root-exported(Root Properties Exports)",
+   "name" : "Root Properties Exports",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "exported" : {
+            "subtask-exported" : "Subtask Properties Exports"
+         },
+         "hasPass" : true,
+         "hint" : "root-exported(Root Properties Exports) subtask-exported(Subtask Properties Exports)",
+         "name" : "Subtask Properties Exports",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Internal Properties"]
+  export-root = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  set-root-internals = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  fail = True
+  fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  subtask = Subtask Internal Properties
+
+[task "Subtask Internal Properties"]
+  fail = True
+  fail-hint = root-internals(${root-internals}) Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+
+{
+   "applicable" : true,
+   "exported" : {
+      "root" : "Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)"
+   },
+   "hasPass" : true,
+   "hint" : "Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+   "name" : "Root Internal Properties",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "root-internals(Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)) Name(Subtask Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "Subtask Internal Properties",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Subtask Via Property"]
+  set-subtask = Subtask
+  subtask = ${subtask} Via Property
+
+[task "Subtask Via Property"]
+  subtask = Second ${_name}
+
+[task "Second Subtask Via Property"]
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Subtask Via Property",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Via Property",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Second Subtask Via Property",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Properties tasks-factory STATIC"]
+  subtasks-factory = tasks-factory STATIC Properties
+
+[tasks-factory "tasks-factory STATIC Properties"]
+  set-welcome-message = Welcome to the jungle
+  names-factory = names-factory static list
+  fail-hint = ${welcome-message} Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties tasks-factory STATIC",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the jungle Name(my a task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "my a task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the jungle Name(my b task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "my b task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the jungle Name(my c task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "my c task",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties tasks-factory CHANGE"]
+  subtasks-factory = tasks-factory CHANGE Properties
+
+[tasks-factory "tasks-factory CHANGE Properties"]
+  set-welcome-message = Welcome to the pleasuredome
+  names-factory = names-factory a change
+  fail-hint = ${welcome-message} Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  fail = True
+
+[names-factory "names-factory a change"]
+  type = change
+  changes = change:_change1_number OR change:_change2_number
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties tasks-factory CHANGE",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the pleasuredome Name(_change1_number) Change Number(_change1_number) Change Id(_change1_id) Change Project(_change1_project) Change Branch(_change1_branch) Change Status(_change1_status) Change Topic(_change1_topic)",
+         "name" : "_change1_number",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the pleasuredome Name(_change2_number) Change Number(_change2_number) Change Id(_change2_id) Change Project(_change2_project) Change Branch(_change2_branch) Change Status(_change2_status) Change Topic(_change2_topic)",
+         "name" : "_change2_number",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties names-factory STATIC"]
+  subtasks-factory = tasks-factory Properties names-factory STATIC
+
+[tasks-factory "tasks-factory Properties names-factory STATIC"]
+  names-factory = Properties names-factory STATIC
+  fail = True
+
+[names-factory "Properties names-factory STATIC"]
+  type = static
+  name = Change Number(${_change_number})
+  name = Change Id(${_change_id})
+  name = Change Project(${_change_project})
+  name = Change Branch(${_change_branch})
+  name = Change Status(${_change_status})
+  name = Change Topic(${_change_topic})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties names-factory STATIC",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Number(_change_number)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Id(_change_id)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Project(_change_project)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Branch(_change_branch)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Status(_change_status)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Topic(_change_topic)",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties names-factory CHANGE"]
+  subtasks-factory = tasks-factory Properties names-factory CHANGE
+
+[tasks-factory "tasks-factory Properties names-factory CHANGE"]
+  names-factory = Properties names-factory CHANGE
+  fail = True
+
+[names-factory "Properties names-factory CHANGE"]
+  type = change
+  changes = change:_change1_number OR change:${_change_number} project:${_change_project} branch:${_change_branch}
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties names-factory CHANGE",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change_number",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change1_number",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties Expansion"]
+  applicable = status:open
+  subtask = Subtask Property Expansion fail-hint
+
+[task "Subtask Property Expansion fail-hint"]
+  subtasks-factory = tasks-factory Property Expansion fail-hint
+
+[tasks-factory "tasks-factory Property Expansion fail-hint"]
+  set-first-property = first-property ${_name}
+  fail-hint = ${first-property}
+  fail = true
+  names-factory = names-factory static list
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties Expansion",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Property Expansion fail-hint",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "first-property my a task",
+               "name" : "my a task",
+               "status" : "FAIL"
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "first-property my b task",
+               "name" : "my b task",
+               "status" : "FAIL"
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "first-property my c task",
+               "name" : "my c task",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Preload"]
+   preload-task = Subtask FAIL
+   subtask = Subtask Preload
+
+[task "Subtask Preload"]
+  preload-task = Subtask READY
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root Preload",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Preload",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Preload Preload"]
+  subtask = Subtask Preload Preload
+
+[task "Subtask Preload Preload"]
+  preload-task = Subtask Preload with Preload
+
+[task "Subtask Preload with Preload"]
+  preload-task = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Preload",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Preload Preload",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root Preload Hints PASS"]
+  subtask = Subtask Preload Hints PASS
+
+[task "Subtask Preload Hints PASS"]
+  preload-task = Subtask Hints
+  pass = False
+
+[task "Subtask Hints"] # meant to be preloaded, not a test case in itself
+  ready-hint = Task is ready
+  fail-hint = Task failed
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Hints PASS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Task is ready",
+         "name" : "Subtask Preload Hints PASS",
+         "status" : "READY"
+      }
+   ]
+}
+
+[root "Root Preload Hints FAIL"]
+  subtask = Subtask Preload Hints FAIL
+
+[task "Subtask Preload Hints FAIL"]
+  preload-task = Subtask Hints
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Hints FAIL",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Task failed",
+         "name" : "Subtask Preload Hints FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Override Preload Pass"]
+  subtask = Subtask Override Preload Pass
+
+[task "Subtask Override Preload Pass"]
+  preload-task = Subtask PASS
+  pass = False
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Override Preload Pass",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Override Preload Pass",
+         "status" : "READY"
+      }
+   ]
+}
+
+[root "Root Override Preload Fail"]
+  subtask = Subtask Override Preload Fail
+
+[task "Subtask Override Preload Fail"]
+  preload-task = Subtask FAIL
+  fail = False
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Override Preload Fail",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Override Preload Fail",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root Append Preloaded Subtasks"]
+  subtask = Subtask Append Preloaded Subtasks
+
+[task "Subtask Append Preloaded Subtasks"]
+  preload-task = Subtask READY
+  subtask = Subtask APPLICABLE
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Append Preloaded Subtasks",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Append Preloaded Subtasks",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask APPLICABLE",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Preload Optional"]
+  subtask = Subtask Preload Optional
+[task "Subtask Preload Optional"]
+  preload-task = Missing | Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Optional",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Preload Optional",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root Preload Properties"]
+  subtask = Subtask Preload Properties
+
+[task "Subtask Preload Properties"]
+  preload-task = Subtask Properties Hints
+  set-fourth-property = fourth-value
+  fail-hint = second-property(${second-property}) fourth-property(${fourth-property})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Properties",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
+         "name" : "Subtask Preload Properties",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root INVALID Preload"]
+  preload-task = missing
+
+{
+   "name" : "UNKNOWN",
+   "status" : "INVALID"
+}
+
+[root "INVALIDS"]
+  subtasks-file = invalids.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "INVALIDS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root NA Pass"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  pass = True
+
+{
+   "applicable" : false,
+   "hasPass" : true,
+   "name" : "Root NA Pass",
+   "status" : "PASS"
+}
+
+[root "Root NA Fail"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  fail = True
+
+{
+   "applicable" : false,
+   "hasPass" : true,
+   "name" : "Root NA Fail",
+   "status" : "FAIL"
+}
+
+[root "NA INVALIDS"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  subtasks-file = invalids.config
+
+{
+   "applicable" : false,
+   "hasPass" : false,
+   "name" : "NA INVALIDS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+```
+
+`task/common.config` file in project `All-Projects` on ref `refs/meta/config`.
+
+```
+[task "file task/common.config PASS"]
+  applicable = is:open
+  pass = is:open
+
+[task "file task/common.config FAIL"]
+  applicable = is:open
+  fail = is:open
+```
+
+`task/invalids.config` file in project `All-Projects` on ref `refs/meta/config`.
+
+```
+[task "No PASS criteria"]
+  fail-hint = Invalid without Pass criteria and without subtasks
+
+[task "WAITING (subtask INVALID)"]
+  pass = is:open
+  subtask = Subtask INVALID
+
+[task "WAITING (subtask duplicate)"]
+  subtask = Subtask INVALID
+  subtask = Subtask INVALID
+
+[task "WAITING (subtask missing)"]
+  pass = is:open
+  subtask = MISSING # security bug: subtask name appears in output
+
+[task "Grouping WAITING (subtask INVALID)"]
+  subtask = Subtask INVALID
+
+[task "Grouping WAITING (subtask missing)"]
+  subtask = MISSING # security bug: subtask name appears in output
+
+[task "Subtask INVALID"]
+  fail-hint = Use when an INVALID subtask is needed, not meant as a test case in itself
+
+[task "Subtask Optional"]
+   subtask = MISSING | MISSING
+
+[task "NA Bad PASS query"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  fail = True
+  pass = has:bad
+
+[task "NA Bad FAIL query"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  pass = True
+  fail = has:bad
+
+[task "NA Bad INPROGRESS query"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  fail = True
+  in-progress = has:bad
+
+[task "Looping"]
+  subtask = Looping
+
+[task "Looping Properties"]
+  set-A = ${B}
+  set-B = ${A}
+  fail = True
+
+[task "task (tasks-factory missing)"]
+  subtasks-factory = missing
+
+[task "task (names-factory type missing)"]
+  subtasks-factory = tasks-factory (names-factory type missing)
+
+[task "task (names-factory type INVALID)"]
+  subtasks-factory = tasks-factory (names-factory type INVALID)
+
+[task "task (names-factory duplicate)"]
+  subtasks-factory = tasks-factory (names-factory duplicate)
+
+[task "task (names-factory changes type missing)"]
+  subtasks-factory = tasks-factory change (names-factory type missing)
+
+[task "task (names-factory changes missing)"]
+  subtasks-factory = tasks-factory change (names-factory changes missing)
+
+[task "task (names-factory changes invalid)"]
+  subtasks-factory = tasks-factory change (names-factory changes invalid)
+
+[task "task (tasks-factory changes loop)"]
+  subtasks-factory = tasks-factory change loop
+
+[tasks-factory "tasks-factory (names-factory type missing)"]
+  names-factory = names-factory (type missing)
+  fail = True
+
+[tasks-factory "tasks-factory (names-factory type INVALID)"]
+  names-factory = name-factory (type INVALID)
+
+[tasks-factory "tasks-factory (names-factory duplicate)"]
+  names-factory = names-factory duplicate
+  fail = True
+
+[tasks-factory "tasks-factory change (names-factory type missing)"]
+  names-factory = names-factory change list (type missing)
+  fail = True
+
+[tasks-factory "tasks-factory change (names-factory changes missing)"]
+  names-factory = names-factory change list (changes missing)
+  fail = True
+
+[tasks-factory "tasks-factory change (names-factory changes invalid)"]
+  names-factory = names-factory change list (changes invalid)
+  fail = True
+
+[tasks-factory "tasks-factory change loop"]
+  names-factory = names-factory change constant
+  subtask = task (tasks-factory changes loop)
+  fail = True
+
+[names-factory "names-factory (type missing)"]
+  name = no type test
+
+[names-factory "names-factory change list (type missing)"]
+  changes = change:_change1_number OR change:_change2_number
+
+[names-factory "names-factory (type INVALID)"]
+  name = invalid type test
+  type = invalid
+
+[names-factory "names-factory duplicate"]
+  name = duplicate
+  name = duplicate
+  type = static
+
+[names-factory "names-factory change list (changes missing)"]
+  type = change
+
+[names-factory "names-factory change list (changes invalid)"]
+  change = change:invalidChange
+  type = change
+
+[names-factory "names-factory change constant"]
+  changes = change:_change1_number OR change:_change2_number
+  type = change
+
+```
+
+`task/special.config` file in project `All-Users` on ref `refs/users/self`.
+
+```
+[task "userfile task/special.config PASS"]
+  applicable = is:open
+  pass = is:open
+
+[task "userfile task/special.config FAIL"]
+  applicable = is:open
+  fail = is:open
+```
diff --git a/test/all b/test/all
deleted file mode 100644
index 4832bba..0000000
--- a/test/all
+++ /dev/null
@@ -1,1134 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "Root N/A",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root APPLICABLE",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask APPLICABLE",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root straight PASS",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root straight FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS-fail",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root pass-FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS-waiting-fail",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root pass-WAITING-fail",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root pass-waiting-FAIL",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping PASS (subtask PASS)",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping NA (subtask NA)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : false,
-                     "hasPass" : false,
-                     "name" : "Subtask NA",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "hint" : "You must now run the ready task",
-               "name" : "Root READY (subtask PASS)",
-               "status" : "READY",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "inProgress" : true,
-               "name" : "Root IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "inProgress" : false,
-               "name" : "Root NOT IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root Optional subtasks",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask READY",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "applicable" : true,
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks File",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks File (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (File Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root tasks-factory",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my a task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my b task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my c task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my d task Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "_change1_number",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "_change2_number",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root tasks-factory static (empty name)"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root tasks-factory static (empty name PASS)",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "exported" : {
-                  "root" : "Root Properties"
-               },
-               "hasPass" : true,
-               "hint" : "Name(Root Properties) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-               "name" : "Root Properties",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "exported" : {
-                        "subtask" : "Subtask Properties"
-                     },
-                     "hasPass" : false,
-                     "name" : "Subtask Properties",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
-                           "name" : "Subtask Properties Hints",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Chained Subtask Properties",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Properties Reset",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Name(_change3_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change3_number",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Name(_change1_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change1_number",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root Preload",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask Preload",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Preload",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Task is ready",
-                           "name" : "Subtask Preload Hints PASS",
-                           "status" : "READY"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Task failed",
-                           "name" : "Subtask Preload Hints FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Pass",
-                           "status" : "READY"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Fail",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Extend Subtasks",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "applicable" : true,
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              },
-                              {
-                                 "applicable" : true,
-                                 "hasPass" : true,
-                                 "name" : "Subtask APPLICABLE",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Optional",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
-                           "name" : "Subtask Preload Properties",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : true,
-               "name" : "Root NA Pass",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : false,
-               "hasPass" : true,
-               "name" : "Root NA Fail",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/check_task_statuses.sh b/test/check_task_statuses.sh
index beff75a..5b7e161 100755
--- a/test/check_task_statuses.sh
+++ b/test/check_task_statuses.sh
@@ -1,4 +1,18 @@
-#!/bin/bash
+#!/usr/bin/env bash
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# 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.
 
 # Usage:
 # All-Projects.git - must have 'Push' rights on refs/meta/config
@@ -15,6 +29,120 @@
     fi
 }
 
+# output must match expected to pass
+result_out() { # test expected actual
+    local name=$1 expected=$2 actual=$3
+
+    [ "$expected" = "$actual" ]
+    result "$name" "$(diff <(echo "$expected") <(echo "$actual"))"
+}
+
+result_root() { # group root expected_file actual_file
+    local name="$1 - $(echo "$2" | sed -es'/Root //')"
+    result_out "$name" "$(get_root "$2" < "$3")" "$(get_root "$2" < "$4")"
+}
+
+# -------- Git Config
+
+config() { git config -f "$CONFIG" "$@" ; } # [args]...
+config_section_keys() { # section > keys ...
+    # handlers.handler-filter filter.sh -> handler-filter
+    config -l --name-only |\
+        grep "^$1\." | \
+        sed -es"/^$1\.//;s/\..*$//" |\
+        awk '$0 != prev ; {prev = $0}'
+}
+
+# -------- Pre JSON --------
+#
+# pre_json is a "templated json" used in the test docs to express test results. It looks
+# like json but has some extra comments to express when a certain output should be used.
+# These comments look like: "# Only Test Suite: <suite>"
+#
+
+remove_suite() { # suite < pre_json > json
+    grep -v "# Only Test Suite: $1" | \
+    sed -e's/# Only Test Suite:.*$//; s/ *$//'
+}
+
+remove_not_suite() { remove_suite !"$1" ; } # suite < pre_json > json
+
+# -------- Test Doc Format --------
+#
+# Test Doc Format has intermixed git config task definitions with json roots. This
+# makes it easy to define tests close to their outputs. Be aware that all of the
+# config will get consolidated into a single file, so non root config will be shared
+# amongst all the roots.
+#
+
+# Sample Test Doc for 2 roots:
+#
+# [root "Root PASS"]
+#   pass = True
+#
+# {
+#    "applicable" : true,
+#    "hasPass" : true,
+#    "name" : "Root PASS",
+#    "status" : "PASS"
+# }
+#
+# [root "Root FAIL"]
+#   fail = True
+#
+# {
+#    <other root>
+# }
+
+# Strip the json from Test Doc formatted text. For the sample above, the output would be:
+#
+# [root "Root PASS"]
+#   pass = True
+#
+# [root "Root FAIL"]
+#   fail = True
+# ...
+#
+testdoc_2_cfg() { awk '/^\{/,/^$/ { next } ; 1' ; } # testdoc_format > task_config
+
+# Strip the git config from Test Doc formatted text. For the sample above, the output would be:
+#
+# { "plugins" : [
+#     { "name" : "task",
+#       "roots" : [
+#         {
+#           "applicable" : true,
+#           "hasPass" : true,
+#           "name" : "Root PASS",
+#           "status" : "PASS"
+#        },
+#        {
+#           <other root>
+#        },
+#    ...
+# }
+testdoc_2_pjson() { # < testdoc_format > pjson_task_roots
+    awk 'BEGIN { print "{ \"plugins\" : [ { \"name\" : \"task\", \"roots\" : [" }; \
+         /^\{/  { open=1 }; \
+         open && end { print "}," ; end=0 }; \
+         /^\}/  { open=0 ; end=1 }; \
+         open; \
+         END   { print "}]}]}" }'
+}
+
+# ---- JSON PARSING ----
+
+json_pp() { # < json > json
+    python -c "import sys, json; \
+            print json.dumps(json.loads(sys.stdin.read()), indent=3, \
+            separators=(',', ' : '), sort_keys=True)"
+}
+
+json_val_by() { # json index|'key' > value
+    echo "$1" | python -c "import json,sys;print json.load(sys.stdin)[$2]"
+}
+json_val_by_key() { json_val_by "$1" "'$2'" ; }  # json key > value
+
 # --------
 gssh() { ssh -x -p "$PORT" "$SERVER" gerrit "$@" ; } # cmd [args]...
 
@@ -24,27 +152,55 @@
 
 commit_message() { printf "$1 \n\nChange-Id: $2" ; } # message change-id > commit_msg
 
+err() { echo "ERROR: $1" >&2 ; exit 1 ; }
+
 # Run a test setup command quietly, exit on failure
-q_setup() { # cmd [args...]
-  local out ; out=$("$@" 2>&1) || { echo "$out" ; exit ; }
+q_setup() { local out ; out=$("$@" 2>&1) || err "$out" ; } # cmd [args...]
+
+ensure() { "$@" || err "$1 results are not valid" ; } # cmd [args]... < data > data
+
+set_change() { # change_json
+    { CHANGE=("$(json_val_by_key "$1" number)" \
+        "$(json_val_by_key "$1" id)" \
+        "$(json_val_by_key "$1" project)" \
+        "refs/heads/$(json_val_by_key "$1" branch)" \
+        "$(json_val_by_key "$1" status)" \
+        "$(json_val_by_key "$1" topic)") ; } 2> /dev/null
 }
 
-replace_change_properties() { # file change_token change_number change_id project branch status topic
+# change_token change_number change_id project branch status topic < templated_txt > change_txt
+replace_change_properties() {
+    sed -e "s|_change$1_number|$2|g" \
+        -e "s|_change$1_id|$3|g" \
+        -e "s|_change$1_project|$4|g" \
+        -e "s|_change$1_branch|$5|g" \
+        -e "s|_change$1_status|$6|g" \
+        -e "s|_change$1_topic|$7|g"
+}
 
-    sed -i -e "s/_change$2_number/$3/g" \
-              -e "s/_change$2_id/$4/g" \
-              -e "s/_change$2_project/$5/g" \
-              -e "s/_change$2_branch/$6/g" \
-              -e "s/_change$2_status/$7/g" \
-              -e "s/_change$2_topic/$8/g" "$1"
+replace_default_changes() {
+    replace_change_properties "1" "${CHANGE1[@]}" | replace_change_properties "2" "${CHANGE2[@]}"
 }
 
 replace_user() { # < text_with_testuser > text_with_$USER
     sed -e"s/testuser/$USER/"
 }
 
+strip_non_applicable() { ensure "$MYDIR"/strip_non_applicable.py ; } # < json > json
+strip_non_invalid() { ensure "$MYDIR"/strip_non_invalid.py ; } # < json > json
+
+get_root() { # root < task_plugin_ouptut > root_json
+    python -c "if True: # NOP to start indent
+        import sys, json
+
+        roots=json.loads(sys.stdin.read())['plugins'][0]['roots']
+        for root in roots:
+            if 'name' in root.keys() and root['name']=='$1':
+                print json.dumps(root, indent=3, separators=(',', ' : '), sort_keys=True)"
+}
+
 example() { # example_num
-    awk '/```/{Q++;E=(Q+1)/2};E=='"$1" < "$DOC_STATES" | grep -v '```' | replace_user
+    echo "$DOC_STATES" | awk '/```/{Q++;E=(Q+1)/2};E=='"$1" | grep -v '```' | replace_user
 }
 
 get_change_num() { # < gerrit_push_response > changenum
@@ -95,31 +251,42 @@
     )
 }
 
-query() { # query
-    gssh query "$@" \
-        --format json | head -1 | python -c "import sys, json; \
-        print json.dumps(json.loads(sys.stdin.read()), indent=3, \
-        separators=(',', ' : '), sort_keys=True)"
+query_plugins() { # query
+    gssh query "$@" --format json | head -1 | python -c "import sys, json; \
+        plugins={}; plugins['plugins']=json.loads(sys.stdin.read())['plugins']; \
+        print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)"
 }
 
-query_plugins() { query "$@" | awk '$0=="   \"plugins\" : [",$0=="   ],"' ; }
-
 test_tasks() { # name expected_file task_args...
     local name=$1 expected=$2 ; shift 2
-    local output=$STATUSES.$name
+    local output=$STATUSES.$name out root
 
     query_plugins "$@" > "$output"
-    out=$(diff "$expected" "$output")
-    result "$name" "$out"
+    echo "$ROOTS" | while read root ; do
+        result_root "$name" "$root" "$expected" "$output"
+    done
+    out=$(diff "$expected" "$output" | head -15)
+    [ -z "$out" ]
+    result "$name - Full Test Suite" "$out"
+}
+
+test_generated() { # name task_args...
+    local name=$1 ; shift
+    test_tasks "$name" "$EXPECTED.$name" "$@"
 }
 
 test_file() { # name task_args...
     local name=$1 ; shift
-    test_tasks "$name" "$MYDIR/$name" "$@"
+    local expected=$MYDIR/$name output=$STATUSES.$name
+
+    query "$@" | awk '$0=="   \"plugins\" : [",$0=="   ],"' > "$output"
+    out=$(diff "$expected" "$output")
+    result "$name" "$out"
 }
 
-MYDIR=$(dirname "$0")
-DOCS=$MYDIR/.././src/main/resources/Documentation
+readlink -f / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
+MYDIR=$(dirname -- "$(readlink -f -- "$0")")
+DOCS=$MYDIR/.././src/main/resources/Documentation/test
 OUT=$MYDIR/../target/tests
 
 ALL=$OUT/All-Projects
@@ -128,7 +295,7 @@
 USERS=$OUT/All-Users
 USER_TASKS=$USERS/task
 
-DOC_STATES=$DOCS/task_states.md
+DOC_PREVIEW=$DOCS/preview.md
 EXPECTED=$OUT/expected
 STATUSES=$OUT/statuses
 
@@ -151,54 +318,72 @@
 REF_ALL=refs/meta/config
 REF_USERS=refs/users/self
 
-RESULT=0
+CONFIG=$ROOT_CFG
 
-mkdir -p "$OUT"
+mkdir -p "$OUT" "$ALL_TASKS" "$USER_TASKS"
+
 q_setup setup_repo "$ALL" "$REMOTE_ALL" "$REF_ALL"
 q_setup setup_repo "$USERS" "$REMOTE_USERS" "$REF_USERS" --initial-commit
 q_setup setup_repo "$OUT/$PROJECT" "$REMOTE_TEST" "$BRANCH"
 
-mkdir -p "$ALL_TASKS" "$USER_TASKS"
+changes=$(gssh query "status:open limit:2" --format json)
+set_change "$(echo "$changes" | awk 'NR==1')" ; CHANGE1=("${CHANGE[@]}")
+set_change "$(echo "$changes" | awk 'NR==2')" ; CHANGE2=("${CHANGE[@]}")
+DOC_STATES=$(replace_default_changes < "$DOCS/task_states.md")
 
-CHANGES=($(gssh query "status:open limit:2" | grep 'number:' | awk '{print $2}'))
-replace_change_properties "$DOC_STATES" "1" "${CHANGES[0]}"
-replace_change_properties "$DOC_STATES" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/all" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/all" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/preview" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/preview" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/preview.invalid" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/preview.invalid" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/invalid" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/invalid" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/invalid-applicable" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/invalid-applicable" "2" "${CHANGES[1]}"
+example 2 | replace_user | testdoc_2_cfg > "$ROOT_CFG"
+example 3 > "$COMMON_CFG"
+example 4 > "$INVALIDS_CFG"
+example 5 > "$USER_SPECIAL_CFG"
 
-example 1 |sed -e"s/current-user/$USER/" > "$ROOT_CFG"
-example 2 > "$COMMON_CFG"
-example 3 > "$INVALIDS_CFG"
-example 4 > "$USER_SPECIAL_CFG"
+ROOTS=$(config_section_keys "root") || err "Invalid ROOTS"
 
 q_setup update_repo "$ALL" "$REMOTE_ALL" "$REF_ALL"
 q_setup update_repo "$USERS" "$REMOTE_USERS" "$REF_USERS"
 
-example 5 |tail -n +5| awk 'NR>1{print P};{P=$0}' > "$EXPECTED"
-
 change3_id=$(gen_change_id)
 change3_number=$(create_repo_change "$OUT/$PROJECT" "$REMOTE_TEST" "$BRANCH" "$change3_id")
-replace_change_properties "$EXPECTED" "3" "$change3_number" "$change3_id" "$PROJECT" "refs\/heads\/$BRANCH" "NEW" ""
-replace_change_properties "$MYDIR/all" "3" "$change3_number" "$change3_id" "$PROJECT" "refs\/heads\/$BRANCH" "NEW" ""
 
-query="change:$change3_number status:open"
-test_tasks statuses "$EXPECTED" --task--applicable "$query"
-test_file all --task--all "$query"
+all_pjson=$(example 2 | testdoc_2_pjson | \
+    replace_change_properties \
+        "" \
+        "$change3_number" \
+        "$change3_id" \
+        "$PROJECT" \
+        "refs\/heads\/$BRANCH" \
+        "NEW" \
+        "")
 
-replace_user < "$MYDIR"/root.change > "$ROOT_CFG"
+no_all_json=$(echo "$all_pjson" | remove_suite all)
+
+echo "$no_all_json" | strip_non_applicable | \
+    grep -v "\"applicable\" :" > "$EXPECTED".applicable
+
+echo "$all_pjson" | remove_not_suite all | ensure json_pp > "$EXPECTED".all
+
+echo "$no_all_json" | strip_non_invalid > "$EXPECTED".invalid
+
+strip_non_invalid < "$EXPECTED".applicable > "$EXPECTED".invalid-applicable
+
+
+preview_pjson=$(testdoc_2_pjson < "$DOC_PREVIEW" | replace_default_changes)
+echo "$preview_pjson" | remove_suite invalid | ensure json_pp > "$EXPECTED".preview
+echo "$preview_pjson" | remove_not_suite invalid | strip_non_invalid > "$EXPECTED".preview-invalid
+
+testdoc_2_cfg < "$DOC_PREVIEW" | replace_user > "$ROOT_CFG"
 cnum=$(create_repo_change "$ALL" "$REMOTE_ALL" "$REF_ALL")
-test_file preview --task--preview "$cnum,1" --task--all "$query"
-test_file preview.invalid --task--preview "$cnum,1" --task--invalid "$query"
+PREVIEW_ROOTS=$(config_section_keys "root")
 
-test_file invalid --task--invalid "$query"
-test_file invalid-applicable --task--applicable --task--invalid "$query"
 
+RESULT=0
+query="change:$change3_number status:open"
+test_generated applicable --task--applicable "$query"
+test_generated all --task--all "$query"
+
+test_generated invalid --task--invalid "$query"
+test_generated invalid-applicable --task--applicable --task--invalid "$query"
+
+ROOTS=$PREVIEW_ROOTS
+test_generated preview --task--preview "$cnum,1" --task--all "$query"
+test_generated preview-invalid --task--preview "$cnum,1" --task--invalid "$query"
 exit $RESULT
diff --git a/test/docker/run.sh b/test/docker/run.sh
index 9c1f5d9..a57780b 100755
--- a/test/docker/run.sh
+++ b/test/docker/run.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-readlink --canonicalize / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
+readlink -f / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
 MYDIR=$(dirname -- "$(readlink -f -- "$0")")
 ARTIFACTS=$MYDIR/gerrit/artifacts
 
@@ -85,8 +85,7 @@
     usage "$MISSING, did you forget --task-plugin-jar?"
 fi
 [ -n "$GERRIT_WAR" ] && cp -f "$GERRIT_WAR" "$ARTIFACTS/gerrit.war"
-progress "Building docker images" build_images
-run_task_plugin_tests ; RESULT=$?
-cleanup
-
-exit "$RESULT"
+( trap cleanup EXIT SIGTERM
+    progress "Building docker images" build_images
+    run_task_plugin_tests
+)
diff --git a/test/docker/run_tests/wait-for-it.sh b/test/docker/run_tests/wait-for-it.sh
index d7b6e3c..17436f2 100755
--- a/test/docker/run_tests/wait-for-it.sh
+++ b/test/docker/run_tests/wait-for-it.sh
@@ -2,7 +2,7 @@
 # https://github.com/vishnubob/wait-for-it/blob/master/wait-for-it.sh
 #   Use this script to test if a given TCP host/port are available
 
-cmdname=$(basename $0)
+cmdname=$(basename -- "$0")
 
 echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
 
diff --git a/test/invalid b/test/invalid
deleted file mode 100644
index 5b5bc32..0000000
--- a/test/invalid
+++ /dev/null
@@ -1,559 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "Root N/A",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping NA (subtask NA)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : false,
-                     "hasPass" : false,
-                     "name" : "Subtask NA",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/invalid-applicable b/test/invalid-applicable
deleted file mode 100644
index 369ac47..0000000
--- a/test/invalid-applicable
+++ /dev/null
@@ -1,244 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/preview b/test/preview
deleted file mode 100644
index 235eaca..0000000
--- a/test/preview
+++ /dev/null
@@ -1,570 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS Preview",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "hint" : "You must now run the ready task",
-               "name" : "Root READY (subtask PASS) Preview",
-               "status" : "READY",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS Preview",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : true,
-               "name" : "Root NA Pass Preview",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/preview.invalid b/test/preview.invalid
deleted file mode 100644
index 3f0c844..0000000
--- a/test/preview.invalid
+++ /dev/null
@@ -1,511 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/root.change b/test/root.change
deleted file mode 100644
index 99dea09..0000000
--- a/test/root.change
+++ /dev/null
@@ -1,30 +0,0 @@
-[root "INVALIDS Preview"]
-  subtasks-file = invalids.config
-
-[root "Root PASS Preview"]
-  pass = True
-
-[root "Root READY (subtask PASS) Preview"]
-  applicable = is:open
-  pass = NOT is:open
-  subtask = Subtask PASS Preview
-  ready-hint = You must now run the ready task
-
-[root "Subtasks External Preview"]
-  subtasks-external = user special Preview
-
-[root "Root NA Pass Preview"]
-  applicable = NOT is:open
-  pass = True
-
-[root "NA INVALIDS Preview"]
-  applicable = NOT is:open
-  subtasks-file = invalids.config
-
-[task "Subtask PASS Preview"]
-  applicable = is:open
-  pass = is:open
-
-[external "user special Preview"]
-  user = testuser
-  file = special.config
diff --git a/test/strip_non_applicable.py b/test/strip_non_applicable.py
new file mode 100755
index 0000000..1ff097a
--- /dev/null
+++ b/test/strip_non_applicable.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# 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.
+
+import sys
+import json
+
+APPLICABLE='applicable'
+HASPASS='hasPass'
+STATUS='status'
+SUBTASKS='subTasks'
+
+def del_non_applicable(tasks):
+    i=0
+    while i < len(tasks):
+        nexti = i + 1
+
+        task=tasks[i]
+        if APPLICABLE in task.keys() and task[APPLICABLE] == False:
+            del tasks[i]
+            nexti = i
+        else:
+            subtasks=[]
+            if SUBTASKS in task.keys():
+                subtasks=task[SUBTASKS]
+                del_non_applicable(subtasks)
+            if SUBTASKS in task.keys() and len(subtasks) == 0:
+                del task[SUBTASKS]
+            if not SUBTASKS in task.keys():
+                if HASPASS in task.keys() and task[HASPASS] == False:
+                    status=''
+                    if STATUS in task.keys():
+                        status = task[STATUS]
+                    if status != 'INVALID':
+                        del tasks[i]
+                        nexti = i
+
+        i = nexti
+
+plugins=json.loads(sys.stdin.read())
+roots=plugins['plugins'][0]['roots']
+del_non_applicable(roots)
+print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)
diff --git a/test/strip_non_invalid.py b/test/strip_non_invalid.py
new file mode 100755
index 0000000..dafae15
--- /dev/null
+++ b/test/strip_non_invalid.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# 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.
+
+import sys
+import json
+
+STATUS='status'
+SUBTASKS='subTasks'
+
+def keep_invalid(tasks):
+    i=0
+    while i < len(tasks):
+        nexti = i + 1
+
+        task=tasks[i]
+        if SUBTASKS in task.keys():
+            subtasks=task[SUBTASKS]
+            keep_invalid(subtasks)
+            if len(subtasks) == 0:
+                del task[SUBTASKS]
+
+        status=''
+        if STATUS in task.keys():
+            status = task[STATUS]
+        if status != 'INVALID' and not SUBTASKS in task.keys():
+            del tasks[i]
+            nexti = i
+
+        i = nexti
+
+plugins=json.loads(sys.stdin.read())
+roots=plugins['plugins'][0]['roots']
+keep_invalid(roots)
+print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)